125
class ConfigObj(configobj.ConfigObj):
127
def get_bool(self, section, key):
128
return self[section].as_bool(key)
130
def get_value(self, section, name):
131
# Try [] for the old DEFAULT section.
132
if section == "DEFAULT":
137
return self[section][name]
126
def ConfigObj(*args, **kwargs):
128
if _ConfigObj is None:
129
class ConfigObj(configobj.ConfigObj):
131
def get_bool(self, section, key):
132
return self[section].as_bool(key)
134
def get_value(self, section, name):
135
# Try [] for the old DEFAULT section.
136
if section == "DEFAULT":
141
return self[section][name]
142
_ConfigObj = ConfigObj
143
return _ConfigObj(*args, **kwargs)
140
146
class Config(object):
141
147
"""A configuration policy - what username, editor, gpg needs etc."""
150
super(Config, self).__init__()
143
152
def get_editor(self):
144
153
"""Get the users pop up editor."""
145
154
raise NotImplementedError
156
def get_change_editor(self, old_tree, new_tree):
157
from bzrlib import diff
158
cmd = self._get_change_editor()
161
return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
147
165
def get_mail_client(self):
148
166
"""Get a mail client to use"""
149
167
selected_client = self.get_user_option('mail_client')
168
186
"""Get a generic option - no special process, no default."""
169
187
return self._get_user_option(option_name)
189
def get_user_option_as_bool(self, option_name):
190
"""Get a generic option as a boolean - no special process, no default.
192
:return None if the option doesn't exist or its value can't be
193
interpreted as a boolean. Returns True or False otherwise.
195
s = self._get_user_option(option_name)
196
return ui.bool_from_string(s)
198
def get_user_option_as_list(self, option_name):
199
"""Get a generic option as a list - no special process, no default.
201
:return None if the option doesn't exist. Returns the value as a list
204
l = self._get_user_option(option_name)
205
if isinstance(l, (str, unicode)):
206
# A single value, most probably the user forgot the final ','
171
210
def gpg_signing_command(self):
172
211
"""What program should be used to sign signatures?"""
173
212
result = self._gpg_signing_command()
994
1078
:param user: login (optional)
996
1080
:param path: the absolute path on the server (optional)
1082
:param realm: the http authentication realm (optional)
998
1084
:return: A dict containing the matching credentials or None.
1000
1086
- name: the section name of the credentials in the
1001
1087
authentication.conf file,
1002
- user: can't de different from the provided user if any,
1088
- user: can't be different from the provided user if any,
1089
- scheme: the server protocol,
1090
- host: the server address,
1091
- port: the server port (can be None),
1092
- path: the absolute server path (can be None),
1093
- realm: the http specific authentication realm (can be None),
1003
1094
- password: the decoded password, could be None if the credential
1004
1095
defines only the user
1005
1096
- verify_certificates: https specific, True if the server
1046
1137
if a_user is None:
1047
1138
# Can't find a user
1140
# Prepare a credentials dictionary with additional keys
1141
# for the credential providers
1049
1142
credentials = dict(name=auth_def_name,
1051
1149
password=auth_def.get('password', None),
1052
1150
verify_certificates=a_verify_certificates)
1151
# Decode the password in the credentials (or get one)
1053
1152
self.decode_password(credentials,
1054
1153
auth_def.get('password_encoding', None))
1055
1154
if 'auth' in debug.debug_flags:
1056
1155
trace.mutter("Using authentication section: %r", auth_def_name)
1158
if credentials is None:
1159
# No credentials were found in authentication.conf, try the fallback
1160
# credentials stores.
1161
credentials = credential_store_registry.get_fallback_credentials(
1162
scheme, host, port, user, path, realm)
1059
1164
return credentials
1061
def get_user(self, scheme, host, port=None,
1062
realm=None, path=None, prompt=None):
1166
def set_credentials(self, name, host, user, scheme=None, password=None,
1167
port=None, path=None, verify_certificates=None,
1169
"""Set authentication credentials for a host.
1171
Any existing credentials with matching scheme, host, port and path
1172
will be deleted, regardless of name.
1174
:param name: An arbitrary name to describe this set of credentials.
1175
:param host: Name of the host that accepts these credentials.
1176
:param user: The username portion of these credentials.
1177
:param scheme: The URL scheme (e.g. ssh, http) the credentials apply
1179
:param password: Password portion of these credentials.
1180
:param port: The IP port on the host that these credentials apply to.
1181
:param path: A filesystem path on the host that these credentials
1183
:param verify_certificates: On https, verify server certificates if
1185
:param realm: The http authentication realm (optional).
1187
values = {'host': host, 'user': user}
1188
if password is not None:
1189
values['password'] = password
1190
if scheme is not None:
1191
values['scheme'] = scheme
1192
if port is not None:
1193
values['port'] = '%d' % port
1194
if path is not None:
1195
values['path'] = path
1196
if verify_certificates is not None:
1197
values['verify_certificates'] = str(verify_certificates)
1198
if realm is not None:
1199
values['realm'] = realm
1200
config = self._get_config()
1202
for section, existing_values in config.items():
1203
for key in ('scheme', 'host', 'port', 'path', 'realm'):
1204
if existing_values.get(key) != values.get(key):
1208
config.update({name: values})
1211
def get_user(self, scheme, host, port=None, realm=None, path=None,
1212
prompt=None, ask=False, default=None):
1063
1213
"""Get a user from authentication file.
1065
1215
:param scheme: protocol
1125
1294
return password
1127
1296
def decode_password(self, credentials, encoding):
1298
cs = credential_store_registry.get_credential_store(encoding)
1300
raise ValueError('%r is not a known password_encoding' % encoding)
1301
credentials['password'] = cs.decode_password(credentials)
1305
class CredentialStoreRegistry(registry.Registry):
1306
"""A class that registers credential stores.
1308
A credential store provides access to credentials via the password_encoding
1309
field in authentication.conf sections.
1311
Except for stores provided by bzr itself, most stores are expected to be
1312
provided by plugins that will therefore use
1313
register_lazy(password_encoding, module_name, member_name, help=help,
1314
fallback=fallback) to install themselves.
1316
A fallback credential store is one that is queried if no credentials can be
1317
found via authentication.conf.
1320
def get_credential_store(self, encoding=None):
1321
cs = self.get(encoding)
1326
def is_fallback(self, name):
1327
"""Check if the named credentials store should be used as fallback."""
1328
return self.get_info(name)
1330
def get_fallback_credentials(self, scheme, host, port=None, user=None,
1331
path=None, realm=None):
1332
"""Request credentials from all fallback credentials stores.
1334
The first credentials store that can provide credentials wins.
1337
for name in self.keys():
1338
if not self.is_fallback(name):
1340
cs = self.get_credential_store(name)
1341
credentials = cs.get_credentials(scheme, host, port, user,
1343
if credentials is not None:
1344
# We found some credentials
1348
def register(self, key, obj, help=None, override_existing=False,
1350
"""Register a new object to a name.
1352
:param key: This is the key to use to request the object later.
1353
:param obj: The object to register.
1354
:param help: Help text for this entry. This may be a string or
1355
a callable. If it is a callable, it should take two
1356
parameters (registry, key): this registry and the key that
1357
the help was registered under.
1358
:param override_existing: Raise KeyErorr if False and something has
1359
already been registered for that key. If True, ignore if there
1360
is an existing key (always register the new value).
1361
:param fallback: Whether this credential store should be
1364
return super(CredentialStoreRegistry,
1365
self).register(key, obj, help, info=fallback,
1366
override_existing=override_existing)
1368
def register_lazy(self, key, module_name, member_name,
1369
help=None, override_existing=False,
1371
"""Register a new credential store to be loaded on request.
1373
:param module_name: The python path to the module. Such as 'os.path'.
1374
:param member_name: The member of the module to return. If empty or
1375
None, get() will return the module itself.
1376
:param help: Help text for this entry. This may be a string or
1378
:param override_existing: If True, replace the existing object
1379
with the new one. If False, if there is already something
1380
registered with the same key, raise a KeyError
1381
:param fallback: Whether this credential store should be
1384
return super(CredentialStoreRegistry, self).register_lazy(
1385
key, module_name, member_name, help,
1386
info=fallback, override_existing=override_existing)
1389
credential_store_registry = CredentialStoreRegistry()
1392
class CredentialStore(object):
1393
"""An abstract class to implement storage for credentials"""
1395
def decode_password(self, credentials):
1396
"""Returns a clear text password for the provided credentials."""
1397
raise NotImplementedError(self.decode_password)
1399
def get_credentials(self, scheme, host, port=None, user=None, path=None,
1401
"""Return the matching credentials from this credential store.
1403
This method is only called on fallback credential stores.
1405
raise NotImplementedError(self.get_credentials)
1409
class PlainTextCredentialStore(CredentialStore):
1410
"""Plain text credential store for the authentication.conf file."""
1412
def decode_password(self, credentials):
1413
"""See CredentialStore.decode_password."""
1414
return credentials['password']
1417
credential_store_registry.register('plain', PlainTextCredentialStore,
1418
help=PlainTextCredentialStore.__doc__)
1419
credential_store_registry.default_key = 'plain'
1131
1422
class BzrDirConfig(object):
1133
def __init__(self, transport):
1134
self._config = TransportConfig(transport, 'control.conf')
1424
def __init__(self, bzrdir):
1425
self._bzrdir = bzrdir
1426
self._config = bzrdir._get_config()
1136
1428
def set_default_stack_on(self, value):
1137
1429
"""Set the default stacking location.