/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
1474 by Robert Collins
Merge from Aaron Bentley.
54
55
import errno
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
56
import os
1185.38.1 by John Arbash Meinel
Adding my win32 patch for moving the home directory.
57
import sys
1442.1.12 by Robert Collins
LocationConfig section retrieval falls into my lap
58
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.
59
import re
60
61
import bzrlib
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
62
import bzrlib.errors as errors
1474 by Robert Collins
Merge from Aaron Bentley.
63
import bzrlib.util.configobj.configobj as configobj
1185.35.11 by Aaron Bentley
Added support for branch nicks
64
from StringIO import StringIO
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
65
1442.1.14 by Robert Collins
Create a default signature checking policy of CHECK_IF_POSSIBLE
66
CHECK_IF_POSSIBLE=0
67
CHECK_ALWAYS=1
68
CHECK_NEVER=2
69
70
1474 by Robert Collins
Merge from Aaron Bentley.
71
class ConfigObj(configobj.ConfigObj):
72
73
    def get_bool(self, section, key):
74
        val = self[section][key].lower()
75
        if val in ('1', 'yes', 'true', 'on'):
76
            return True
77
        elif val in ('0', 'no', 'false', 'off'):
78
            return False
79
        else:
80
            raise ValueError("Value %r is not boolean" % val)
81
82
    def get_value(self, section, name):
83
        # Try [] for the old DEFAULT section.
84
        if section == "DEFAULT":
85
            try:
86
                return self[name]
87
            except KeyError:
88
                pass
89
        return self[section][name]
90
91
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
92
class Config(object):
93
    """A configuration policy - what username, editor, gpg needs etc."""
94
95
    def get_editor(self):
96
        """Get the users pop up editor."""
97
        raise NotImplementedError
98
1442.1.15 by Robert Collins
make getting the signature checking policy a template method
99
    def _get_signature_checking(self):
100
        """Template method to override signature checking policy."""
101
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
102
    def _get_user_option(self, option_name):
103
        """Template method to provide a user option."""
104
        return None
105
106
    def get_user_option(self, option_name):
107
        """Get a generic option - no special process, no default."""
108
        return self._get_user_option(option_name)
109
1442.1.56 by Robert Collins
gpg_signing_command configuration item
110
    def gpg_signing_command(self):
111
        """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.
112
        result = self._gpg_signing_command()
113
        if result is None:
114
            result = "gpg"
115
        return result
116
117
    def _gpg_signing_command(self):
118
        """See gpg_signing_command()."""
119
        return None
1442.1.56 by Robert Collins
gpg_signing_command configuration item
120
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
121
    def __init__(self):
122
        super(Config, self).__init__()
123
1472 by Robert Collins
post commit hook, first pass implementation
124
    def post_commit(self):
125
        """An ordered list of python functions to call.
126
127
        Each function takes branch, rev_id as parameters.
128
        """
129
        return self._post_commit()
130
131
    def _post_commit(self):
132
        """See Config.post_commit."""
133
        return None
134
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
135
    def user_email(self):
136
        """Return just the email component of a username."""
1185.33.31 by Martin Pool
Make annotate cope better with revisions committed without a valid
137
        return extract_email_address(self.username())
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
138
139
    def username(self):
140
        """Return email-style username.
141
    
142
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
143
        
144
        $BZREMAIL can be set to override this, then
145
        the concrete policy type is checked, and finally
1185.37.2 by Jamie Wilkinson
Fix a typo and grammar in Config.username() docstring.
146
        $EMAIL is examined.
147
        If none is found, a reasonable default is (hopefully)
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
148
        created.
149
    
150
        TODO: Check it's reasonably well-formed.
