15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
"""Configuration that affects the behaviour of Bazaar."""
18
"""Configuration that affects the behaviour of Bazaar.
20
Currently this configuration resides in ~/.bazaar/bazaar.conf
21
and ~/.bazaar/branches.conf, which is written to by bzr.
23
In bazaar.config the following options may be set:
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)
30
in branches.conf, you specify the url of a branch and options for it.
31
Wildcards may be used - * and ? as normal in shell completion. Options
32
set in both bazaar.conf and branches.conf are overriden by the branches.conf
34
[/home/robertc/source]
35
recurse=False|True(default)
37
check_signatures= as abive
38
create_signatures= as above.
40
explanation of options
41
----------------------
42
editor - this option sets the pop up editor to use during commits.
43
email - this option sets the user id bzr will use when committing.
44
check_signatures - this option controls whether bzr will require good gpg
45
signatures, ignore them, or check them if they are
47
create_signatures - this option controls whether bzr will always create
48
gpg signatures, never create them, or create them if the
49
branch is configured to require them.
50
NB: This option is planned, but not implemented yet.
20
53
from ConfigParser import ConfigParser
55
from fnmatch import fnmatch
60
import bzrlib.errors as errors
69
"""A configuration policy - what username, editor, gpg needs etc."""
72
"""Get the users pop up editor."""
73
raise NotImplementedError
75
def _get_signature_checking(self):
76
"""Template method to override signature checking policy."""
79
super(Config, self).__init__()
82
"""Return just the email component of a username."""
84
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
86
raise BzrError("%r doesn't seem to contain "
87
"a reasonable email address" % e)
91
"""Return email-style username.
93
Something similar to 'Martin Pool <mbp@sourcefrog.net>'
95
$BZREMAIL can be set to override this, then
96
the concrete policy type is checked, and finally
98
but if none is found, a reasonable default is (hopefully)
101
TODO: Check it's reasonably well-formed.
103
v = os.environ.get('BZREMAIL')
105
return v.decode(bzrlib.user_encoding)
107
v = self._get_user_id()
111
v = os.environ.get('EMAIL')
113
return v.decode(bzrlib.user_encoding)
115
name, email = _auto_user_id()
117
return '%s <%s>' % (name, email)
121
def signature_checking(self):
122
"""What is the current policy for signature checking?."""
123
policy = self._get_signature_checking()
124
if policy is not None:
126
return CHECK_IF_POSSIBLE
128
def signature_needed(self):
129
"""Is a signature needed when committing ?."""
130
policy = self._get_signature_checking()
131
if policy == CHECK_ALWAYS:
136
class IniBasedConfig(Config):
137
"""A configuration policy that draws from ini files."""
139
def _get_parser(self, file=None):
140
if self._parser is not None:
142
parser = ConfigParser()
146
parser.read([self._get_filename()])
147
self._parser = parser
150
def _get_section(self):
151
"""Override this to define the section used by the config."""
154
def _get_signature_checking(self):
155
"""See Config._get_signature_checking."""
156
section = self._get_section()
159
if self._get_parser().has_option(section, 'check_signatures'):
160
return self._string_to_signature_policy(
161
self._get_parser().get(section, 'check_signatures'))
163
def _get_user_id(self):
164
"""Get the user id from the 'email' key in the current section."""
165
section = self._get_section()
166
if section is not None:
167
if self._get_parser().has_option(section, 'email'):
168
return self._get_parser().get(section, 'email')
170
def __init__(self, get_filename):
171
super(IniBasedConfig, self).__init__()
172
self._get_filename = get_filename
175
def _string_to_signature_policy(self, signature_string):
176
"""Convert a string to a signing policy."""
177
if signature_string.lower() == 'check-available':
178
return CHECK_IF_POSSIBLE
179
if signature_string.lower() == 'ignore':
181
if signature_string.lower() == 'require':
183
raise errors.BzrError("Invalid signatures policy '%s'"
187
class GlobalConfig(IniBasedConfig):
188
"""The configuration that should be used for a specific location."""
190
def get_editor(self):
191
if self._get_parser().has_option(self._get_section(), 'editor'):
192
return self._get_parser().get(self._get_section(), 'editor')
195
super(GlobalConfig, self).__init__(config_filename)
198
class LocationConfig(IniBasedConfig):
199
"""A configuration object that gives the policy for a location."""
201
def __init__(self, location):
202
super(LocationConfig, self).__init__(branches_config_filename)
203
self._global_config = None
204
self.location = location
206
def _get_global_config(self):
207
if self._global_config is None:
208
self._global_config = GlobalConfig()
209
return self._global_config
211
def _get_section(self):
212
"""Get the section we should look in for config items.
214
Returns None if none exists.
215
TODO: perhaps return a NullSection that thunks through to the
218
sections = self._get_parser().sections()
219
location_names = self.location.split('/')
220
if self.location.endswith('/'):
221
del location_names[-1]
223
for section in sections:
224
section_names = section.split('/')
225
if section.endswith('/'):
226
del section_names[-1]
227
names = zip(location_names, section_names)
230
if not fnmatch(name[0], name[1]):
235
# so, for the common prefix they matched.
236
# if section is longer, no match.
237
if len(section_names) > len(location_names):
239
# if path is longer, and recurse is not true, no match
240
if len(section_names) < len(location_names):
241
if (self._get_parser().has_option(section, 'recurse')
242
and not self._get_parser().getboolean(section, 'recurse')):
244
matches.append((len(section_names), section))
247
matches.sort(reverse=True)
250
def _get_user_id(self):
251
user_id = super(LocationConfig, self)._get_user_id()
252
if user_id is not None:
254
return self._get_global_config()._get_user_id()
256
def _get_signature_checking(self):
257
"""See Config._get_signature_checking."""
258
check = super(LocationConfig, self)._get_signature_checking()
259
if check is not None:
261
return self._get_global_config()._get_signature_checking()
264
class BranchConfig(Config):
265
"""A configuration object giving the policy for a branch."""
267
def _get_location_config(self):
268
if self._location_config is None:
269
self._location_config = LocationConfig(self.branch.base)
270
return self._location_config
272
def _get_user_id(self):
273
"""Return the full user id for the branch.
275
e.g. "John Hacker <jhacker@foo.org>"
276
This is looked up in the email controlfile for the branch.
279
return (self.branch.controlfile("email", "r")
281
.decode(bzrlib.user_encoding)
283
except errors.NoSuchFile, e:
286
return self._get_location_config()._get_user_id()
288
def _get_signature_checking(self):
289
"""See Config._get_signature_checking."""
290
return self._get_location_config()._get_signature_checking()
292
def __init__(self, branch):
293
super(BranchConfig, self).__init__()
294
self._location_config = None
40
310
return os.path.join(config_dir(), 'bazaar.conf')
43
def _get_config_parser(file=None):
44
parser = ConfigParser()
48
parser.read([config_filename()])
52
def get_editor(parser=None):
54
parser = _get_config_parser()
55
if parser.has_option('DEFAULT', 'editor'):
56
return parser.get('DEFAULT', 'editor')
59
def _get_user_id(branch=None, parser = None):
60
"""Return the full user id from a file or environment variable.
62
e.g. "John Hacker <jhacker@foo.org>"
65
A branch to use for a per-branch configuration, or None.
67
The following are searched in order:
70
2. .bzr/email for this branch.
74
v = os.environ.get('BZREMAIL')
76
return v.decode(bzrlib.user_encoding)
80
return (branch.controlfile("email", "r")
82
.decode(bzrlib.user_encoding)
85
if e.errno != errno.ENOENT:
91
parser = _get_config_parser()
92
if parser.has_option('DEFAULT', 'email'):
93
email = parser.get('DEFAULT', 'email')
97
v = os.environ.get('EMAIL')
99
return v.decode(bzrlib.user_encoding)
313
def branches_config_filename():
314
"""Return per-user configuration ini file filename."""
315
return os.path.join(config_dir(), 'branches.conf')
104
318
def _auto_user_id():