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.conf 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)
29
gpg_signing_command=name-of-program
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
35
[/home/robertc/source]
36
recurse=False|True(default)
38
check_signatures= as abive
39
create_signatures= as above.
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
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.
51
NB: This option is planned, but not implemented yet.
20
54
from ConfigParser import ConfigParser
56
from fnmatch import fnmatch
61
import bzrlib.errors as errors
70
"""A configuration policy - what username, editor, gpg needs etc."""
73
"""Get the users pop up editor."""
74
raise NotImplementedError
76
def _get_signature_checking(self):
77
"""Template method to override signature checking policy."""
79
def gpg_signing_command(self):
80
"""What program should be used to sign signatures?"""
81
result = self._gpg_signing_command()
86
def _gpg_signing_command(self):
87
"""See gpg_signing_command()."""
91
super(Config, self).__init__()
94
"""Return just the email component of a username."""
96
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
98
raise BzrError("%r doesn't seem to contain "
99
"a reasonable email address" % e)
103
"""Return email-style username.
105
Something similar to 'Martin Pool <mbp@sourcefrog.net>'
107
$BZREMAIL can be set to override this, then
108
the concrete policy type is checked, and finally
110
but if none is found, a reasonable default is (hopefully)
113
TODO: Check it's reasonably well-formed.
115
v = os.environ.get('BZREMAIL')
117
return v.decode(bzrlib.user_encoding)
119
v = self._get_user_id()
123
v = os.environ.get('EMAIL')
125
return v.decode(bzrlib.user_encoding)
127
name, email = _auto_user_id()
129
return '%s <%s>' % (name, email)
133
def signature_checking(self):
134
"""What is the current policy for signature checking?."""
135
policy = self._get_signature_checking()
136
if policy is not None:
138
return CHECK_IF_POSSIBLE
140
def signature_needed(self):
141
"""Is a signature needed when committing ?."""
142
policy = self._get_signature_checking()
143
if policy == CHECK_ALWAYS:
148
class IniBasedConfig(Config):
149
"""A configuration policy that draws from ini files."""
151
def _get_parser(self, file=None):
152
if self._parser is not None:
154
parser = ConfigParser()
158
parser.read([self._get_filename()])
159
self._parser = parser
162
def _get_section(self):
163
"""Override this to define the section used by the config."""
166
def _get_signature_checking(self):
167
"""See Config._get_signature_checking."""
168
section = self._get_section()
171
if self._get_parser().has_option(section, 'check_signatures'):
172
return self._string_to_signature_policy(
173
self._get_parser().get(section, 'check_signatures'))
175
def _get_user_id(self):
176
"""Get the user id from the 'email' key in the current section."""
177
section = self._get_section()
178
if section is not None:
179
if self._get_parser().has_option(section, 'email'):
180
return self._get_parser().get(section, 'email')
182
def _gpg_signing_command(self):
183
"""See Config.gpg_signing_command."""
184
section = self._get_section()
185
if section is not None:
186
if self._get_parser().has_option(section, 'gpg_signing_command'):
187
return self._get_parser().get(section, 'gpg_signing_command')
189
def __init__(self, get_filename):
190
super(IniBasedConfig, self).__init__()
191
self._get_filename = get_filename
194
def _string_to_signature_policy(self, signature_string):
195
"""Convert a string to a signing policy."""
196
if signature_string.lower() == 'check-available':
197
return CHECK_IF_POSSIBLE
198
if signature_string.lower() == 'ignore':
200
if signature_string.lower() == 'require':
202
raise errors.BzrError("Invalid signatures policy '%s'"
206
class GlobalConfig(IniBasedConfig):
207
"""The configuration that should be used for a specific location."""
209
def get_editor(self):
210
if self._get_parser().has_option(self._get_section(), 'editor'):
211
return self._get_parser().get(self._get_section(), 'editor')
214
super(GlobalConfig, self).__init__(config_filename)
217
class LocationConfig(IniBasedConfig):
218
"""A configuration object that gives the policy for a location."""
220
def __init__(self, location):
221
super(LocationConfig, self).__init__(branches_config_filename)
222
self._global_config = None
223
self.location = location
225
def _get_global_config(self):
226
if self._global_config is None:
227
self._global_config = GlobalConfig()
228
return self._global_config
230
def _get_section(self):
231
"""Get the section we should look in for config items.
233
Returns None if none exists.
234
TODO: perhaps return a NullSection that thunks through to the
237
sections = self._get_parser().sections()
238
location_names = self.location.split('/')
239
if self.location.endswith('/'):
240
del location_names[-1]
242
for section in sections:
243
section_names = section.split('/')
244
if section.endswith('/'):
245
del section_names[-1]
246
names = zip(location_names, section_names)
249
if not fnmatch(name[0], name[1]):
254
# so, for the common prefix they matched.
255
# if section is longer, no match.
256
if len(section_names) > len(location_names):
258
# if path is longer, and recurse is not true, no match
259
if len(section_names) < len(location_names):
260
if (self._get_parser().has_option(section, 'recurse')
261
and not self._get_parser().getboolean(section, 'recurse')):
263
matches.append((len(section_names), section))
266
matches.sort(reverse=True)
269
def _gpg_signing_command(self):
270
"""See Config.gpg_signing_command."""
271
command = super(LocationConfig, self)._gpg_signing_command()
272
if command is not None:
274
return self._get_global_config()._gpg_signing_command()
276
def _get_user_id(self):
277
user_id = super(LocationConfig, self)._get_user_id()
278
if user_id is not None:
280
return self._get_global_config()._get_user_id()
282
def _get_signature_checking(self):
283
"""See Config._get_signature_checking."""
284
check = super(LocationConfig, self)._get_signature_checking()
285
if check is not None:
287
return self._get_global_config()._get_signature_checking()
290
class BranchConfig(Config):
291
"""A configuration object giving the policy for a branch."""
293
def _get_location_config(self):
294
if self._location_config is None:
295
self._location_config = LocationConfig(self.branch.base)
296
return self._location_config
298
def _get_user_id(self):
299
"""Return the full user id for the branch.
301
e.g. "John Hacker <jhacker@foo.org>"
302
This is looked up in the email controlfile for the branch.
305
return (self.branch.controlfile("email", "r")
307
.decode(bzrlib.user_encoding)
309
except errors.NoSuchFile, e:
312
return self._get_location_config()._get_user_id()
314
def _get_signature_checking(self):
315
"""See Config._get_signature_checking."""
316
return self._get_location_config()._get_signature_checking()
318
def _gpg_signing_command(self):
319
"""See Config.gpg_signing_command."""
320
return self._get_location_config()._gpg_signing_command()
322
def __init__(self, branch):
323
super(BranchConfig, self).__init__()
324
self._location_config = None