151
        """
152
        v = os.environ.get('BZREMAIL')
153
        if v:
154
            return v.decode(bzrlib.user_encoding)
155
    
156
        v = self._get_user_id()
157
        if v:
158
            return v
159
        
160
        v = os.environ.get('EMAIL')
161
        if v:
162
            return v.decode(bzrlib.user_encoding)
163
164
        name, email = _auto_user_id()
165
        if name:
166
            return '%s <%s>' % (name, email)
167
        else:
168
            return email
169
1442.1.14 by Robert Collins
Create a default signature checking policy of CHECK_IF_POSSIBLE
170
    def signature_checking(self):
171
        """What is the current policy for signature checking?."""
1442.1.15 by Robert Collins
make getting the signature checking policy a template method
172
        policy = self._get_signature_checking()
173
        if policy is not None:
174
            return policy
1442.1.14 by Robert Collins
Create a default signature checking policy of CHECK_IF_POSSIBLE
175
        return CHECK_IF_POSSIBLE
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
176
1442.1.21 by Robert Collins
create signature_needed() call for commit to trigger creating signatures
177
    def signature_needed(self):
178
        """Is a signature needed when committing ?."""
179
        policy = self._get_signature_checking()
180
        if policy == CHECK_ALWAYS:
181
            return True
182
        return False
183
1442.1.15 by Robert Collins
make getting the signature checking policy a template method
184
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
185
class IniBasedConfig(Config):
186
    """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
187
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
188
    def _get_parser(self, file=None):
1185.12.51 by Aaron Bentley
Allowed second call of _get_parser() to not require a file
189
        if self._parser is not None:
190
            return self._parser
1185.12.49 by Aaron Bentley
Switched to ConfigObj
191
        if file is None:
192
            input = self._get_filename()
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
193
        else:
1185.12.49 by Aaron Bentley
Switched to ConfigObj
194
            input = file
1185.12.51 by Aaron Bentley
Allowed second call of _get_parser() to not require a file
195
        try:
196
            self._parser = ConfigObj(input)
1474 by Robert Collins
Merge from Aaron Bentley.
197
        except configobj.ConfigObjError, e:
1185.12.51 by Aaron Bentley
Allowed second call of _get_parser() to not require a file
198
            raise errors.ParseConfigError(e.errors, e.config.filename)
1185.12.49 by Aaron Bentley
Switched to ConfigObj
199
        return self._parser
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
200
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
201
    def _get_section(self):
202
        """Override this to define the section used by the config."""
203
        return "DEFAULT"
204
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
205
    def _get_signature_checking(self):
206
        """See Config._get_signature_checking."""
1474 by Robert Collins
Merge from Aaron Bentley.
207
        policy = self._get_user_option('check_signatures')
208
        if policy:
209
            return self._string_to_signature_policy(policy)
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
210
211
    def _get_user_id(self):
212
        """Get the user id from the 'email' key in the current section."""
1474 by Robert Collins
Merge from Aaron Bentley.
213
        return self._get_user_option('email')
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
214
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
215
    def _get_user_option(self, option_name):
216
        """See Config._get_user_option."""
1185.12.53 by Aaron Bentley
Merged more from Robert
217
        try:
1474 by Robert Collins
Merge from Aaron Bentley.
218
            return self._get_parser().get_value(self._get_section(),
219
                                                option_name)
1185.12.53 by Aaron Bentley
Merged more from Robert
220
        except KeyError:
221
            pass
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
222
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
223
    def _gpg_signing_command(self):
1442.1.56 by Robert Collins
gpg_signing_command configuration item
224
        """See Config.gpg_signing_command."""
1472 by Robert Collins
post commit hook, first pass implementation
225
        return self._get_user_option('gpg_signing_command')
1442.1.56 by Robert Collins
gpg_signing_command configuration item
226
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
227
    def __init__(self, get_filename):
228
        super(IniBasedConfig, self).__init__()
229
        self._get_filename = get_filename
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
230
        self._parser = None
1472 by Robert Collins
post commit hook, first pass implementation
231
        
232
    def _post_commit(self):
233
        """See Config.post_commit."""
234
        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
235
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
236
    def _string_to_signature_policy(self, signature_string):
