/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
1
# Copyright (C) 2005 by Canonical Ltd
2
#   Authors: Robert Collins <robert.collins@canonical.com>
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
1442.1.20 by Robert Collins
add some documentation on options
18
"""Configuration that affects the behaviour of Bazaar.
19
20
Currently this configuration resides in ~/.bazaar/bazaar.conf
21
and ~/.bazaar/branches.conf, which is written to by bzr.
22
1461 by Robert Collins
Typo in config.py (Thanks Fabbione)
23
In bazaar.conf the following options may be set:
1442.1.20 by Robert Collins
add some documentation on options
24
[DEFAULT]
25
editor=name-of-program
26
email=Your Name <your@email.address>
27
check_signatures=require|ignore|check-available(default)
28
create_signatures=always|never|when-required(default)
1442.1.56 by Robert Collins
gpg_signing_command configuration item
29
gpg_signing_command=name-of-program
1442.1.20 by Robert Collins
add some documentation on options
30
31
in branches.conf, you specify the url of a branch and options for it.
32
Wildcards may be used - * and ? as normal in shell completion. Options
33
set in both bazaar.conf and branches.conf are overriden by the branches.conf
34
setting.
35
[/home/robertc/source]
36
recurse=False|True(default)
37
email= as above
38
check_signatures= as abive 
39
create_signatures= as above.
40
41
explanation of options
42
----------------------
43
editor - this option sets the pop up editor to use during commits.
44
email - this option sets the user id bzr will use when committing.
45
check_signatures - this option controls whether bzr will require good gpg
46
                   signatures, ignore them, or check them if they are 
47
                   present.
48
create_signatures - this option controls whether bzr will always create 
49
                    gpg signatures, never create them, or create them if the
50
                    branch is configured to require them.
1442.1.21 by Robert Collins
create signature_needed() call for commit to trigger creating signatures
51
                    NB: This option is planned, but not implemented yet.
1442.1.20 by Robert Collins
add some documentation on options
52
"""
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
53
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
54
from ConfigParser import ConfigParser
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
55
import os
1442.1.12 by Robert Collins
LocationConfig section retrieval falls into my lap
56
from fnmatch import fnmatch
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
57
import errno
58
import re
59
60
import bzrlib
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
61
import bzrlib.errors as errors
62
63
1442.1.14 by Robert Collins
Create a default signature checking policy of CHECK_IF_POSSIBLE
64
CHECK_IF_POSSIBLE=0
65
CHECK_ALWAYS=1
66
CHECK_NEVER=2
67
68
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
69
class Config(object):
70
    """A configuration policy - what username, editor, gpg needs etc."""
71
72
    def get_editor(self):
73
        """Get the users pop up editor."""
74
        raise NotImplementedError
75
1442.1.15 by Robert Collins
make getting the signature checking policy a template method
76
    def _get_signature_checking(self):
77
        """Template method to override signature checking policy."""
78
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
79
    def _get_user_option(self, option_name):
80
        """Template method to provide a user option."""
81
        return None
82
83
    def get_user_option(self, option_name):
84
        """Get a generic option - no special process, no default."""
85
        return self._get_user_option(option_name)
86
1442.1.56 by Robert Collins
gpg_signing_command configuration item
87
    def gpg_signing_command(self):
88
        """What program should be used to sign signatures?"""
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
89
        result = self._gpg_signing_command()
90
        if result is None:
91
            result = "gpg"
92
        return result
93
94
    def _gpg_signing_command(self):
95
        """See gpg_signing_command()."""
96
        return None
1442.1.56 by Robert Collins
gpg_signing_command configuration item
97
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
98
    def __init__(self):
99
        super(Config, self).__init__()
100
1472 by Robert Collins
post commit hook, first pass implementation
101
    def post_commit(self):
102
        """An ordered list of python functions to call.
103
104
        Each function takes branch, rev_id as parameters.
105
        """
106
        return self._post_commit()
107
108
    def _post_commit(self):
109
        """See Config.post_commit."""
110
        return None
111
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
112
    def user_email(self):
113
        """Return just the email component of a username."""
114
        e = self.username()
115
        m = re.search(r'[\w+.-]+@[\w+.-]+', e)
116
        if not m:
117
            raise BzrError("%r doesn't seem to contain "
118
                           "a reasonable email address" % e)
119
        return m.group(0)
120
121
    def username(self):
