15
15
# You should have received a copy of the GNU General Public License
16
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
19
"""Configuration that affects the behaviour of Bazaar.
45
45
editor - this option sets the pop up editor to use during commits.
46
46
email - this option sets the user id bzr will use when committing.
47
47
check_signatures - this option controls whether bzr will require good gpg
48
signatures, ignore them, or check them if they are
48
signatures, ignore them, or check them if they are
50
create_signatures - this option controls whether bzr will always create
50
create_signatures - this option controls whether bzr will always create
51
51
gpg signatures, never create them, or create them if the
52
52
branch is configured to require them.
53
53
log_format - this option sets the default log format. Possible values are
174
177
"""Get a generic option - no special process, no default."""
175
178
return self._get_user_option(option_name)
180
def get_user_option_as_bool(self, option_name):
181
"""Get a generic option as a boolean - no special process, no default.
183
:return None if the option doesn't exist or its value can't be
184
interpreted as a boolean. Returns True or False ortherwise.
186
s = self._get_user_option(option_name)
187
return ui.bool_from_string(s)
177
189
def gpg_signing_command(self):
178
190
"""What program should be used to sign signatures?"""
179
191
result = self._gpg_signing_command()
217
226
def username(self):
218
227
"""Return email-style username.
220
229
Something similar to 'Martin Pool <mbp@sourcefrog.net>'
222
231
$BZR_EMAIL can be set to override this (as well as the
223
232
deprecated $BZREMAIL), then
224
233
the concrete policy type is checked, and finally
225
234
$EMAIL is examined.
226
235
If none is found, a reasonable default is (hopefully)
229
238
TODO: Check it's reasonably well-formed.
231
240
v = os.environ.get('BZR_EMAIL')
709
718
trace.warning('Value "%s" is masked by "%s" from'
710
719
' branch.conf', value, mask_value)
713
721
def _gpg_signing_command(self):
714
722
"""See Config.gpg_signing_command."""
715
723
return self._get_safe_value('_gpg_signing_command')
717
725
def __init__(self, branch):
718
726
super(BranchConfig, self).__init__()
719
727
self._location_config = None
720
728
self._branch_data_config = None
721
729
self._global_config = None
722
730
self.branch = branch
723
self.option_sources = (self._get_location_config,
731
self.option_sources = (self._get_location_config,
724
732
self._get_branch_data_config,
725
733
self._get_global_config)
917
925
# XXX: Really needs a better name, as this is not part of the tree! -- mbp 20080507
919
927
def __init__(self, branch):
920
# XXX: Really this should be asking the branch for its configuration
921
# data, rather than relying on a Transport, so that it can work
922
# more cleanly with a RemoteBranch that has no transport.
923
self._config = TransportConfig(branch._transport, 'branch.conf')
928
self._config = branch._get_config()
924
929
self.branch = branch
926
931
def _get_parser(self, file=None):
993
997
section[option_name] = value
996
def get_credentials(self, scheme, host, port=None, user=None, path=None):
1000
def get_credentials(self, scheme, host, port=None, user=None, path=None,
997
1002
"""Returns the matching credentials from authentication.conf file.
999
1004
:param scheme: protocol
1005
1010
:param user: login (optional)
1007
1012
:param path: the absolute path on the server (optional)
1014
:param realm: the http authentication realm (optional)
1009
1016
:return: A dict containing the matching credentials or None.
1011
1018
- name: the section name of the credentials in the
1012
1019
authentication.conf file,
1013
- user: can't de different from the provided user if any,
1020
- user: can't be different from the provided user if any,
1021
- scheme: the server protocol,
1022
- host: the server address,
1023
- port: the server port (can be None),
1024
- path: the absolute server path (can be None),
1025
- realm: the http specific authentication realm (can be None),
1014
1026
- password: the decoded password, could be None if the credential
1015
1027
defines only the user
1016
1028
- verify_certificates: https specific, True if the server
1057
1069
if a_user is None:
1058
1070
# Can't find a user
1072
# Prepare a credentials dictionary with additional keys
1073
# for the credential providers
1060
1074
credentials = dict(name=auth_def_name,
1062
1081
password=auth_def.get('password', None),
1063
1082
verify_certificates=a_verify_certificates)
1083
# Decode the password in the credentials (or get one)
1064
1084
self.decode_password(credentials,
1065
1085
auth_def.get('password_encoding', None))
1066
1086
if 'auth' in debug.debug_flags:
1067
1087
trace.mutter("Using authentication section: %r", auth_def_name)
1090
if credentials is None:
1091
# No credentials were found in authentication.conf, try the fallback
1092
# credentials stores.
1093
credentials = credential_store_registry.get_fallback_credentials(
1094
scheme, host, port, user, path, realm)
1070
1096
return credentials
1072
1098
def set_credentials(self, name, host, user, scheme=None, password=None,
1073
port=None, path=None, verify_certificates=None):
1099
port=None, path=None, verify_certificates=None,
1074
1101
"""Set authentication credentials for a host.
1076
1103
Any existing credentials with matching scheme, host, port and path
1099
1127
values['path'] = path
1100
1128
if verify_certificates is not None:
1101
1129
values['verify_certificates'] = str(verify_certificates)
1130
if realm is not None:
1131
values['realm'] = realm
1102
1132
config = self._get_config()
1103
1133
for_deletion = []
1104
1134
for section, existing_values in config.items():
1105
for key in ('scheme', 'host', 'port', 'path'):
1135
for key in ('scheme', 'host', 'port', 'path', 'realm'):
1106
1136
if existing_values.get(key) != values.get(key):
1110
1140
config.update({name: values})
1113
def get_user(self, scheme, host, port=None,
1114
realm=None, path=None, prompt=None):
1143
def get_user(self, scheme, host, port=None, realm=None, path=None,
1144
prompt=None, ask=False, default=None):
1115
1145
"""Get a user from authentication file.
1117
1147
:param scheme: protocol
1125
1155
:param path: the absolute path on the server (optional)
1157
:param ask: Ask the user if there is no explicitly configured username
1160
:param default: The username returned if none is defined (optional).
1127
1162
:return: The found user.
1129
1164
credentials = self.get_credentials(scheme, host, port, user=None,
1165
path=path, realm=realm)
1131
1166
if credentials is not None:
1132
1167
user = credentials['user']
1173
# Create a default prompt suitable for most cases
1174
prompt = scheme.upper() + ' %(host)s username'
1175
# Special handling for optional fields in the prompt
1176
if port is not None:
1177
prompt_host = '%s:%d' % (host, port)
1180
user = ui.ui_factory.get_username(prompt, host=prompt_host)
1137
1185
def get_password(self, scheme, host, user, port=None,
1153
1201
:return: The found password or the one entered by the user.
1155
credentials = self.get_credentials(scheme, host, port, user, path)
1203
credentials = self.get_credentials(scheme, host, port, user, path,
1156
1205
if credentials is not None:
1157
1206
password = credentials['password']
1158
1207
if password is not None and scheme is 'ssh':
1191
1240
A credential store provides access to credentials via the password_encoding
1192
1241
field in authentication.conf sections.
1194
Except for stores provided by bzr itself,most stores are expected to be
1243
Except for stores provided by bzr itself, most stores are expected to be
1195
1244
provided by plugins that will therefore use
1196
1245
register_lazy(password_encoding, module_name, member_name, help=help,
1197
info=info) to install themselves.
1246
fallback=fallback) to install themselves.
1248
A fallback credential store is one that is queried if no credentials can be
1249
found via authentication.conf.
1200
1252
def get_credential_store(self, encoding=None):
1258
def is_fallback(self, name):
1259
"""Check if the named credentials store should be used as fallback."""
1260
return self.get_info(name)
1262
def get_fallback_credentials(self, scheme, host, port=None, user=None,
1263
path=None, realm=None):
1264
"""Request credentials from all fallback credentials stores.
1266
The first credentials store that can provide credentials wins.
1269
for name in self.keys():
1270
if not self.is_fallback(name):
1272
cs = self.get_credential_store(name)
1273
credentials = cs.get_credentials(scheme, host, port, user,
1275
if credentials is not None:
1276
# We found some credentials
1280
def register(self, key, obj, help=None, override_existing=False,
1282
"""Register a new object to a name.
1284
:param key: This is the key to use to request the object later.
1285
:param obj: The object to register.
1286
:param help: Help text for this entry. This may be a string or
1287
a callable. If it is a callable, it should take two
1288
parameters (registry, key): this registry and the key that
1289
the help was registered under.
1290
:param override_existing: Raise KeyErorr if False and something has
1291
already been registered for that key. If True, ignore if there
1292
is an existing key (always register the new value).
1293
:param fallback: Whether this credential store should be
1296
return super(CredentialStoreRegistry,
1297
self).register(key, obj, help, info=fallback,
1298
override_existing=override_existing)
1300
def register_lazy(self, key, module_name, member_name,
1301
help=None, override_existing=False,
1303
"""Register a new credential store to be loaded on request.
1305
:param module_name: The python path to the module. Such as 'os.path'.
1306
:param member_name: The member of the module to return. If empty or
1307
None, get() will return the module itself.
1308
:param help: Help text for this entry. This may be a string or
1310
:param override_existing: If True, replace the existing object
1311
with the new one. If False, if there is already something
1312
registered with the same key, raise a KeyError
1313
:param fallback: Whether this credential store should be
1316
return super(CredentialStoreRegistry, self).register_lazy(
1317
key, module_name, member_name, help,
1318
info=fallback, override_existing=override_existing)
1207
1321
credential_store_registry = CredentialStoreRegistry()
1211
1325
"""An abstract class to implement storage for credentials"""
1213
1327
def decode_password(self, credentials):
1214
"""Returns a password for the provided credentials in clear text."""
1328
"""Returns a clear text password for the provided credentials."""
1215
1329
raise NotImplementedError(self.decode_password)
1331
def get_credentials(self, scheme, host, port=None, user=None, path=None,
1333
"""Return the matching credentials from this credential store.
1335
This method is only called on fallback credential stores.
1337
raise NotImplementedError(self.get_credentials)
1218
1341
class PlainTextCredentialStore(CredentialStore):
1219
1342
"""Plain text credential store for the authentication.conf file."""
1231
1354
class BzrDirConfig(object):
1233
def __init__(self, transport):
1234
self._config = TransportConfig(transport, 'control.conf')
1356
def __init__(self, bzrdir):
1357
self._bzrdir = bzrdir
1358
self._config = bzrdir._get_config()
1236
1360
def set_default_stack_on(self, value):
1237
1361
"""Set the default stacking location.
1304
1432
configobj.setdefault(section, {})[name] = value
1305
1433
self._set_configobj(configobj)
1435
def _get_config_file(self):
1437
return self._transport.get(self._filename)
1438
except errors.NoSuchFile:
1307
1441
def _get_configobj(self):
1309
return ConfigObj(self._transport.get(self._filename),
1311
except errors.NoSuchFile:
1312
return ConfigObj(encoding='utf-8')
1442
return ConfigObj(self._get_config_file(), encoding='utf-8')
1314
1444
def _set_configobj(self, configobj):
1315
1445
out_file = StringIO()