237
        """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
238
        if signature_string.lower() == 'check-available':
239
            return CHECK_IF_POSSIBLE
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
240
        if signature_string.lower() == 'ignore':
241
            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
242
        if signature_string.lower() == 'require':
243
            return CHECK_ALWAYS
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
244
        raise errors.BzrError("Invalid signatures policy '%s'"
245
                              % signature_string)
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
246
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
247
248
class GlobalConfig(IniBasedConfig):
249
    """The configuration that should be used for a specific location."""
250
251
    def get_editor(self):
1474 by Robert Collins
Merge from Aaron Bentley.
252
        return self._get_user_option('editor')
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
253
254
    def __init__(self):
255
        super(GlobalConfig, self).__init__(config_filename)
256
257
258
class LocationConfig(IniBasedConfig):
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
259
    """A configuration object that gives the policy for a location."""
260
261
    def __init__(self, location):
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
262
        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
263
        self._global_config = None
264
        self.location = location
265
266
    def _get_global_config(self):
267
        if self._global_config is None:
268
            self._global_config = GlobalConfig()
269
        return self._global_config
270
1442.1.9 by Robert Collins
exact section test passes
271
    def _get_section(self):
272
        """Get the section we should look in for config items.
273
274
        Returns None if none exists. 
275
        TODO: perhaps return a NullSection that thunks through to the 
276
              global config.
277
        """
1185.12.49 by Aaron Bentley
Switched to ConfigObj
278
        sections = self._get_parser()
1442.1.12 by Robert Collins
LocationConfig section retrieval falls into my lap
279
        location_names = self.location.split('/')
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
280
        if self.location.endswith('/'):
281
            del location_names[-1]
1442.1.12 by Robert Collins
LocationConfig section retrieval falls into my lap
282
        matches=[]
1442.1.10 by Robert Collins
explicit over glob test passes
283
        for section in sections:
1442.1.12 by Robert Collins
LocationConfig section retrieval falls into my lap
284
            section_names = section.split('/')
285
            if section.endswith('/'):
286
                del section_names[-1]
287
            names = zip(location_names, section_names)
288
            matched = True
289
            for name in names:
290
                if not fnmatch(name[0], name[1]):
291
                    matched = False
292
                    break
293
            if not matched:
294
                continue
295
            # so, for the common prefix they matched.
296
            # if section is longer, no match.
297
            if len(section_names) > len(location_names):
298
                continue
299
            # if path is longer, and recurse is not true, no match
300
            if len(section_names) < len(location_names):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
301
                try:
1474 by Robert Collins
Merge from Aaron Bentley.
302
                    if not self._get_parser().get_bool(section, 'recurse'):
1185.12.49 by Aaron Bentley
Switched to ConfigObj
303
                        continue
304
                except KeyError:
305
                    pass
1442.1.12 by Robert Collins
LocationConfig section retrieval falls into my lap
306
            matches.append((len(section_names), section))
307
        if not len(matches):
308
            return None
309
        matches.sort(reverse=True)
310
        return matches[0][1]
1442.1.9 by Robert Collins
exact section test passes
311
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
312
    def _gpg_signing_command(self):
1442.1.56 by Robert Collins
gpg_signing_command configuration item
313
        """See Config.gpg_signing_command."""
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
314
        command = super(LocationConfig, self)._gpg_signing_command()
1442.1.56 by Robert Collins
gpg_signing_command configuration item
315
        if command is not None:
316
            return command
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
317
        return self._get_global_config()._gpg_signing_command()
1442.1.56 by Robert Collins
gpg_signing_command configuration item
318
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
319
    def _get_user_id(self):
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
320
        user_id = super(LocationConfig, self)._get_user_id()
321
        if user_id is not None:
322
            return user_id
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
323
        return self._get_global_config()._get_user_id()
324
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
325
    def _get_user_option(self, option_name):
326
        """See Config._get_user_option."""
327
        option_value = super(LocationConfig, 
328
                             self)._get_user_option(option_name)
329
        if option_value is not None:
330
            return option_value
331
        return self._get_global_config()._get_user_option(option_name)
332
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
333
    def _get_signature_checking(self):
334
        """See Config._get_signature_checking."""
335
        check = super(LocationConfig, self)._get_signature_checking()
336
        if check is not None:
337
            return check
338
        return self._get_global_config()._get_signature_checking()
339
1472 by Robert Collins
post commit hook, first pass implementation
340
    def _post_commit(self):
341
        """See Config.post_commit."""
342
        hook = self._get_user_option('post_commit')
343
        if hook is not None:
344
            return hook
345
        return self._get_global_config()._post_commit()
346
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
347
    def set_user_option(self, option, value):
348
        """Save option and its value in the configuration."""
349
        # FIXME: RBC 20051029 This should refresh the parser and also take a
350
        # file lock on branches.conf.
351
        if not os.path.isdir(os.path.dirname(self._get_filename())):
352
            os.mkdir(os.path.dirname(self._get_filename()))
353
        location = self.location
354
        if location.endswith('/'):
355
            location = location[:-1]
356
        if (not location in self._get_parser() and
357
            not location + '/' in self._get_parser()):
358
            self._get_parser()[location]={}
359
        elif location + '/' in self._get_parser():
360
            location = location + '/'
361
        self._get_parser()[location][option]=value
362
        self._get_parser().write()
363
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
364
365
class BranchConfig(Config):
366
    """A configuration object giving the policy for a branch."""
367
368
    def _get_location_config(self):
369
        if self._location_config is None:
370
            self._location_config = LocationConfig(self.branch.base)
371
        return self._location_config
372
373
    def _get_user_id(self):
374
        """Return the full user id for the branch.
