/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/bedding.py

  • Committer: Jelmer Vernooij
  • Date: 2018-05-06 11:48:54 UTC
  • mto: This revision was merged to the branch mainline in revision 6960.
  • Revision ID: jelmer@jelmer.uk-20180506114854-h4qd9ojaqy8wxjsd
Move .mailmap to root.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2014, 2016 Canonical Ltd
2
 
# Copyright (C) 2019 Breezy developers
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
 
 
18
 
"""Functions for deriving user configuration from system environment."""
19
 
 
20
 
from __future__ import absolute_import
21
 
 
22
 
import os
23
 
import sys
24
 
 
25
 
from .lazy_import import lazy_import
26
 
lazy_import(globals(), """
27
 
from breezy import (
28
 
    osutils,
29
 
    trace,
30
 
    win32utils,
31
 
    )
32
 
""")
33
 
from . import (
34
 
    errors,
35
 
    )
36
 
from .sixish import (
37
 
    PY3,
38
 
    )
39
 
 
40
 
 
41
 
def ensure_config_dir_exists(path=None):
42
 
    """Make sure a configuration directory exists.
43
 
 
44
 
    This makes sure that the directory exists.
45
 
    On windows, since configuration directories are 2 levels deep,
46
 
    it makes sure both the directory and the parent directory exists.
47
 
    """
48
 
    if path is None:
49
 
        path = config_dir()
50
 
    if not os.path.isdir(path):
51
 
        if sys.platform == 'win32':
52
 
            parent_dir = os.path.dirname(path)
53
 
            if not os.path.isdir(parent_dir):
54
 
                trace.mutter(
55
 
                    'creating config parent directory: %r', parent_dir)
56
 
                os.mkdir(parent_dir)
57
 
        trace.mutter('creating config directory: %r', path)
58
 
        os.mkdir(path)
59
 
        osutils.copy_ownership_from_path(path)
60
 
 
61
 
 
62
 
def bazaar_config_dir():
63
 
    """Return per-user configuration directory as unicode string
64
 
 
65
 
    By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
66
 
    and Linux.  On Mac OS X and Linux, if there is a $XDG_CONFIG_HOME/bazaar
67
 
    directory, that will be used instead
68
 
 
69
 
    TODO: Global option --config-dir to override this.
70
 
    """
71
 
    base = osutils.path_from_environ('BZR_HOME')
72
 
    if sys.platform == 'win32':
73
 
        if base is None:
74
 
            base = win32utils.get_appdata_location()
75
 
        if base is None:
76
 
            base = win32utils.get_home_location()
77
 
        return osutils.pathjoin(base, 'bazaar', '2.0')
78
 
    if base is None:
79
 
        xdg_dir = osutils.path_from_environ('XDG_CONFIG_HOME')
80
 
        if xdg_dir is None:
81
 
            xdg_dir = osutils.pathjoin(osutils._get_home_dir(), ".config")
82
 
        xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
83
 
        if osutils.isdir(xdg_dir):
84
 
            trace.mutter(
85
 
                "Using configuration in XDG directory %s." % xdg_dir)
86
 
            return xdg_dir
87
 
        base = osutils._get_home_dir()
88
 
    return osutils.pathjoin(base, ".bazaar")
89
 
 
90
 
 
91
 
def _config_dir():
92
 
    """Return per-user configuration directory as unicode string
93
 
 
94
 
    By default this is %APPDATA%/breezy on Windows, $XDG_CONFIG_HOME/breezy on
95
 
    Mac OS X and Linux. If the breezy config directory doesn't exist but
96
 
    the bazaar one (see bazaar_config_dir()) does, use that instead.
97
 
    """
98
 
    # TODO: Global option --config-dir to override this.
99
 
    base = osutils.path_from_environ('BRZ_HOME')
100
 
    if sys.platform == 'win32':
101
 
        if base is None:
102
 
            base = win32utils.get_appdata_location()
103
 
        if base is None:
