/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: 2019-07-12 01:01:45 UTC
  • mto: This revision was merged to the branch mainline in revision 7375.
  • Revision ID: jelmer@jelmer.uk-20190712010145-m7224qumb8w068zw
Fix importing from remote git repositories.

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