122
        """Return email-style username.
123
    
124
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
125
        
126
        $BZREMAIL can be set to override this, then
127
        the concrete policy type is checked, and finally
128
        $EMAIL is examinged.
129
        but if none is found, a reasonable default is (hopefully)
130
        created.
131
    
132
        TODO: Check it's reasonably well-formed.
133
        """
134
        v = os.environ.get('BZREMAIL')
135
        if v:
136
            return v.decode(bzrlib.user_encoding)
137
    
138
        v = self._get_user_id()
139
        if v:
140
            return v
141
        
142
        v = os.environ.get('EMAIL')
143
        if v:
144
            return v.decode(bzrlib.user_encoding)
145
146
        name, email = _auto_user_id()
147
        if name:
148
            return '%s <%s>' % (name, email)
149
        else:
150
            return email
151
1442.1.14 by Robert Collins
Create a default signature checking policy of CHECK_IF_POSSIBLE
152
    def signature_checking(self):
153
        """What is the current policy for signature checking?."""
1442.1.15 by Robert Collins
make getting the signature checking policy a template method
154
        policy = self._get_signature_checking()
155
        if policy is not None:
156
            return policy
1442.1.14 by Robert Collins
Create a default signature checking policy of CHECK_IF_POSSIBLE
157
        return CHECK_IF_POSSIBLE
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
158
1442.1.21 by Robert Collins
create signature_needed() call for commit to trigger creating signatures
159
    def signature_needed(self):
160
        """Is a signature needed when committing ?."""
161
        policy = self._get_signature_checking()
162
        if policy == CHECK_ALWAYS:
163
            return True
164
        return False
165
1442.1.15 by Robert Collins
make getting the signature checking policy a template method
166
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
167
class IniBasedConfig(Config):
168
    """A configuration policy that draws from ini files."""
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
169
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
170
    def _get_parser(self, file=None):
171
        if self._parser is not None:
172
            return self._parser
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
173
        parser = ConfigParser()
174
        if file is not None:
175
            parser.readfp(file)
176
        else:
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
177
            parser.read([self._get_filename()])
178
        self._parser = parser
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
179
        return parser
180
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
181
    def _get_section(self):
182
        """Override this to define the section used by the config."""
183
        return "DEFAULT"
184
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
185
    def _get_signature_checking(self):
186
        """See Config._get_signature_checking."""
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
187
        section = self._get_section()
188
        if section is None:
189
            return None
1442.1.21 by Robert Collins
create signature_needed() call for commit to trigger creating signatures
190
        if self._get_parser().has_option(section, 'check_signatures'):
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
191
            return self._string_to_signature_policy(
1442.1.21 by Robert Collins
create signature_needed() call for commit to trigger creating signatures
192
                self._get_parser().get(section, 'check_signatures'))
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
193
194
    def _get_user_id(self):
195
        """Get the user id from the 'email' key in the current section."""
196
        section = self._get_section()
197
        if section is not None:
198
            if self._get_parser().has_option(section, 'email'):
199
                return self._get_parser().get(section, 'email')
200
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
201
    def _get_user_option(self, option_name):
202
        """See Config._get_user_option."""
203
        section = self._get_section()
204
        if section is not None:
205
            if self._get_parser().has_option(section, option_name):
206
                return self._get_parser().get(section, option_name)
207
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
208
    def _gpg_signing_command(self):
1442.1.56 by Robert Collins
gpg_signing_command configuration item
209
        """See Config.gpg_signing_command."""
1472 by Robert Collins
post commit hook, first pass implementation
210
        return self._get_user_option('gpg_signing_command')
1442.1.56 by Robert Collins
gpg_signing_command configuration item
211
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
212
    def __init__(self, get_filename):
213
        super(IniBasedConfig, self).__init__()
214
        self._get_filename = get_filename
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
215
        self._parser = None
1472 by Robert Collins
post commit hook, first pass implementation
216
        
217
    def _post_commit(self):
218
        """See Config.post_commit."""
219
        return self._get_user_option('post_commit')
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
220
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
221
    def _string_to_signature_policy(self, signature_string):
222
        """Convert a string to a signing policy."""
1442.1.17 by Robert Collins
allow global overriding of signature policy to force checking, or (pointless but allowed) to set auto checking
223
        if signature_string.lower() == 'check-available':
