~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: John Arbash Meinel
  • Date: 2008-07-11 21:41:24 UTC
  • mto: This revision was merged to the branch mainline in revision 3543.
  • Revision ID: john@arbash-meinel.com-20080711214124-qi09irlj7pd5cuzg
Shortcut the case when one revision is in the ancestry of the other.

At the cost of a heads() check, when one parent supersedes, we don't have to extract
the text for the other. Changes merge time from 3m37s => 3m21s. Using a
CachingParentsProvider would drop the time down to 3m11s.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2007, 2008 Canonical Ltd
 
1
# Copyright (C) 2005, 2007 Canonical Ltd
2
2
#   Authors: Robert Collins <robert.collins@canonical.com>
3
3
#            and others
4
4
#
78
78
    errors,
79
79
    mail_client,
80
80
    osutils,
81
 
    registry,
82
81
    symbol_versioning,
83
82
    trace,
84
83
    ui,
122
121
STORE_BRANCH = 3
123
122
STORE_GLOBAL = 4
124
123
 
125
 
_ConfigObj = None
126
 
def ConfigObj(*args, **kwargs):
127
 
    global _ConfigObj
128
 
    if _ConfigObj is None:
129
 
        class ConfigObj(configobj.ConfigObj):
130
 
 
131
 
            def get_bool(self, section, key):
132
 
                return self[section].as_bool(key)
133
 
 
134
 
            def get_value(self, section, name):
135
 
                # Try [] for the old DEFAULT section.
136
 
                if section == "DEFAULT":
137
 
                    try:
138
 
                        return self[name]
139
 
                    except KeyError:
140
 
                        pass
141
 
                return self[section][name]
142
 
        _ConfigObj = ConfigObj
143
 
    return _ConfigObj(*args, **kwargs)
 
124
 
 
125
class ConfigObj(configobj.ConfigObj):
 
126
 
 
127
    def get_bool(self, section, key):
 
128
        return self[section].as_bool(key)
 
129
 
 
130
    def get_value(self, section, name):
 
131
        # Try [] for the old DEFAULT section.
 
132
        if section == "DEFAULT":
 
133
            try:
 
134
                return self[name]
 
135
            except KeyError:
 
136
                pass
 
137
        return self[section][name]
144
138
 
145
139
 
146
140
class Config(object):
153
147
    def get_mail_client(self):
154
148
        """Get a mail client to use"""
155
149
        selected_client = self.get_user_option('mail_client')
156
 
        _registry = mail_client.mail_client_registry
157
150
        try:
158
 
            mail_client_class = _registry.get(selected_client)
 
151
            mail_client_class = {
 
152
                None: mail_client.DefaultMail,
 
153
                # Specific clients
 
154
                'emacsclient': mail_client.EmacsMail,
 
155
                'evolution': mail_client.Evolution,
 
156
                'kmail': mail_client.KMail,
 
157
                'mutt': mail_client.Mutt,
 
158
                'thunderbird': mail_client.Thunderbird,
 
159
                # Generic options
 
160
                'default': mail_client.DefaultMail,
 
161
                'editor': mail_client.Editor,
 
162
                'mapi': mail_client.MAPIClient,
 
163
                'xdg-email': mail_client.XDGEmail,
 
164
            }[selected_client]
159
165
        except KeyError:
160
166
            raise errors.UnknownMailClient(selected_client)
161
167
        return mail_client_class(self)
230
236
        """
231
237
        v = os.environ.get('BZR_EMAIL')
232
238
        if v:
233
 
            return v.decode(osutils.get_user_encoding())
 
239
            return v.decode(bzrlib.user_encoding)
234
240
 
235
241
        v = self._get_user_id()
236
242
        if v:
238
244
 
239
245
        v = os.environ.get('EMAIL')
240
246
        if v:
241
 
            return v.decode(osutils.get_user_encoding())
 
247
            return v.decode(bzrlib.user_encoding)
242
248
 
243
249
        name, email = _auto_user_id()
244
250
        if name:
663
669
        """
664
670
        try:
665
671
            return (self.branch._transport.get_bytes("email")
666
 
                    .decode(osutils.get_user_encoding())
 
672
                    .decode(bzrlib.user_encoding)
667
673
                    .rstrip("\r\n"))
668
674
        except errors.NoSuchFile, e:
669
675
            pass
840
846
    try:
841
847
        import pwd
842
848
        uid = os.getuid()
843
 
        try:
844
 
            w = pwd.getpwuid(uid)
845
 
        except KeyError:
846
 
            raise errors.BzrCommandError('Unable to determine your name.  '
847
 
                'Please use "bzr whoami" to set it.')
 
849
        w = pwd.getpwuid(uid)
848
850
 
849
851
        # we try utf-8 first, because on many variants (like Linux),
850
852
        # /etc/passwd "should" be in utf-8, and because it's unlikely to give
855
857
            encoding = 'utf-8'
856
858
        except UnicodeError:
857
859
            try:
858
 
                encoding = osutils.get_user_encoding()
859
 
                gecos = w.pw_gecos.decode(encoding)
 
860
                gecos = w.pw_gecos.decode(bzrlib.user_encoding)
 
861
                encoding = bzrlib.user_encoding
860
862
            except UnicodeError:
861
863
                raise errors.BzrCommandError('Unable to determine your name.  '
862
864
                   'Use "bzr whoami" to set it.')
877
879
    except ImportError:
878
880
        import getpass
879
881
        try:
880
 
            user_encoding = osutils.get_user_encoding()
881
 
            realname = username = getpass.getuser().decode(user_encoding)
 
882
            realname = username = getpass.getuser().decode(bzrlib.user_encoding)
882
883
        except UnicodeDecodeError:
