/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
1
# Copyright (C) 2005 by Canonical Ltd
2
#   Authors: Robert Collins <robert.collins@canonical.com>
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18
"""Configuration that affects the behaviour of Bazaar."""
19
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
20
from ConfigParser import ConfigParser
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
21
import os
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
22
import errno
23
import re
24
25
import bzrlib
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
26
import bzrlib.errors as errors
27
28
29
class Config(object):
30
    """A configuration policy - what username, editor, gpg needs etc."""
31
32
    def get_editor(self):
33
        """Get the users pop up editor."""
34
        raise NotImplementedError
35
36
    def __init__(self):
37
        super(Config, self).__init__()
38
39
    def user_email(self):
40
        """Return just the email component of a username."""
41
        e = self.username()
42
        m = re.search(r'[\w+.-]+@[\w+.-]+', e)
43
        if not m:
44
            raise BzrError("%r doesn't seem to contain "
45
                           "a reasonable email address" % e)
46
        return m.group(0)
47
48
    def username(self):
49
        """Return email-style username.
50
    
51
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
52
        
53
        $BZREMAIL can be set to override this, then
54
        the concrete policy type is checked, and finally
55
        $EMAIL is examinged.
56
        but if none is found, a reasonable default is (hopefully)
57
        created.
58
    
59
        TODO: Check it's reasonably well-formed.
60
        """
61
        v = os.environ.get('BZREMAIL')
62
        if v:
63
            return v.decode(bzrlib.user_encoding)
64
    
65
        v = self._get_user_id()
66
        if v:
67
            return v
68
        
69
        v = os.environ.get('EMAIL')
70
        if v:
71
            return v.decode(bzrlib.user_encoding)
72
73
        name, email = _auto_user_id()
74
        if name:
75
            return '%s <%s>' % (name, email)
76
        else:
77
            return email
78
79
80
class GlobalConfig(Config):
81
    """The configuration that should be used for a specific location."""
82
83
    def _get_parser(self, filename=None, file=None):
84
        parser = ConfigParser()
85
        if file is not None:
86
            parser.readfp(file)
87
        else:
88
            parser.read([filename])
89
        return parser
90
91
    def _get_config_parser(self, file=None):
92
        if self._parser is None:
93
            self._parser =  self._get_parser(config_filename(), file)
94
        return self._parser
95
    
96
    def _get_branches_config_parser(self, file=None):
97
        if self._branches_parser is None:
98
            self._branches_parser = self._get_parser(
99
                branches_config_filename(), file)
100
        return self._branches_parser
101
102
    def get_editor(self):
103
        if self._get_config_parser().has_option('DEFAULT', 'editor'):
104
            return self._get_config_parser().get('DEFAULT', 'editor')
105
106
    def _get_user_id(self, branch=None):
107
        """Return the full user id from the global config file.
108
    
109
        e.g. "John Hacker <jhacker@foo.org>"
110
        from 
111
        [DEFAULT]
112
        email=John Hacker <jhacker@foo.org>
113
        """
114
        if self._get_config_parser().has_option('DEFAULT', 'email'):
115
            email = self._get_config_parser().get('DEFAULT', 'email')
116
            if email is not None:
117
                return email
118
    
119
    def __init__(self):
120
        super(GlobalConfig, self).__init__()
121
        self._branches_parser = None
122
        self._parser = None
123
124
125
class LocationConfig(Config):
126
    """A configuration object that gives the policy for a location."""
127
128
    def __init__(self, location):
129
        self._global_config = None
130
        self.location = location
131
132
    def _get_branches_config_parser(self, file=None):
133
        return self._get_global_config()._get_branches_config_parser(file)
134
135
    def _get_global_config(self):
136
        if self._global_config is None:
137
            self._global_config = GlobalConfig()
138
        return self._global_config
139
140
    def _get_user_id(self):
141
        return self._get_global_config()._get_user_id()
142
143
144
class BranchConfig(Config):
145
    """A configuration object giving the policy for a branch."""
146
147
    def _get_location_config(self):
148
        if self._location_config is None:
149
            self._location_config = LocationConfig(self.branch.base)
150
        return self._location_config
151
152
    def _get_user_id(self):
153
        """Return the full user id for the branch.
154
    
155
        e.g. "John Hacker <jhacker@foo.org>"
156
        This is looked up in the email controlfile for the branch.
157
        """
158
        try:
159
            return (self.branch.controlfile("email", "r") 
160
                    .read()
161
                    .decode(bzrlib.user_encoding)
162
                    .rstrip("\r\n"))
163
        except errors.NoSuchFile, e:
164
            pass
165
        
166
        return self._get_location_config()._get_user_id()
167
168
    def __init__(self, branch):
169
        super(BranchConfig, self).__init__()
170
        self._location_config = None
171
        self.branch = branch
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
172
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
173
174
def config_dir():
175
    """Return per-user configuration directory.
176
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
177
    By default this is ~/.bazaar/
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
178
    
179
    TODO: Global option --config-dir to override this.
180
    """
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
181
    return os.path.join(os.path.expanduser("~"), ".bazaar")
182
183
184
def config_filename():
185
    """Return per-user configuration ini file filename."""
186
    return os.path.join(config_dir(), 'bazaar.conf')
187
188
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
189
def branches_config_filename():
190
    """Return per-user configuration ini file filename."""
191
    return os.path.join(config_dir(), 'branches.conf')
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
192
193
194
def _auto_user_id():
195
    """Calculate automatic user identification.
196
197
    Returns (realname, email).
198
199
    Only used when none is set in the environment or the id file.
200
201
    This previously used the FQDN as the default domain, but that can
202
    be very slow on machines where DNS is broken.  So now we simply
203
    use the hostname.
204
    """
205
    import socket
206
207
    # XXX: Any good way to get real user name on win32?
208
209
    try:
210
        import pwd
211
        uid = os.getuid()
212
        w = pwd.getpwuid(uid)
213
        gecos = w.pw_gecos.decode(bzrlib.user_encoding)
214
        username = w.pw_name.decode(bzrlib.user_encoding)
215
        comma = gecos.find(',')
216
        if comma == -1:
217
            realname = gecos
218
        else:
219
            realname = gecos[:comma]
220
        if not realname:
221
            realname = username
222
223
    except ImportError:
224
        import getpass
225
        realname = username = getpass.getuser().decode(bzrlib.user_encoding)
226
227
    return realname, (username + '@' + socket.gethostname())
228
229