224
            return CHECK_IF_POSSIBLE
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
225
        if signature_string.lower() == 'ignore':
226
            return CHECK_NEVER
1442.1.17 by Robert Collins
allow global overriding of signature policy to force checking, or (pointless but allowed) to set auto checking
227
        if signature_string.lower() == 'require':
228
            return CHECK_ALWAYS
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
229
        raise errors.BzrError("Invalid signatures policy '%s'"
230
                              % signature_string)
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
231
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
232
233
class GlobalConfig(IniBasedConfig):
234
    """The configuration that should be used for a specific location."""
235
236
    def get_editor(self):
237
        if self._get_parser().has_option(self._get_section(), 'editor'):
238
            return self._get_parser().get(self._get_section(), 'editor')
239
240
    def __init__(self):
241
        super(GlobalConfig, self).__init__(config_filename)
242
243
244
class LocationConfig(IniBasedConfig):
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
245
    """A configuration object that gives the policy for a location."""
246
247
    def __init__(self, location):
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
248
        super(LocationConfig, self).__init__(branches_config_filename)
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
249
        self._global_config = None
250
        self.location = location
251
252
    def _get_global_config(self):
253
        if self._global_config is None:
254
            self._global_config = GlobalConfig()
255
        return self._global_config
256
1442.1.9 by Robert Collins
exact section test passes
257
    def _get_section(self):
258
        """Get the section we should look in for config items.
259
260
        Returns None if none exists. 
261
        TODO: perhaps return a NullSection that thunks through to the 
262
              global config.
263
        """
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
264
        sections = self._get_parser().sections()
1442.1.12 by Robert Collins
LocationConfig section retrieval falls into my lap
265
        location_names = self.location.split('/')
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
266
        if self.location.endswith('/'):
267
            del location_names[-1]
1442.1.12 by Robert Collins
LocationConfig section retrieval falls into my lap
268
        matches=[]
1442.1.10 by Robert Collins
explicit over glob test passes
269
        for section in sections:
1442.1.12 by Robert Collins
LocationConfig section retrieval falls into my lap
270
            section_names = section.split('/')
271
            if section.endswith('/'):
272
                del section_names[-1]
273
            names = zip(location_names, section_names)
274
            matched = True
275
            for name in names:
276
                if not fnmatch(name[0], name[1]):
277
                    matched = False
278
                    break
279
            if not matched:
280
                continue
281
            # so, for the common prefix they matched.
282
            # if section is longer, no match.
283
            if len(section_names) > len(location_names):
284
                continue
285
            # if path is longer, and recurse is not true, no match
286
            if len(section_names) < len(location_names):
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
287
                if (self._get_parser().has_option(section, 'recurse')
288
                    and not self._get_parser().getboolean(section, 'recurse')):
1442.1.12 by Robert Collins
LocationConfig section retrieval falls into my lap
289
                    continue
290
            matches.append((len(section_names), section))
291
        if not len(matches):
292
            return None
293
        matches.sort(reverse=True)
294
        return matches[0][1]
1442.1.9 by Robert Collins
exact section test passes
295
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
296
    def _gpg_signing_command(self):
1442.1.56 by Robert Collins
gpg_signing_command configuration item
297
        """See Config.gpg_signing_command."""
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
298
        command = super(LocationConfig, self)._gpg_signing_command()
1442.1.56 by Robert Collins
gpg_signing_command configuration item
299
        if command is not None:
300
            return command
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
301
        return self._get_global_config()._gpg_signing_command()
1442.1.56 by Robert Collins
gpg_signing_command configuration item
302
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
303
    def _get_user_id(self):
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
304
        user_id = super(LocationConfig, self)._get_user_id()
305
        if user_id is not None:
306
            return user_id
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
307
        return self._get_global_config()._get_user_id()
308
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
309
    def _get_user_option(self, option_name):
310
        """See Config._get_user_option."""
311
        option_value = super(LocationConfig, 
312
                             self)._get_user_option(option_name)
313
        if option_value is not None:
314
            return option_value
315
        return self._get_global_config()._get_user_option(option_name)
316
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
317
    def _get_signature_checking(self):
318
        """See Config._get_signature_checking."""
319
        check = super(LocationConfig, self)._get_signature_checking()
320
        if check is not None:
321
            return check
322
        return self._get_global_config()._get_signature_checking()
323
1472 by Robert Collins
post commit hook, first pass implementation
324
    def _post_commit(self):
