~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: Martin Pool
  • Date: 2005-04-15 03:28:29 UTC
  • Revision ID: mbp@sourcefrog.net-20050415032829-4fcd42b8ff201ed9
- better reporting of errors
- handle assertions specially

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
# along with this program; if not, write to the Free Software
17
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
18
 
19
 
import os, types, re, time, types
 
19
import os, types, re, time, errno
20
20
from stat import S_ISREG, S_ISDIR, S_ISLNK, ST_MODE, ST_SIZE
21
21
 
22
 
from errors import bailout
 
22
from errors import bailout, BzrError
 
23
from trace import mutter
 
24
import bzrlib
23
25
 
24
26
def make_readonly(filename):
25
27
    """Make a filename read-only."""
54
56
    elif S_ISLNK(mode):
55
57
        return 'symlink'
56
58
    else:
57
 
        bailout("can't handle file kind with mode %o of %r" % (mode, f)) 
 
59
        raise BzrError("can't handle file kind with mode %o of %r" % (mode, f)) 
58
60
 
59
61
 
60
62
 
117
119
 
118
120
 
119
121
 
120
 
def username():
121
 
    """Return email-style username.
122
 
 
123
 
    Something similar to 'Martin Pool <mbp@sourcefrog.net>'
124
 
 
125
 
    :todo: Check it's reasonably well-formed.
126
 
 
127
 
    :todo: Allow taking it from a dotfile to help people on windows
128
 
           who can't easily set variables.
129
 
 
130
 
    :todo: Cope without pwd module, which is only on unix. 
131
 
    """
132
 
    e = os.environ.get('BZREMAIL') or os.environ.get('EMAIL')
133
 
    if e: return e
134
 
 
 
122
def fingerprint_file(f):
 
123
    import sha
 
124
    s = sha.new()
 
125
    b = f.read()
 
126
    s.update(b)
 
127
    size = len(b)
 
128
    return {'size': size,
 
129
            'sha1': s.hexdigest()}
 
130
 
 
131
 
 
132
def config_dir():
 
133
    """Return per-user configuration directory.
 
134
 
 
135
    By default this is ~/.bzr.conf/
 
136
    
 
137
    TODO: Global option --config-dir to override this.
 
138
    """
 
139
    return os.path.expanduser("~/.bzr.conf")
 
140
 
 
141
 
 
142
def _auto_user_id():
 
143
    """Calculate automatic user identification.
 
144
 
 
145
    Returns (realname, email).
 
146
 
 
147
    Only used when none is set in the environment or the id file.
 
148
 
 
149
    This previously used the FQDN as the default domain, but that can
 
150
    be very slow on machines where DNS is broken.  So now we simply
 
151
    use the hostname.
 
152
    """
135
153
    import socket
136
 
    
 
154
 
 
155
    # XXX: Any good way to get real user name on win32?
 
156
 
137
157
    try:
138
158
        import pwd
139
159
        uid = os.getuid()
140
160
        w = pwd.getpwuid(uid)
141
 
        gecos = w.pw_gecos
 
161
        gecos = w.pw_gecos.decode(bzrlib.user_encoding)
 
162
        username = w.pw_name.decode(bzrlib.user_encoding)
142
163
        comma = gecos.find(',')
143
164
        if comma == -1:
144
165
            realname = gecos
145
166
        else:
146
167
            realname = gecos[:comma]
147
 
        return '%s <%s@%s>' % (realname, w.pw_name, socket.getfqdn())
 
168
        if not realname:
 
169
            realname = username
 
170
 
148
171
    except ImportError:
149
 
        pass
150
 
 
151
 
    import getpass, socket
152
 
    return '<%s@%s>' % (getpass.getuser(), socket.getfqdn())
153
 
 
154
 
 
 
172
        import getpass
 
173
        realname = username = getpass.getuser().decode(bzrlib.user_encoding)
 