375
    
376
        e.g. "John Hacker <jhacker@foo.org>"
377
        This is looked up in the email controlfile for the branch.
378
        """
379
        try:
380
            return (self.branch.controlfile("email", "r") 
381
                    .read()
382
                    .decode(bzrlib.user_encoding)
383
                    .rstrip("\r\n"))
384
        except errors.NoSuchFile, e:
385
            pass
386
        
387
        return self._get_location_config()._get_user_id()
388
1442.1.19 by Robert Collins
BranchConfigs inherit signature_checking policy from their LocationConfig.
389
    def _get_signature_checking(self):
390
        """See Config._get_signature_checking."""
391
        return self._get_location_config()._get_signature_checking()
392
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
393
    def _get_user_option(self, option_name):
394
        """See Config._get_user_option."""
395
        return self._get_location_config()._get_user_option(option_name)
396
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
397
    def _gpg_signing_command(self):
1442.1.56 by Robert Collins
gpg_signing_command configuration item
398
        """See Config.gpg_signing_command."""
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
399
        return self._get_location_config()._gpg_signing_command()
1442.1.56 by Robert Collins
gpg_signing_command configuration item
400
        
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
401
    def __init__(self, branch):
402
        super(BranchConfig, self).__init__()
403
        self._location_config = None
404
        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.
405
1472 by Robert Collins
post commit hook, first pass implementation
406
    def _post_commit(self):
407
        """See Config.post_commit."""
408
        return self._get_location_config()._post_commit()
409
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
410
411
def config_dir():
412
    """Return per-user configuration directory.
413
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
414
    By default this is ~/.bazaar/
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
415
    
416
    TODO: Global option --config-dir to override this.
417
    """
1185.38.1 by John Arbash Meinel
Adding my win32 patch for moving the home directory.
418
    base = os.environ.get('BZR_HOME', None)
419
    if sys.platform == 'win32':
420
        if base is None:
421
            base = os.environ.get('APPDATA', None)
422
        if base is None:
423
            base = os.environ.get('HOME', None)
424
        if base is None:
425
            raise BzrError('You must have one of BZR_HOME, APPDATA, or HOME set')
426
        return os.path.join(base, 'bazaar', '2.0')
427
    else:
428
        # cygwin, linux, and darwin all have a $HOME directory
429
        if base is None:
430
            base = os.path.expanduser("~")
431
        return os.path.join(base, ".bazaar")
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
432
433
434
def config_filename():
435
    """Return per-user configuration ini file filename."""
436
    return os.path.join(config_dir(), 'bazaar.conf')
437
438
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
439
def branches_config_filename():
440
    """Return per-user configuration ini file filename."""
441
    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.
442
443
444
def _auto_user_id():
445
    """Calculate automatic user identification.
