~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: aaron.bentley at utoronto
  • Date: 2005-08-19 12:06:01 UTC
  • mto: (1092.1.41) (1185.3.4) (974.1.47)
  • mto: This revision was merged to the branch mainline in revision 1110.
  • Revision ID: aaron.bentley@utoronto.ca-20050819120601-58525b75283a9c1c
Initial greedy fetch work

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
    os.chmod(filename, mod)
38
38
 
39
39
 
40
 
_QUOTE_RE = None
 
40
_QUOTE_RE = re.compile(r'([^a-zA-Z0-9.,:/_~-])')
41
41
 
 
42
_SLASH_RE = re.compile(r'[\\/]+')
42
43
 
43
44
def quotefn(f):
44
45
    """Return a quoted filename filename
46
47
    This previously used backslash quoting, but that works poorly on
47
48
    Windows."""
48
49
    # TODO: I'm not really sure this is the best format either.x
49
 
    global _QUOTE_RE
50
 
    if _QUOTE_RE == None:
51
 
        _QUOTE_RE = re.compile(r'([^a-zA-Z0-9.,:/_~-])')
52
 
        
53
50
    if _QUOTE_RE.search(f):
54
51
        return '"' + f + '"'
55
52
    else:
272
269
    return realname, (username + '@' + socket.gethostname())
273
270
 
274
271
 
275
 
def _get_user_id(branch):
 
272
def _get_user_id():
276
273
    """Return the full user id from a file or environment variable.
277
274
 
278
 
    e.g. "John Hacker <jhacker@foo.org>"
279
 
 
280
 
    branch
281
 
        A branch to use for a per-branch configuration, or None.
282
 
 
283
 
    The following are searched in order:
284
 
 
285
 
    1. $BZREMAIL
286
 
    2. .bzr/email for this branch.
287
 
    3. ~/.bzr.conf/email
288
 
    4. $EMAIL
289
 
    """
 
275
    TODO: Allow taking this from a file in the branch directory too
 
276
    for per-branch ids."""
290
277
    v = os.environ.get('BZREMAIL')
291
278
    if v:
292
279
        return v.decode(bzrlib.user_encoding)
293
 
 
294
 
    if branch:
295
 
        try:
296
 
            return (branch.controlfile("email", "r") 
297
 
                    .read()
298
 
                    .decode(bzrlib.user_encoding)
299
 
                    .rstrip("\r\n"))
300
 
        except IOError, e:
301
 
            if e.errno != errno.ENOENT:
302
 
                raise
303
 
        except BzrError, e:
304
 
            pass
305
280
    
306
281
    try:
307
282
        return (open(os.path.join(config_dir(), "email"))
319
294
        return None
320
295
 
321
296
 
322
 
def username(branch):
 
297
def username():
323
298
    """Return email-style username.
324
299
 
325
300
    Something similar to 'Martin Pool <mbp@sourcefrog.net>'
326
301
 
327
302
    TODO: Check it's reasonably well-formed.
328
303
    """
329
 
    v = _get_user_id(branch)
 
304
    v = _get_user_id()
330
305
    if v:
331
306
        return v
332
307
    
337
312
        return email
338
313
 
339
314
 
340
 
def user_email(branch):
 
315
_EMAIL_RE = re.compile(r'[\w+.-]+@[\w+.-]+')
 
316
def user_email():
341
317
    """Return just the email component of a username."""
342
 
    e = _get_user_id(branch)
 
318
    e = _get_user_id()
343
319
    if e:
344
 
        m = re.search(r'[\w+.-]+@[\w+.-]+', e)
 
320
        m = _EMAIL_RE.search(e)
345
321
        if not m:
346
322
            raise BzrError("%r doesn't seem to contain a reasonable email address" % e)
347
323
        return m.group(0)
492
468
        raise
493
469
 
494
470
 
 
471
def _get_editor():
 
472
    """Return a sequence of possible editor binaries for the current platform"""
 
473
    e = _read_config_value("editor")
 
474
    if e is not None:
 
475
        yield e
 
476
        
 
477
    if os.name == "windows":
 
478
        yield "notepad.exe"
 
479
    elif os.name == "posix":
 
480
        try:
 
481
            yield os.environ["EDITOR"]
 
482
        except KeyError:
 
483
            yield "/usr/bin/vi"
 
484
 
 
485
 
 
486
def _run_editor(filename):
 
487
    """Try to execute an editor to edit the commit message. Returns True on success,
 
488
    False on failure"""
 
489
    for e in _get_editor():
 
490
        x = os.spawnvp(os.P_WAIT, e, (e, filename))
 
491
        if x == 0:
 
492
            return True
 
493
        elif x == 127:
 
494
            continue
 
495
        else:
 
496
            break
 
497
    raise BzrError("Could not start any editor. Please specify $EDITOR or use ~/.bzr.conf/editor")
 
498
    return False
 
499
                          
 
500
 
 
501
def get_text_message(infotext, ignoreline = "default"):
 
502
    import tempfile
 
503
    
 
504
    if ignoreline == "default":
 
505
        ignoreline = "-- This line and the following will be ignored --"
 
506
        
 
507
    try:
 
508
        tmp_fileno, msgfilename = tempfile.mkstemp()
 
509
        msgfile = os.close(tmp_fileno)
 
510
        if infotext is not None and infotext != "":
 
511
            hasinfo = True
 
512
            msgfile = file(msgfilename, "w")
 
513
            msgfile.write("\n\n%s\n\n%s" % (ignoreline, infotext))
 
514
            msgfile.close()
 
515
        else:
 
516
            hasinfo = False
 
517
 
 
518
        if not _run_editor(msgfilename):
 
519
            return None
 
520
        
 
521
        started = False
 
522
        msg = []
 
523
        lastline, nlines = 0, 0
 
524
        for line in file(msgfilename, "r"):
 
525
            stripped_line = line.strip()
 
526
            # strip empty line before the log message starts
 
527
            if not started:
 
528
                if stripped_line != "":
 
529
                    started = True
 
530
                else:
 
531
                    continue
 
532
            # check for the ignore line only if there
 
533
            # is additional information at the end
 
534
            if hasinfo and stripped_line == ignoreline:
 
535
                break
 
536
            nlines += 1
 
537
            # keep track of the last line that had some content
 
538
            if stripped_line != "":
 
539
                lastline = nlines
 
540
            msg.append(line)
 
541
            
 
542
        if len(msg) == 0:
 
543
            return None
 
544
        # delete empty lines at the end
 
545
        del msg[lastline:]
 
546
        # add a newline at the end, if needed
 
547
        if not msg[-1].endswith("\n"):
 
548
            return "%s%s" % ("".join(msg), "\n")
 
549
        else:
 
550
            return "".join(msg)
 
551
    finally:
 
552
        # delete the msg file in any case
 
553
        try: os.unlink(msgfilename)
 
554
        except IOError: pass