/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: 2020-04-05 19:11:34 UTC
  • mto: (7490.7.16 work)
  • mto: This revision was merged to the branch mainline in revision 7501.
  • Revision ID: jelmer@jelmer.uk-20200405191134-0aebh8ikiwygxma5
Populate the .gitignore file.

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)