446
447
    Returns (realname, email).
448
449
    Only used when none is set in the environment or the id file.
450
451
    This previously used the FQDN as the default domain, but that can
452
    be very slow on machines where DNS is broken.  So now we simply
453
    use the hostname.
454
    """
455
    import socket
456
457
    # XXX: Any good way to get real user name on win32?
458
459
    try:
460
        import pwd
461
        uid = os.getuid()
462
        w = pwd.getpwuid(uid)
463
        gecos = w.pw_gecos.decode(bzrlib.user_encoding)
464
        username = w.pw_name.decode(bzrlib.user_encoding)
465
        comma = gecos.find(',')
466
        if comma == -1:
467
            realname = gecos
468
        else:
469
            realname = gecos[:comma]
470
        if not realname:
471
            realname = username
472
473
    except ImportError:
474
        import getpass
475
        realname = username = getpass.getuser().decode(bzrlib.user_encoding)
476
477
    return realname, (username + '@' + socket.gethostname())
478
479
1185.16.52 by Martin Pool
- add extract_email_address
480
def extract_email_address(e):
481
    """Return just the address part of an email string.
482
    
483
    That is just the user@domain part, nothing else. 
484
    This part is required to contain only ascii characters.
485
    If it can't be extracted, raises an error.
486
    
487
    >>> extract_email_address('Jane Tester <jane@test.com>')
488
    "jane@test.com"
489
    """
490
    m = re.search(r'[\w+.-]+@[\w+.-]+', e)
491
    if not m:
1185.33.31 by Martin Pool
Make annotate cope better with revisions committed without a valid
492
        raise errors.BzrError("%r doesn't seem to contain "
493
                              "a reasonable email address" % e)
1185.16.52 by Martin Pool
- add extract_email_address
494
    return m.group(0)
1185.35.11 by Aaron Bentley
Added support for branch nicks
495
496
class TreeConfig(object):
497
    """Branch configuration data associated with its contents, not location"""
498
    def __init__(self, branch):
499
        self.branch = branch
500
501
    def _get_config(self):
502
        try:
1185.35.12 by Aaron Bentley
Got writes of existing tree configs working.
503
            obj = ConfigObj(self.branch.controlfile('branch.conf',
504
                                                    'rb').readlines())
1185.35.27 by Aaron Bentley
Got unicode nicks working properly, even when gannotate is installed.
505
            obj.decode('UTF-8')
1185.35.11 by Aaron Bentley
Added support for branch nicks
506
        except errors.NoSuchFile:
507
            obj = ConfigObj()
508
        return obj
509
510
    def get_option(self, name, section=None, default=None):
511
        self.branch.lock_read()
512
        try:
513
            obj = self._get_config()
514
            try:
515
                if section is not None:
516
                    obj[section]
517
                result = obj[name]
518
            except KeyError:
519
                result = default
520
        finally:
521
            self.branch.unlock()
522
        return result
523
524
    def set_option(self, value, name, section=None):
525
        """Set a per-branch configuration option"""
526
        self.branch.lock_write()
527
        try:
528
            cfg_obj = self._get_config()
529
            if section is None:
530
                obj = cfg_obj
531
            else:
532
                try:
533
                    obj = cfg_obj[section]
534
                except KeyError:
535
                    cfg_obj[section] = {}
536
                    obj = cfg_obj[section]
537
            obj[name] = value
1185.35.27 by Aaron Bentley
Got unicode nicks working properly, even when gannotate is installed.
538
            cfg_obj.encode('UTF-8')
1185.35.11 by Aaron Bentley
Added support for branch nicks
539
            out_file = StringIO(''.join([l+'\n' for l in cfg_obj.write()]))
540
            out_file.seek(0)
1185.35.27 by Aaron Bentley
Got unicode nicks working properly, even when gannotate is installed.
541
            self.branch.put_controlfile('branch.conf', out_file, encode=False)
1185.35.11 by Aaron Bentley
Added support for branch nicks
542
        finally:
543
            self.branch.unlock()