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, errno, sys
19
import os, types, re, time, types
20
20
from stat import S_ISREG, S_ISDIR, S_ISLNK, ST_MODE, ST_SIZE
22
from errors import bailout, BzrError
23
from trace import mutter
22
from errors import bailout
26
24
def make_readonly(filename):
27
25
"""Make a filename read-only."""
86
84
"""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.
88
return file('/proc/sys/kernel/random/uuid').readline().rstrip('\n')
90
return chomp(file('/proc/sys/kernel/random/uuid').readline())
90
92
return chomp(os.popen('uuidgen').readline())
96
if s and (s[-1] == '\n'):
104
## TODO: Maybe read in chunks to handle big files
95
105
if hasattr(f, 'tell'):
96
106
assert f.tell() == 0
104
109
return s.hexdigest()
122
127
'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
132
"""Return email-style username.
134
Something similar to 'Martin Pool <mbp@sourcefrog.net>'
136
:todo: Check it's reasonably well-formed.
138
:todo: Allow taking it from a dotfile to help people on windows
139
who can't easily set variables.
141
:todo: Cope without pwd module, which is only on unix.
143
e = os.environ.get('BZREMAIL') or os.environ.get('EMAIL')
148
# XXX: Any good way to get real user name on win32?
152
150
uid = os.getuid()
153
151
w = pwd.getpwuid(uid)
154
gecos = w.pw_gecos.decode(bzrlib.user_encoding)
155
username = w.pw_name.decode(bzrlib.user_encoding)
156
153
comma = gecos.find(',')
160
157
realname = gecos[:comma]
158
return '%s <%s@%s>' % (realname, w.pw_name, socket.getfqdn())
164
159
except ImportError:
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+.-]+')
162
import getpass, socket
163
return '<%s@%s>' % (getpass.getuser(), socket.getfqdn())
215
166
def user_email():
216
167
"""Return just the email component of a username."""
168
e = os.environ.get('BZREMAIL') or os.environ.get('EMAIL')
219
m = _EMAIL_RE.search(e)
171
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
221
bailout("%r doesn't seem to contain a reasonable email address" % e)
173
bailout('%r is not a reasonable email address' % e)
222
174
return m.group(0)
224
return _auto_user_id()[1]
177
import getpass, socket
178
return '%s@%s' % (getpass.getuser(), socket.getfqdn())
228
183
def compare_files(a, b):
229
184
"""Returns true if equal in contents"""
185
# TODO: don't read the whole thing in one go.
232
188
ai = a.read(BUFSIZE)
286
244
if hasattr(os, 'urandom'): # python 2.4 and later
287
245
rand_bytes = os.urandom
288
elif sys.platform == 'linux2':
289
rand_bytes = file('/dev/urandom', 'rb').read
291
# not well seeded, but better than nothing
296
s += chr(random.randint(0, 255))
247
# FIXME: No good on non-Linux
248
_rand_file = file('/dev/urandom', 'rb')
249
rand_bytes = _rand_file.read
301
252
## TODO: We could later have path objects that remember their list
318
269
BzrError: ("sorry, '..' not allowed in path", [])
320
271
assert isinstance(p, types.StringTypes)
322
# split on either delimiter because people might use either on
324
ps = re.split(r'[\\/]', p)
272
ps = [f for f in p.split('/') if f != '.']
329
275
bailout("sorry, %r not allowed in path" % f)
330
elif (f == '.') or (f == ''):
337
279
assert isinstance(p, list)
339
if (f == '..') or (f == None) or (f == ''):
281
if (f == '..') or (f is None) or (f == ''):
340
282
bailout("sorry, %r not allowed in path" % f)
341
return os.path.join(*p)
344
286
def appendpath(p1, p2):
348
return os.path.join(p1, p2)
351
293
def extern_command(cmd, ignore_errors = False):