104
 
            base = win32utils.get_home_location()
105
 
    if base is None:
106
 
        base = osutils.path_from_environ('XDG_CONFIG_HOME')
107
 
        if base is None:
108
 
            base = osutils.pathjoin(osutils._get_home_dir(), ".config")
109
 
    breezy_dir = osutils.pathjoin(base, 'breezy')
110
 
    if osutils.isdir(breezy_dir):
111
 
        return (breezy_dir, 'breezy')
112
 
    # If the breezy directory doesn't exist, but the bazaar one does, use that:
113
 
    bazaar_dir = bazaar_config_dir()
114
 
    if osutils.isdir(bazaar_dir):
115
 
        trace.mutter(
116
 
            "Using Bazaar configuration directory (%s)", bazaar_dir)
117
 
        return (bazaar_dir, 'bazaar')
118
 
    return (breezy_dir, 'breezy')
119
 
 
120
 
 
121
 
def config_dir():
122
 
    """Return per-user configuration directory as unicode string
123
 
 
124
 
    By default this is %APPDATA%/breezy on Windows, $XDG_CONFIG_HOME/breezy on
125
 
    Mac OS X and Linux. If the breezy config directory doesn't exist but
126
 
    the bazaar one (see bazaar_config_dir()) does, use that instead.
127
 
    """
128
 
    return _config_dir()[0]
129
 
 
130
 
 
131
 
def config_path():
132
 
    """Return per-user configuration ini file filename."""
133
 
    path, kind = _config_dir()
134
 
    if kind == 'bazaar':
135
 
        return osutils.pathjoin(path, 'bazaar.conf')
136
 
    else:
137
 
        return osutils.pathjoin(path, 'breezy.conf')
138
 
 
139
 
 
140
 
def locations_config_path():
141
 
    """Return per-user configuration ini file filename."""
142
 
    return osutils.pathjoin(config_dir(), 'locations.conf')
143
 
 
144
 
 
145
 
def authentication_config_path():
146
 
    """Return per-user authentication ini file filename."""
147
 
    return osutils.pathjoin(config_dir(), 'authentication.conf')
148
 
 
149
 
 
150
 
def user_ignore_config_path():
151
 
    """Return per-user authentication ini file filename."""
152
 
    return osutils.pathjoin(config_dir(), 'ignore')
153
 
 
154
 
 
155
 
def crash_dir():
156
 
    """Return the directory name to store crash files.
157
 
 
158
 
    This doesn't implicitly create it.
159
 
 
160
 
    On Windows it's in the config directory; elsewhere it's /var/crash
161
 
    which may be monitored by apport.  It can be overridden by
162
 
    $APPORT_CRASH_DIR.
163
 
    """
164
 
    if sys.platform == 'win32':
165
 
        return osutils.pathjoin(config_dir(), 'Crash')
166
 
    else:
167
 
        # XXX: hardcoded in apport_python_hook.py; therefore here too -- mbp
168
 
        # 2010-01-31
169
 
        return os.environ.get('APPORT_CRASH_DIR', '/var/crash')
170
 
 
171
 
 
172
 
def cache_dir():
173
 
    """Return the cache directory to use."""
174
 
    base = osutils.path_from_environ('BRZ_HOME')
175
 
    if sys.platform in "win32":
176
 
        if base is None:
177
 
            base = win32utils.get_local_appdata_location()
178
 
        if base is None:
179
 
            base = win32utils.get_home_location()
180
 
    else:
181
 
        base = osutils.path_from_environ('XDG_CACHE_HOME')
182
 
        if base is None:
183
 
            base = osutils.pathjoin(osutils._get_home_dir(), ".cache")
184
 
 
185
 
    cache_dir = osutils.pathjoin(base, "breezy")
186
 
 
187
 
    # GZ 2019-06-15: Move responsibility for ensuring dir exists elsewhere?
188
 
    if not os.path.exists(cache_dir):