174
 
 
175
    return realname, (username + '@' + socket.gethostname())
 
176
 
 
177
 
 
178
def _get_user_id():
 
179
    """Return the full user id from a file or environment variable.
 
180
 
 
181
    TODO: Allow taking this from a file in the branch directory too
 
182
    for per-branch ids."""
 
183
    v = os.environ.get('BZREMAIL')
 
184
    if v:
 
185
        return v.decode(bzrlib.user_encoding)
 
186
    
 
187
    try:
 
188
        return (open(os.path.join(config_dir(), "email"))
 
189
                .read()
 
190
                .decode(bzrlib.user_encoding)
 
191
                .rstrip("\r\n"))
 
192
    except IOError, e:
 
193
        if e.errno != errno.ENOENT:
 
194
            raise e
 
195
 
 
196
    v = os.environ.get('EMAIL')
 
197
    if v:
 
198
        return v.decode(bzrlib.user_encoding)
 
199
    else:    
 
200
        return None
 
201
 
 
202
 
 
203
def username():
 
204
    """Return email-style username.
 
205
 
 
206
    Something similar to 'Martin Pool <mbp@sourcefrog.net>'
 
207
 
 
208
    TODO: Check it's reasonably well-formed.
 
209
    """
 
210
    v = _get_user_id()
 
211
    if v:
 
212
        return v
 
213
    
 
214
    name, email = _auto_user_id()
 
215
    if name:
 
216
        return '%s <%s>' % (name, email)
 
217
    else:
 
218
        return email
 
219
 
 
220
 
 
221
_EMAIL_RE = re.compile(r'[\w+.-]+@[\w+.-]+')
155
222
def user_email():
156
223
    """Return just the email component of a username."""
157
 
    e = os.environ.get('BZREMAIL') or os.environ.get('EMAIL')
 
224
    e = _get_user_id()
158
225
    if e:
159
 
        import re
160
 
        m = re.search(r'[\w+.-]+@[\w+.-]+', e)
 
226
        m = _EMAIL_RE.search(e)
161
227
        if not m:
162
 
            bailout('%r is not a reasonable email address' % e)
 
228
            bailout("%r doesn't seem to contain a reasonable email address" % e)
163
229
        return m.group(0)
164
230
 
165
 
 
166
 
    import getpass, socket
167
 
    return '%s@%s' % (getpass.getuser(), socket.getfqdn())
168
 
 
 
231
    return _auto_user_id()[1]
169
232
    
170
233
 
171
234
 
186
249
def local_time_offset(t=None):
187
250
    """Return offset of local zone from GMT, either at present or at time t."""
188
251
    # python2.3 localtime() can't take None
189
 
    if t is None:
 
252
    if t == None:
190
253
        t = time.time()
191
254
        
192
255
    if time.localtime(t).tm_isdst and time.daylight:
198
261
def format_date(t, offset=0, timezone='original'):
199
262
    ## TODO: Perhaps a global option to use either universal or local time?
200
263
    ## Or perhaps just let people set $TZ?
201
 
    import time
202
 
    
203
264
    assert isinstance(t, float)
204
265
    
205
266
    if timezone == 'utc':
258
319
    BzrError: ("sorry, '..' not allowed in path", [])
259
320
    """
260
321
    assert isinstance(p, types.StringTypes)
261
 
    ps = [f for f in p.split('/') if f != '.']
 
322
    ps = [f for f in p.split('/') if (f != '.' and f != '')]
262
323
    for f in ps:
263
324
        if f == '..':
264
325
            bailout("sorry, %r not allowed in path" % f)
267
328
def joinpath(p):
268
329
    assert isinstance(p, list)
269
330
    for f in p:
270
 
        if (f == '..') or (f is None) or (f == ''):
 
331
        if (f == '..') or (f == None) or (f == ''):
271
332
            bailout("sorry, %r not allowed in path" % f)
272
333
    return '/'.join(p)
273
334