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
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
22
from errors import bailout
22
from errors import bailout, BzrError
23
from trace import mutter
24
26
def make_readonly(filename):
25
27
"""Make a filename read-only."""
84
86
"""Return a new UUID"""
86
## XXX: Could alternatively read /proc/sys/kernel/random/uuid on
87
## Linux, but we need something portable for other systems;
88
## preferably an implementation in Python.
89
bailout('uuids not allowed!')
90
return chomp(os.popen('uuidgen').readline())
93
if s and (s[-1] == '\n'):
88
return file('/proc/sys/kernel/random/uuid').readline().rstrip('\n')
90
return chomp(os.popen('uuidgen').readline())
101
## TODO: Maybe read in chunks to handle big files
102
95
if hasattr(f, 'tell'):
103
96
assert f.tell() == 0
106
104
return s.hexdigest()
118
"""Return email-style username.
120
Something similar to 'Martin Pool <mbp@sourcefrog.net>'
122
:todo: Check it's reasonably well-formed.
124
:todo: Allow taking it from a dotfile to help people on windows
125
who can't easily set variables.
127
:todo: Cope without pwd module, which is only on unix.
129
e = os.environ.get('BZREMAIL') or os.environ.get('EMAIL')
115
def fingerprint_file(f):
121
return {'size': size,
122
'sha1': s.hexdigest()}
126
"""Return per-user configuration directory.
128
By default this is ~/.bzr.conf/
130
TODO: Global option --config-dir to override this.
132
return os.path.expanduser("~/.bzr.conf")
136
"""Calculate automatic user identification.
138
Returns (realname, email).
140
Only used when none is set in the environment or the id file.
142
This previously used the FQDN as the default domain, but that can
143
be very slow on machines where DNS is broken. So now we simply
148
# XXX: Any good way to get real user name on win32?
136
152
uid = os.getuid()
137
153
w = pwd.getpwuid(uid)
154
gecos = w.pw_gecos.decode(bzrlib.user_encoding)
155
username = w.pw_name.decode(bzrlib.user_encoding)
139
156
comma = gecos.find(',')
143
160
realname = gecos[:comma]
144
return '%s <%s@%s>' % (realname, w.pw_name, socket.getfqdn())
145
164
except ImportError:
148
import getpass, socket
149
return '<%s@%s>' % (getpass.getuser(), socket.getfqdn())
166
realname = username = getpass.getuser().decode(bzrlib.user_encoding)
168
return realname, (username + '@' + socket.gethostname())
172
"""Return the full user id from a file or environment variable.
174
TODO: Allow taking this from a file in the branch directory too
175
for per-branch ids."""
176
v = os.environ.get('BZREMAIL')
178
return v.decode(bzrlib.user_encoding)
181
return (open(os.path.join(config_dir(), "email"))
183
.decode(bzrlib.user_encoding)
186
if e.errno != errno.ENOENT:
189
v = os.environ.get('EMAIL')
191
return v.decode(bzrlib.user_encoding)
197
"""Return email-style username.
199
Something similar to 'Martin Pool <mbp@sourcefrog.net>'
201
TODO: Check it's reasonably well-formed.
207
name, email = _auto_user_id()
209
return '%s <%s>' % (name, email)
214
_EMAIL_RE = re.compile(r'[\w+.-]+@[\w+.-]+')
152
215
def user_email():
153
216
"""Return just the email component of a username."""
154
e = os.environ.get('BZREMAIL') or os.environ.get('EMAIL')
157
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
219
m = _EMAIL_RE.search(e)
159
bailout('%r is not a reasonable email address' % e)
221
bailout("%r doesn't seem to contain a reasonable email address" % e)
160
222
return m.group(0)
163
import getpass, socket
164
return '%s@%s' % (getpass.getuser(), socket.getfqdn())
224
return _auto_user_id()[1]
169
228
def compare_files(a, b):
170
229
"""Returns true if equal in contents"""
171
# TODO: don't read the whole thing in one go.
172
result = a.read() == b.read()
177
def local_time_offset():
241
def local_time_offset(t=None):
242
"""Return offset of local zone from GMT, either at present or at time t."""
243
# python2.3 localtime() can't take None
247
if time.localtime(t).tm_isdst and time.daylight:
179
248
return -time.altzone
181
250
return -time.timezone
244
311
BzrError: ("sorry, '..' not allowed in path", [])
246
313
assert isinstance(p, types.StringTypes)
247
ps = [f for f in p.split('/') if f != '.']
315
# split on either delimiter because people might use either on
317
ps = re.split(r'[\\/]', p)
250
322
bailout("sorry, %r not allowed in path" % f)
323
elif (f == '.') or (f == ''):
254
330
assert isinstance(p, list)
256
if (f == '..') or (f is None) or (f == ''):
332
if (f == '..') or (f == None) or (f == ''):
257
333
bailout("sorry, %r not allowed in path" % f)
334
return os.path.join(*p)
261
337
def appendpath(p1, p2):
341
return os.path.join(p1, p2)
268
344
def extern_command(cmd, ignore_errors = False):