325
        """See Config.post_commit."""
326
        hook = self._get_user_option('post_commit')
327
        if hook is not None:
328
            return hook
329
        return self._get_global_config()._post_commit()
330
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
331
332
class BranchConfig(Config):
333
    """A configuration object giving the policy for a branch."""
334
335
    def _get_location_config(self):
336
        if self._location_config is None:
337
            self._location_config = LocationConfig(self.branch.base)
338
        return self._location_config
339
340
    def _get_user_id(self):
341
        """Return the full user id for the branch.
342
    
343
        e.g. "John Hacker <jhacker@foo.org>"
344
        This is looked up in the email controlfile for the branch.
345
        """
346
        try:
347
            return (self.branch.controlfile("email", "r") 
348
                    .read()
349
                    .decode(bzrlib.user_encoding)
350
                    .rstrip("\r\n"))
351
        except errors.NoSuchFile, e:
352
            pass
353
        
354
        return self._get_location_config()._get_user_id()
355
1442.1.19 by Robert Collins
BranchConfigs inherit signature_checking policy from their LocationConfig.
356
    def _get_signature_checking(self):
357
        """See Config._get_signature_checking."""
358
        return self._get_location_config()._get_signature_checking()
359
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
360
    def _get_user_option(self, option_name):
361
        """See Config._get_user_option."""
362
        return self._get_location_config()._get_user_option(option_name)
363
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
364
    def _gpg_signing_command(self):
1442.1.56 by Robert Collins
gpg_signing_command configuration item
365
        """See Config.gpg_signing_command."""
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
366
        return self._get_location_config()._gpg_signing_command()
1442.1.56 by Robert Collins
gpg_signing_command configuration item
367
        
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
368
    def __init__(self, branch):
369
        super(BranchConfig, self).__init__()
370
        self._location_config = None
371
        self.branch = branch
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
372
1472 by Robert Collins
post commit hook, first pass implementation
373
    def _post_commit(self):
374
        """See Config.post_commit."""
375
        return self._get_location_config()._post_commit()
376
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
377
378
def config_dir():
379
    """Return per-user configuration directory.
380
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
381
    By default this is ~/.bazaar/
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
382
    
383
    TODO: Global option --config-dir to override this.
384
    """
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
385
    return os.path.join(os.path.expanduser("~"), ".bazaar")
386
387
388
def config_filename():
389
    """Return per-user configuration ini file filename."""
390
    return os.path.join(config_dir(), 'bazaar.conf')
391
392
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
393
def branches_config_filename():
394
    """Return per-user configuration ini file filename."""
395
    return os.path.join(config_dir(), 'branches.conf')
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
396
397
398
def _auto_user_id():
399
    """Calculate automatic user identification.
400
401
    Returns (realname, email).
402
403
    Only used when none is set in the environment or the id file.
404
405
    This previously used the FQDN as the default domain, but that can
406
    be very slow on machines where DNS is broken.  So now we simply
407
    use the hostname.
408
    """
409
    import socket
410
411
    # XXX: Any good way to get real user name on win32?
412
413
    try:
414
        import pwd
415
        uid = os.getuid()
416
        w = pwd.getpwuid(uid)
417
        gecos = w.pw_gecos.decode(bzrlib.user_encoding)
418
        username = w.pw_name.decode(bzrlib.user_encoding)
419
        comma = gecos.find(',')
420
        if comma == -1:
421
            realname = gecos
422
        else:
423
            realname = gecos[:comma]
424
        if not realname:
425
            realname = username
426
427
    except ImportError:
428
        import getpass
429
        realname = username = getpass.getuser().decode(bzrlib.user_encoding)
430
431
    return realname, (username + '@' + socket.gethostname())
432
433
1185.16.52 by Martin Pool
- add extract_email_address
434
def extract_email_address(e):
435
    """Return just the address part of an email string.
436
    
437
    That is just the user@domain part, nothing else. 
438
    This part is required to contain only ascii characters.
439
    If it can't be extracted, raises an error.
440
    
441
    >>> extract_email_address('Jane Tester <jane@test.com>')
442
    "jane@test.com"
443
    """
444
    m = re.search(r'[\w+.-]+@[\w+.-]+', e)
445
    if not m:
446
        raise BzrError("%r doesn't seem to contain "
447
                       "a reasonable email address" % e)
448
    return m.group(0)