189
 
        os.makedirs(cache_dir)
190
 
 
191
 
    return cache_dir
192
 
 
193
 
 
194
 
def _get_default_mail_domain(mailname_file='/etc/mailname'):
195
 
    """If possible, return the assumed default email domain.
196
 
 
197
 
    :returns: string mail domain, or None.
198
 
    """
199
 
    if sys.platform == 'win32':
200
 
        # No implementation yet; patches welcome
201
 
        return None
202
 
    try:
203
 
        f = open(mailname_file)
204
 
    except (IOError, OSError):
205
 
        return None
206
 
    try:
207
 
        domain = f.readline().strip()
208
 
        return domain
209
 
    finally:
210
 
        f.close()
211
 
 
212
 
 
213
 
def default_email():
214
 
    v = os.environ.get('BRZ_EMAIL')
215
 
    if v:
216
 
        if not PY3:
217
 
            v = v.decode(osutils.get_user_encoding())
218
 
        return v
219
 
    v = os.environ.get('EMAIL')
220
 
    if v:
221
 
        if not PY3:
222
 
            v = v.decode(osutils.get_user_encoding())
223
 
        return v
224
 
    name, email = _auto_user_id()
225
 
    if name and email:
226
 
        return u'%s <%s>' % (name, email)
227
 
    elif email:
228
 
        return email
229
 
    raise errors.NoWhoami()
230
 
 
231
 
 
232
 
def _auto_user_id():
233
 
    """Calculate automatic user identification.
234
 
 
235
 
    :returns: (realname, email), either of which may be None if they can't be
236
 
    determined.
237
 
 
238
 
    Only used when none is set in the environment or the id file.
239
 
 
240
 
    This only returns an email address if we can be fairly sure the
241
 
    address is reasonable, ie if /etc/mailname is set on unix.
242
 
 
243
 
    This doesn't use the FQDN as the default domain because that may be
244
 
    slow, and it doesn't use the hostname alone because that's not normally
245
 
    a reasonable address.
246
 
    """
247
 
    if sys.platform == 'win32':
248
 
        # No implementation to reliably determine Windows default mail
249
 
        # address; please add one.
250
 
        return None, None
251
 
 
252
 
    default_mail_domain = _get_default_mail_domain()
253
 
    if not default_mail_domain:
254
 
        return None, None
255
 
 
256
 
    import pwd
257
 
    uid = os.getuid()
258
 
    try:
259
 
        w = pwd.getpwuid(uid)
260
 
    except KeyError:
261
 
        trace.mutter('no passwd entry for uid %d?' % uid)
262
 
        return None, None
263
 
 
264
 
    # we try utf-8 first, because on many variants (like Linux),
265
 
    # /etc/passwd "should" be in utf-8, and because it's unlikely to give
266
 
    # false positives.  (many users will have their user encoding set to
267
 
    # latin-1, which cannot raise UnicodeError.)
268
 
    gecos = w.pw_gecos
269
 
    if isinstance(gecos, bytes):
270
 
        try:
271
 
            gecos = gecos.decode('utf-8')
272
 
            encoding = 'utf-8'
273
 
        except UnicodeError:
274
 
            try:
275
 
                encoding = osutils.get_user_encoding()
276
 
                gecos = gecos.decode(encoding)
277
 
            except UnicodeError:
278
 
                trace.mutter("cannot decode passwd entry %s" % w)
279
 
                return None, None
280
 
 
281
 
    username = w.pw_name
282
 
    if isinstance(username, bytes):
283
 
        try:
284
 
            username = username.decode(encoding)
285
 
        except UnicodeError:
286
 
            trace.mutter("cannot decode passwd entry %s" % w)
287
 
            return None, None
288
 
 
289
 
    comma = gecos.find(',')
290
 
    if comma == -1:
291
 
        realname = gecos
292
 
    else:
293
 
        realname = gecos[:comma]
294
 
 
295
 
    return realname, (username + '@' + default_mail_domain)