883
884
            raise errors.BzrError("Can't decode username as %s." % \
884
 
                    user_encoding)
 
885
                    bzrlib.user_encoding)
885
886
 
886
887
    return realname, (username + '@' + socket.gethostname())
887
888
 
1069
1070
 
1070
1071
        return credentials
1071
1072
 
1072
 
    def set_credentials(self, name, host, user, scheme=None, password=None,
1073
 
                        port=None, path=None, verify_certificates=None):
1074
 
        """Set authentication credentials for a host.
1075
 
 
1076
 
        Any existing credentials with matching scheme, host, port and path
1077
 
        will be deleted, regardless of name.
1078
 
 
1079
 
        :param name: An arbitrary name to describe this set of credentials.
1080
 
        :param host: Name of the host that accepts these credentials.
1081
 
        :param user: The username portion of these credentials.
1082
 
        :param scheme: The URL scheme (e.g. ssh, http) the credentials apply
1083
 
            to.
1084
 
        :param password: Password portion of these credentials.
1085
 
        :param port: The IP port on the host that these credentials apply to.
1086
 
        :param path: A filesystem path on the host that these credentials
1087
 
            apply to.
1088
 
        :param verify_certificates: On https, verify server certificates if
1089
 
            True.
1090
 
        """
1091
 
        values = {'host': host, 'user': user}
1092
 
        if password is not None:
1093
 
            values['password'] = password
1094
 
        if scheme is not None:
1095
 
            values['scheme'] = scheme
1096
 
        if port is not None:
1097
 
            values['port'] = '%d' % port
1098
 
        if path is not None:
1099
 
            values['path'] = path
1100
 
        if verify_certificates is not None:
1101
 
            values['verify_certificates'] = str(verify_certificates)
1102
 
        config = self._get_config()
1103
 
        for_deletion = []
1104
 
        for section, existing_values in config.items():
1105
 
            for key in ('scheme', 'host', 'port', 'path'):
1106
 
                if existing_values.get(key) != values.get(key):
1107
 
                    break
1108
 
            else:
1109
 
                del config[section]
1110
 
        config.update({name: values})
1111
 
        self._save()
1112
 
 
1113
1073
    def get_user(self, scheme, host, port=None,
1114
1074
                 realm=None, path=None, prompt=None):
1115
1075
        """Get a user from authentication file.
1177
1137
        return password
1178
1138
 
1179
1139
    def decode_password(self, credentials, encoding):
1180
 
        try:
1181
 
            cs = credential_store_registry.get_credential_store(encoding)
1182
 
        except KeyError:
1183
 
            raise ValueError('%r is not a known password_encoding' % encoding)
1184
 
        credentials['password'] = cs.decode_password(credentials)
1185
1140
        return credentials
1186
1141
 
1187
1142
 
1188
 
class CredentialStoreRegistry(registry.Registry):
1189
 
    """A class that registers credential stores.
1190
 
 
1191
 
    A credential store provides access to credentials via the password_encoding
1192
 
    field in authentication.conf sections.
1193
 
 
1194
 
    Except for stores provided by bzr itself,most stores are expected to be
1195
 
    provided by plugins that will therefore use
1196
 
    register_lazy(password_encoding, module_name, member_name, help=help,
1197
 
    info=info) to install themselves.
1198
 
    """
1199
 
 
1200
 
    def get_credential_store(self, encoding=None):
1201
 
        cs = self.get(encoding)
1202
 
        if callable(cs):
1203
 
            cs = cs()
1204
 
        return cs
1205
 
 
1206
 
 
1207
 
credential_store_registry = CredentialStoreRegistry()
1208
 
 
1209
 
 
1210
 
class CredentialStore(object):
1211
 
    """An abstract class to implement storage for credentials"""
1212
 
 
1213
 
    def decode_password(self, credentials):
1214
 
        """Returns a password for the provided credentials in clear text."""
1215
 
        raise NotImplementedError(self.decode_password)
1216
 
 
1217
 
 
1218
 
class PlainTextCredentialStore(CredentialStore):
1219
 
    """Plain text credential store for the authentication.conf file."""
1220
 
 
1221
 
    def decode_password(self, credentials):
1222
 
        """See CredentialStore.decode_password."""
1223
 
        return credentials['password']
1224
 
 
1225
 
 
1226
 
credential_store_registry.register('plain', PlainTextCredentialStore,
1227
 
                                   help=PlainTextCredentialStore.__doc__)
1228
 
credential_store_registry.default_key = 'plain'
1229
 
 
1230
 
 
1231
 
class BzrDirConfig(object):
1232
 
 
1233
 
    def __init__(self, transport):
1234
 
        self._config = TransportConfig(transport, 'control.conf')
1235
 
 
1236
 
    def set_default_stack_on(self, value):
1237
 
        """Set the default stacking location.
1238
 
 
1239
 
        It may be set to a location, or None.
1240
 
 
1241
 
        This policy affects all branches contained by this bzrdir, except for
1242
 
        those under repositories.
1243
 
        """
1244
 
        if value is None:
1245
 
            self._config.set_option('', 'default_stack_on')
1246
 
        else:
1247
 
            self._config.set_option(value, 'default_stack_on')
1248
 
 
1249
 
    def get_default_stack_on(self):
1250
 
        """Return the default stacking location.
1251
 
 
1252
 
        This will either be a location, or None.
1253
 
 
1254
 
        This policy affects all branches contained by this bzrdir, except for
1255
 
        those under repositories.
1256
 
        """
1257
 
        value = self._config.get_option('default_stack_on')
1258
 
        if value == '':
1259
 
            value = None
1260
 
        return value
1261
 
 
1262
 
 
1263
1143
class TransportConfig(object):
1264
1144
    """A Config that reads/writes a config file on a Transport.
1265
1145