mercurial/util.py
author Thomas Arendsen Hein <thomas@intevation.de>
Mon, 06 Mar 2006 17:47:41 +0100
changeset 1839 876e4e6ad82b
parent 1835 bdfb524d728a
child 1877 d314a89fa4f1
permissions -rw-r--r--
Create local ui object per repository, so .hg/hgrc don't get mixed. This is needed for hooks, but may be important for other settings, too. Fixes issue113, also integrated push-hook-lock.sh as a test case for this.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
     1
"""
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
     2
util.py - Mercurial utility functions and platform specfic implementations
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
     3
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
     4
 Copyright 2005 K. Thananchayan <thananck@yahoo.com>
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
     5
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
     6
This software may be used and distributed according to the terms
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
     7
of the GNU General Public License, incorporated herein by reference.
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
     8
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
     9
This contains helper routines that are independent of the SCM core and hide
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
    10
platform-specific details from the core.
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
    11
"""
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
    12
704
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
    13
import os, errno
1400
cf9a1233738a i18n first part: make '_' available for files who need it
Benoit Boissinot <benoit.boissinot@ens-lyon.org
parents: 1399
diff changeset
    14
from i18n import gettext as _
724
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
    15
from demandload import *
1609
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
    16
demandload(globals(), "cStringIO errno popen2 re shutil sys tempfile")
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
    17
demandload(globals(), "threading time")
1258
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    18
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    19
def pipefilter(s, cmd):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    20
    '''filter string S through command CMD, returning its output'''
1258
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    21
    (pout, pin) = popen2.popen2(cmd, -1, 'b')
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    22
    def writer():
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    23
        pin.write(s)
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    24
        pin.close()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    25
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    26
    # we should use select instead on UNIX, but this will work on most
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    27
    # systems, including Windows
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    28
    w = threading.Thread(target=writer)
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    29
    w.start()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    30
    f = pout.read()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    31
    pout.close()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    32
    w.join()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    33
    return f
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
    34
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    35
def tempfilter(s, cmd):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    36
    '''filter string S through a pair of temporary files with CMD.
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    37
    CMD is used as a template to create the real command to be run,
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    38
    with the strings INFILE and OUTFILE replaced by the real names of
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    39
    the temporary files generated.'''
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    40
    inname, outname = None, None
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    41
    try:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    42
        infd, inname = tempfile.mkstemp(prefix='hgfin')
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    43
        fp = os.fdopen(infd, 'wb')
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    44
        fp.write(s)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    45
        fp.close()
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    46
        outfd, outname = tempfile.mkstemp(prefix='hgfout')
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    47
        os.close(outfd)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    48
        cmd = cmd.replace('INFILE', inname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    49
        cmd = cmd.replace('OUTFILE', outname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    50
        code = os.system(cmd)
1402
9d2c2e6b32b5 i18n part2: use '_' for all strings who are part of the user interface
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1400
diff changeset
    51
        if code: raise Abort(_("command '%s' failed: %s") %
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    52
                             (cmd, explain_exit(code)))
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    53
        return open(outname, 'rb').read()
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    54
    finally:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    55
        try:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    56
            if inname: os.unlink(inname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    57
        except: pass
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    58
        try:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    59
            if outname: os.unlink(outname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    60
        except: pass
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    61
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    62
filtertable = {
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    63
    'tempfile:': tempfilter,
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    64
    'pipe:': pipefilter,
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    65
    }
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    66
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    67
def filter(s, cmd):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    68
    "filter a string through a command that transforms its input to its output"
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    69
    for name, fn in filtertable.iteritems():
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    70
        if cmd.startswith(name):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    71
            return fn(s, cmd[len(name):].lstrip())
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    72
    return pipefilter(s, cmd)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    73
1285
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    74
def patch(strip, patchname, ui):
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    75
    """apply the patch <patchname> to the working directory.
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    76
    a list of patched files is returned"""
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    77
    fp = os.popen('patch -p%d < "%s"' % (strip, patchname))
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    78
    files = {}
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    79
    for line in fp:
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    80
        line = line.rstrip()
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    81
        ui.status("%s\n" % line)
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    82
        if line.startswith('patching file '):
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    83
            pf = parse_patch_output(line)
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    84
            files.setdefault(pf, 1)
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    85
    code = fp.close()
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    86
    if code:
1402
9d2c2e6b32b5 i18n part2: use '_' for all strings who are part of the user interface
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1400
diff changeset
    87
        raise Abort(_("patch command failed: %s") % explain_exit(code)[0])
1285
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    88
    return files.keys()
1308
2073e5a71008 Cleanup of tabs and trailing spaces.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1285
diff changeset
    89
1015
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
    90
def binary(s):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
    91
    """return true if a string is binary data using diff's heuristic"""
1015
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
    92
    if s and '\0' in s[:4096]:
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
    93
        return True
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
    94
    return False
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
    95
556
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
    96
def unique(g):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
    97
    """return the uniq elements of iterable g"""
556
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
    98
    seen = {}
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
    99
    for f in g:
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   100
        if f not in seen:
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   101
            seen[f] = 1
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   102
            yield f
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   103
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   104
class Abort(Exception):
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   105
    """Raised if a command needs to print an error and exit."""
508
42a660abaf75 [PATCH] Harden os.system
mpm@selenic.com
parents: 464
diff changeset
   106
724
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   107
def always(fn): return True
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   108
def never(fn): return False
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   109
1563
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   110
def patkind(name, dflt_pat='glob'):
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   111
    """Split a string into an optional pattern kind prefix and the
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   112
    actual pattern."""
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   113
    for prefix in 're', 'glob', 'path', 'relglob', 'relpath', 'relre':
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   114
        if name.startswith(prefix + ':'): return name.split(':', 1)
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   115
    return dflt_pat, name
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   116
1062
6d5a62a549fa pep-0008 cleanup
benoit.boissinot@ens-lyon.fr
parents: 1031
diff changeset
   117
def globre(pat, head='^', tail='$'):
724
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   118
    "convert a glob pattern into a regexp"
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   119
    i, n = 0, len(pat)
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   120
    res = ''
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   121
    group = False
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   122
    def peek(): return i < n and pat[i]
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   123
    while i < n:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   124
        c = pat[i]
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   125
        i = i+1
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   126
        if c == '*':
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   127
            if peek() == '*':
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   128
                i += 1
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   129
                res += '.*'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   130
            else:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   131
                res += '[^/]*'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   132
        elif c == '?':
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   133
            res += '.'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   134
        elif c == '[':
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   135
            j = i
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   136
            if j < n and pat[j] in '!]':
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   137
                j += 1
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   138
            while j < n and pat[j] != ']':
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   139
                j += 1
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   140
            if j >= n:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   141
                res += '\\['
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   142
            else:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   143
                stuff = pat[i:j].replace('\\','\\\\')
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   144
                i = j + 1
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   145
                if stuff[0] == '!':
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   146
                    stuff = '^' + stuff[1:]
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   147
                elif stuff[0] == '^':
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   148
                    stuff = '\\' + stuff
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   149
                res = '%s[%s]' % (res, stuff)
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   150
        elif c == '{':
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   151
            group = True
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   152
            res += '(?:'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   153
        elif c == '}' and group:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   154
            res += ')'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   155
            group = False
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   156
        elif c == ',' and group:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   157
            res += '|'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   158
        else:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   159
            res += re.escape(c)
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   160
    return head + res + tail
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   161
812
b65af904d6d7 Reduce the amount of stat traffic generated by a walk.
Bryan O'Sullivan <bos@serpentine.com>
parents: 782
diff changeset
   162
_globchars = {'[': 1, '{': 1, '*': 1, '?': 1}
b65af904d6d7 Reduce the amount of stat traffic generated by a walk.
Bryan O'Sullivan <bos@serpentine.com>
parents: 782
diff changeset
   163
884
087771ebe2e6 Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents: 878
diff changeset
   164
def pathto(n1, n2):
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   165
    '''return the relative path from one place to another.
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   166
    this returns a path in the form used by the local filesystem, not hg.'''
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   167
    if not n1: return localpath(n2)
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   168
    a, b = n1.split('/'), n2.split('/')
1541
bf4e7ef08741 fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
twaldmann@thinkmo.de
parents: 1528
diff changeset
   169
    a.reverse()
bf4e7ef08741 fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
twaldmann@thinkmo.de
parents: 1528
diff changeset
   170
    b.reverse()
884
087771ebe2e6 Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents: 878
diff changeset
   171
    while a and b and a[-1] == b[-1]:
1541
bf4e7ef08741 fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
twaldmann@thinkmo.de
parents: 1528
diff changeset
   172
        a.pop()
bf4e7ef08741 fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
twaldmann@thinkmo.de
parents: 1528
diff changeset
   173
        b.pop()
884
087771ebe2e6 Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents: 878
diff changeset
   174
    b.reverse()
087771ebe2e6 Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents: 878
diff changeset
   175
    return os.sep.join((['..'] * len(a)) + b)
087771ebe2e6 Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents: 878
diff changeset
   176
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   177
def canonpath(root, cwd, myname):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   178
    """return the canonical path of myname, given cwd and root"""
1566
8befbb4e30b2 Handle hg under /
Arun Sharma <arun@sharma-home.net>
parents: 1563
diff changeset
   179
    if root == os.sep:
8befbb4e30b2 Handle hg under /
Arun Sharma <arun@sharma-home.net>
parents: 1563
diff changeset
   180
        rootsep = os.sep
8befbb4e30b2 Handle hg under /
Arun Sharma <arun@sharma-home.net>
parents: 1563
diff changeset
   181
    else:
1810
7596611ab3d5 Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1635
diff changeset
   182
        rootsep = root + os.sep
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   183
    name = myname
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   184
    if not name.startswith(os.sep):
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   185
        name = os.path.join(root, cwd, name)
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   186
    name = os.path.normpath(name)
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   187
    if name.startswith(rootsep):
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   188
        return pconvert(name[len(rootsep):])
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   189
    elif name == root:
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   190
        return ''
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   191
    else:
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   192
        raise Abort('%s not under root' % myname)
897
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   193
1610
84e9b3484ff6 if hgignore contains errors, print message that is not confusing.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1609
diff changeset
   194
def matcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head='', src=None):
84e9b3484ff6 if hgignore contains errors, print message that is not confusing.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1609
diff changeset
   195
    return _matcher(canonroot, cwd, names, inc, exc, head, 'glob', src)
1413
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   196
1610
84e9b3484ff6 if hgignore contains errors, print message that is not confusing.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1609
diff changeset
   197
def cmdmatcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head='', src=None):
1413
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   198
    if os.name == 'nt':
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   199
        dflt_pat = 'glob'
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   200
    else:
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   201
        dflt_pat = 'relpath'
1610
84e9b3484ff6 if hgignore contains errors, print message that is not confusing.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1609
diff changeset
   202
    return _matcher(canonroot, cwd, names, inc, exc, head, dflt_pat, src)
1413
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   203
1610
84e9b3484ff6 if hgignore contains errors, print message that is not confusing.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1609
diff changeset
   204
def _matcher(canonroot, cwd, names, inc, exc, head, dflt_pat, src):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   205
    """build a function to match a set of file patterns
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   206
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   207
    arguments:
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   208
    canonroot - the canonical root of the tree you're matching against
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   209
    cwd - the current working directory, if relevant
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   210
    names - patterns to find
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   211
    inc - patterns to include
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   212
    exc - patterns to exclude
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   213
    head - a regex to prepend to patterns to control whether a match is rooted
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   214
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   215
    a pattern is one of:
1270
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   216
    'glob:<rooted glob>'
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   217
    're:<rooted regexp>'
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   218
    'path:<rooted path>'
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   219
    'relglob:<relative glob>'
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   220
    'relpath:<relative path>'
1270
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   221
    'relre:<relative regexp>'
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   222
    '<rooted path or regexp>'
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   223
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   224
    returns:
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   225
    a 3-tuple containing
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   226
    - list of explicit non-pattern names passed in
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   227
    - a bool match(filename) function
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   228
    - a bool indicating if any patterns were passed in
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   229
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   230
    todo:
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   231
    make head regex a rooted bool
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   232
    """
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   233
1413
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   234
    def contains_glob(name):
812
b65af904d6d7 Reduce the amount of stat traffic generated by a walk.
Bryan O'Sullivan <bos@serpentine.com>
parents: 782
diff changeset
   235
        for c in name:
1413
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   236
            if c in _globchars: return True
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   237
        return False
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   238
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   239
    def regex(kind, name, tail):
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   240
        '''convert a pattern into a regular expression'''
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   241
        if kind == 're':
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   242
            return name
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   243
        elif kind == 'path':
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   244
            return '^' + re.escape(name) + '(?:/|$)'
1270
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   245
        elif kind == 'relglob':
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   246
            return head + globre(name, '(?:|.*/)', tail)
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   247
        elif kind == 'relpath':
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   248
            return head + re.escape(name) + tail
1270
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   249
        elif kind == 'relre':
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   250
            if name.startswith('^'):
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   251
                return name
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   252
            return '.*' + name
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   253
        return head + globre(name, '', tail)
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   254
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   255
    def matchfn(pats, tail):
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   256
        """build a matching function from a set of patterns"""
1454
f4250806dbeb further fix traceback on invalid .hgignore patterns
Benoit Boissinot <mercurial-bugs@selenic.com>
parents: 1446
diff changeset
   257
        if not pats:
f4250806dbeb further fix traceback on invalid .hgignore patterns
Benoit Boissinot <mercurial-bugs@selenic.com>
parents: 1446
diff changeset
   258
            return
1446
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   259
        matches = []
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   260
        for k, p in pats:
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   261
            try:
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   262
                pat = '(?:%s)' % regex(k, p, tail)
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   263
                matches.append(re.compile(pat).match)
1541
bf4e7ef08741 fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
twaldmann@thinkmo.de
parents: 1528
diff changeset
   264
            except re.error:
1611
301d5cd4abc6 make invalid pattern message not confusing.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1610
diff changeset
   265
                if src: raise Abort("%s: invalid pattern (%s): %s" % (src, k, p))
301d5cd4abc6 make invalid pattern message not confusing.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1610
diff changeset
   266
                else: raise Abort("invalid pattern (%s): %s" % (k, p))
1446
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   267
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   268
        def buildfn(text):
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   269
            for m in matches:
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   270
                r = m(text)
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   271
                if r:
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   272
                    return r
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   273
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   274
        return buildfn
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   275
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   276
    def globprefix(pat):
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   277
        '''return the non-glob prefix of a path, e.g. foo/* -> foo'''
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   278
        root = []
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   279
        for p in pat.split(os.sep):
1413
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   280
            if contains_glob(p): break
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   281
            root.append(p)
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   282
        return '/'.join(root)
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   283
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   284
    pats = []
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   285
    files = []
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   286
    roots = []
1413
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   287
    for kind, name in [patkind(p, dflt_pat) for p in names]:
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   288
        if kind in ('glob', 'relpath'):
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   289
            name = canonpath(canonroot, cwd, name)
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   290
            if name == '':
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   291
                kind, name = 'glob', '**'
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   292
        if kind in ('glob', 'path', 're'):
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   293
            pats.append((kind, name))
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   294
        if kind == 'glob':
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   295
            root = globprefix(name)
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   296
            if root: roots.append(root)
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   297
        elif kind == 'relpath':
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   298
            files.append((kind, name))
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   299
            roots.append(name)
897
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   300
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   301
    patmatch = matchfn(pats, '$') or always
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   302
    filematch = matchfn(files, '(?:/|$)') or always
897
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   303
    incmatch = always
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   304
    if inc:
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   305
        incmatch = matchfn(map(patkind, inc), '(?:/|$)')
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   306
    excmatch = lambda fn: False
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   307
    if exc:
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   308
        excmatch = matchfn(map(patkind, exc), '(?:/|$)')
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   309
1031
503aaf19a040 Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1015
diff changeset
   310
    return (roots,
503aaf19a040 Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1015
diff changeset
   311
            lambda fn: (incmatch(fn) and not excmatch(fn) and
503aaf19a040 Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1015
diff changeset
   312
                        (fn.endswith('/') or
503aaf19a040 Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1015
diff changeset
   313
                         (not pats and not files) or
503aaf19a040 Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1015
diff changeset
   314
                         (pats and patmatch(fn)) or
503aaf19a040 Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1015
diff changeset
   315
                         (files and filematch(fn)))),
503aaf19a040 Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1015
diff changeset
   316
            (inc or exc or (pats and pats != [('glob', '**')])) and True)
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   317
521
0fb8ade0f756 [PATCH] Fix use of util.CommandError
mpm@selenic.com
parents: 515
diff changeset
   318
def system(cmd, errprefix=None):
508
42a660abaf75 [PATCH] Harden os.system
mpm@selenic.com
parents: 464
diff changeset
   319
    """execute a shell command that must succeed"""
42a660abaf75 [PATCH] Harden os.system
mpm@selenic.com
parents: 464
diff changeset
   320
    rc = os.system(cmd)
42a660abaf75 [PATCH] Harden os.system
mpm@selenic.com
parents: 464
diff changeset
   321
    if rc:
521
0fb8ade0f756 [PATCH] Fix use of util.CommandError
mpm@selenic.com
parents: 515
diff changeset
   322
        errmsg = "%s %s" % (os.path.basename(cmd.split(None, 1)[0]),
0fb8ade0f756 [PATCH] Fix use of util.CommandError
mpm@selenic.com
parents: 515
diff changeset
   323
                            explain_exit(rc)[0])
0fb8ade0f756 [PATCH] Fix use of util.CommandError
mpm@selenic.com
parents: 515
diff changeset
   324
        if errprefix:
0fb8ade0f756 [PATCH] Fix use of util.CommandError
mpm@selenic.com
parents: 515
diff changeset
   325
            errmsg = "%s: %s" % (errprefix, errmsg)
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   326
        raise Abort(errmsg)
508
42a660abaf75 [PATCH] Harden os.system
mpm@selenic.com
parents: 464
diff changeset
   327
421
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   328
def rename(src, dst):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   329
    """forcibly rename a file"""
421
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   330
    try:
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   331
        os.rename(src, dst)
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   332
    except:
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   333
        os.unlink(dst)
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   334
        os.rename(src, dst)
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   335
1415
c6e6ca96a033 refactor some unlink/remove code and make sure we prune empty dir
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1413
diff changeset
   336
def unlink(f):
c6e6ca96a033 refactor some unlink/remove code and make sure we prune empty dir
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1413
diff changeset
   337
    """unlink and remove the directory if it is empty"""
c6e6ca96a033 refactor some unlink/remove code and make sure we prune empty dir
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1413
diff changeset
   338
    os.unlink(f)
c6e6ca96a033 refactor some unlink/remove code and make sure we prune empty dir
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1413
diff changeset
   339
    # try removing directories that might now be empty
c6e6ca96a033 refactor some unlink/remove code and make sure we prune empty dir
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1413
diff changeset
   340
    try: os.removedirs(os.path.dirname(f))
c6e6ca96a033 refactor some unlink/remove code and make sure we prune empty dir
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1413
diff changeset
   341
    except: pass
c6e6ca96a033 refactor some unlink/remove code and make sure we prune empty dir
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1413
diff changeset
   342
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   343
def copyfiles(src, dst, hardlink=None):
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   344
    """Copy a directory tree using hardlinks if possible"""
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   345
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   346
    if hardlink is None:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   347
        hardlink = (os.stat(src).st_dev ==
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   348
                    os.stat(os.path.dirname(dst)).st_dev)
698
df78d8ccac4c Use python function instead of external 'cp' command when cloning repos.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 667
diff changeset
   349
1207
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   350
    if os.path.isdir(src):
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   351
        os.mkdir(dst)
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   352
        for name in os.listdir(src):
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   353
            srcname = os.path.join(src, name)
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   354
            dstname = os.path.join(dst, name)
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   355
            copyfiles(srcname, dstname, hardlink)
1207
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   356
    else:
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   357
        if hardlink:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   358
            try:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   359
                os_link(src, dst)
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   360
            except:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   361
                hardlink = False
1591
5a3229cf1492 do not copy atime and mtime in util.copyfiles
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1585
diff changeset
   362
                shutil.copy(src, dst)
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   363
        else:
1591
5a3229cf1492 do not copy atime and mtime in util.copyfiles
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1585
diff changeset
   364
            shutil.copy(src, dst)
698
df78d8ccac4c Use python function instead of external 'cp' command when cloning repos.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 667
diff changeset
   365
1835
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   366
def audit_path(path):
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   367
    """Abort if path contains dangerous components"""
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   368
    parts = os.path.normcase(path).split(os.sep)
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   369
    if (os.path.splitdrive(path)[0] or parts[0] in ('.hg', '')
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   370
        or os.pardir in parts):
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   371
        raise Abort(_("path contains illegal component: %s\n") % path)
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   372
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   373
def opener(base, audit=True):
1090
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   374
    """
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   375
    return a function that opens files relative to base
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   376
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   377
    this function is used to hide the details of COW semantics and
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   378
    remote file access from higher level code.
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   379
    """
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   380
    p = base
1835
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   381
    audit_p = audit
1528
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   382
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   383
    def mktempcopy(name):
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   384
        d, fn = os.path.split(name)
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   385
        fd, temp = tempfile.mkstemp(prefix=fn, dir=d)
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   386
        fp = os.fdopen(fd, "wb")
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   387
        try:
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   388
            fp.write(file(name, "rb").read())
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   389
        except:
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   390
            try: os.unlink(temp)
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   391
            except: pass
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   392
            raise
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   393
        fp.close()
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   394
        st = os.lstat(name)
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   395
        os.chmod(temp, st.st_mode)
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   396
        return temp
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   397
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   398
    class atomicfile(file):
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   399
        """the file will only be copied on close"""
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   400
        def __init__(self, name, mode, atomic=False):
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   401
            self.__name = name
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   402
            self.temp = mktempcopy(name)
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   403
            file.__init__(self, self.temp, mode)
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   404
        def close(self):
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   405
            if not self.closed:
1546
487e256ad545 close file before renaming it (since it doesn't work the other way on windows)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1541
diff changeset
   406
                file.close(self)
1528
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   407
                rename(self.temp, self.__name)
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   408
        def __del__(self):
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   409
            self.close()
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   410
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   411
    def o(path, mode="r", text=False, atomic=False):
1835
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   412
        if audit_p:
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   413
            audit_path(path)
1090
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   414
        f = os.path.join(p, path)
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   415
1329
8f06817bf266 Allow files to be opened in text mode, even on Windows.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1321
diff changeset
   416
        if not text:
8f06817bf266 Allow files to be opened in text mode, even on Windows.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1321
diff changeset
   417
            mode += "b" # for that other OS
1090
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   418
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   419
        if mode[0] != "r":
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   420
            try:
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   421
                nlink = nlinks(f)
1090
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   422
            except OSError:
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   423
                d = os.path.dirname(f)
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   424
                if not os.path.isdir(d):
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   425
                    os.makedirs(d)
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   426
            else:
1528
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   427
                if atomic:
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   428
                    return atomicfile(f, mode)
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   429
                if nlink > 1:
1528
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   430
                    rename(mktempcopy(f), f)
1090
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   431
        return file(f, mode)
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   432
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   433
    return o
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   434
704
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   435
def _makelock_file(info, pathname):
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   436
    ld = os.open(pathname, os.O_CREAT | os.O_WRONLY | os.O_EXCL)
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   437
    os.write(ld, info)
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   438
    os.close(ld)
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   439
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   440
def _readlock_file(pathname):
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   441
    return file(pathname).read()
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   442
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   443
def nlinks(pathname):
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   444
    """Return number of hardlinks for the given file."""
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   445
    return os.stat(pathname).st_nlink
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   446
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   447
if hasattr(os, 'link'):
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   448
    os_link = os.link
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   449
else:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   450
    def os_link(src, dst):
1402
9d2c2e6b32b5 i18n part2: use '_' for all strings who are part of the user interface
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1400
diff changeset
   451
        raise OSError(0, _("Hardlinks not supported"))
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   452
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   453
# Platform specific variants
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   454
if os.name == 'nt':
1420
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   455
    demandload(globals(), "msvcrt")
461
9ae0034f2772 [PATCH] /dev/null for other OS
mpm@selenic.com
parents: 441
diff changeset
   456
    nulldev = 'NUL:'
1609
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   457
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   458
    class winstdout:
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   459
        '''stdout on windows misbehaves if sent through a pipe'''
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   460
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   461
        def __init__(self, fp):
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   462
            self.fp = fp
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   463
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   464
        def __getattr__(self, key):
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   465
            return getattr(self.fp, key)
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   466
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   467
        def close(self):
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   468
            try:
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   469
                self.fp.close()
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   470
            except: pass
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   471
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   472
        def write(self, s):
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   473
            try:
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   474
                return self.fp.write(s)
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   475
            except IOError, inst:
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   476
                if inst.errno != 0: raise
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   477
                self.close()
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   478
                raise IOError(errno.EPIPE, 'Broken pipe')
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   479
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   480
    sys.stdout = winstdout(sys.stdout)
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   481
1399
9a70776e355e Try to use ini-file in the same directory as the exe as the default on NT.
Zbynek Winkler <zwin@users.sourceforge.net>
parents: 1391
diff changeset
   482
    try:
9a70776e355e Try to use ini-file in the same directory as the exe as the default on NT.
Zbynek Winkler <zwin@users.sourceforge.net>
parents: 1391
diff changeset
   483
        import win32api, win32process
9a70776e355e Try to use ini-file in the same directory as the exe as the default on NT.
Zbynek Winkler <zwin@users.sourceforge.net>
parents: 1391
diff changeset
   484
        filename = win32process.GetModuleFileNameEx(win32api.GetCurrentProcess(), 0)
9a70776e355e Try to use ini-file in the same directory as the exe as the default on NT.
Zbynek Winkler <zwin@users.sourceforge.net>
parents: 1391
diff changeset
   485
        systemrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
1609
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   486
1399
9a70776e355e Try to use ini-file in the same directory as the exe as the default on NT.
Zbynek Winkler <zwin@users.sourceforge.net>
parents: 1391
diff changeset
   487
    except ImportError:
9a70776e355e Try to use ini-file in the same directory as the exe as the default on NT.
Zbynek Winkler <zwin@users.sourceforge.net>
parents: 1391
diff changeset
   488
        systemrc = r'c:\mercurial\mercurial.ini'
9a70776e355e Try to use ini-file in the same directory as the exe as the default on NT.
Zbynek Winkler <zwin@users.sourceforge.net>
parents: 1391
diff changeset
   489
        pass
461
9ae0034f2772 [PATCH] /dev/null for other OS
mpm@selenic.com
parents: 441
diff changeset
   490
1399
9a70776e355e Try to use ini-file in the same directory as the exe as the default on NT.
Zbynek Winkler <zwin@users.sourceforge.net>
parents: 1391
diff changeset
   491
    rcpath = (systemrc,
1292
141951276ba1 Use platform-appropriate rc file names.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1285
diff changeset
   492
              os.path.join(os.path.expanduser('~'), 'mercurial.ini'))
141951276ba1 Use platform-appropriate rc file names.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1285
diff changeset
   493
1285
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   494
    def parse_patch_output(output_line):
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   495
        """parses the output produced by patch and returns the file name"""
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   496
        pf = output_line[14:]
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   497
        if pf[0] == '`':
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   498
            pf = pf[1:-1] # Remove the quotes
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   499
        return pf
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   500
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   501
    try: # ActivePython can create hard links using win32file module
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   502
        import win32file
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   503
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   504
        def os_link(src, dst): # NB will only succeed on NTFS
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   505
            win32file.CreateHardLink(dst, src)
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   506
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   507
        def nlinks(pathname):
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   508
            """Return number of hardlinks for the given file."""
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   509
            try:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   510
                fh = win32file.CreateFile(pathname,
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   511
                    win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   512
                    None, win32file.OPEN_EXISTING, 0, None)
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   513
                res = win32file.GetFileInformationByHandle(fh)
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   514
                fh.Close()
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   515
                return res[7]
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   516
            except:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   517
                return os.stat(pathname).st_nlink
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   518
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   519
    except ImportError:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   520
        pass
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   521
441
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   522
    def is_exec(f, last):
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   523
        return last
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   524
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   525
    def set_exec(f, mode):
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   526
        pass
515
03f27b1381f9 Whitespace cleanups
mpm@selenic.com
parents: 508
diff changeset
   527
1420
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   528
    def set_binary(fd):
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   529
        msvcrt.setmode(fd.fileno(), os.O_BINARY)
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   530
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   531
    def pconvert(path):
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   532
        return path.replace("\\", "/")
422
10c43444a38e [PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents: 421
diff changeset
   533
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   534
    def localpath(path):
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   535
        return path.replace('/', '\\')
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   536
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   537
    def normpath(path):
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   538
        return pconvert(os.path.normpath(path))
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   539
704
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   540
    makelock = _makelock_file
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   541
    readlock = _readlock_file
461
9ae0034f2772 [PATCH] /dev/null for other OS
mpm@selenic.com
parents: 441
diff changeset
   542
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   543
    def explain_exit(code):
1402
9d2c2e6b32b5 i18n part2: use '_' for all strings who are part of the user interface
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1400
diff changeset
   544
        return _("exited with status %d") % code, code
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   545
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   546
else:
461
9ae0034f2772 [PATCH] /dev/null for other OS
mpm@selenic.com
parents: 441
diff changeset
   547
    nulldev = '/dev/null'
9ae0034f2772 [PATCH] /dev/null for other OS
mpm@selenic.com
parents: 441
diff changeset
   548
1583
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   549
    def rcfiles(path):
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   550
        rcs = [os.path.join(path, 'hgrc')]
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   551
        rcdir = os.path.join(path, 'hgrc.d')
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   552
        try:
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   553
            rcs.extend([os.path.join(rcdir, f) for f in os.listdir(rcdir)
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   554
                        if f.endswith(".rc")])
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   555
        except OSError, inst: pass
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   556
        return rcs
1635
ae61937c61c5 Fix rcpath for hgwebdir case (sys.argv is empty)
efiring@manini.soest.hawaii.edu
parents: 1611
diff changeset
   557
    rcpath = []
ae61937c61c5 Fix rcpath for hgwebdir case (sys.argv is empty)
efiring@manini.soest.hawaii.edu
parents: 1611
diff changeset
   558
    if len(sys.argv) > 0:
ae61937c61c5 Fix rcpath for hgwebdir case (sys.argv is empty)
efiring@manini.soest.hawaii.edu
parents: 1611
diff changeset
   559
        rcpath.extend(rcfiles(os.path.dirname(sys.argv[0]) + '/../etc/mercurial'))
1583
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   560
    rcpath.extend(rcfiles('/etc/mercurial'))
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   561
    rcpath.append(os.path.expanduser('~/.hgrc'))
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   562
    rcpath = [os.path.normpath(f) for f in rcpath]
1292
141951276ba1 Use platform-appropriate rc file names.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1285
diff changeset
   563
1285
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   564
    def parse_patch_output(output_line):
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   565
        """parses the output produced by patch and returns the file name"""
1593
6bb3463b124b if a filename contains spaces, patch adds quote around it
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1585
diff changeset
   566
        pf = output_line[14:]
6bb3463b124b if a filename contains spaces, patch adds quote around it
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1585
diff changeset
   567
        if pf.startswith("'") and pf.endswith("'") and pf.find(" ") >= 0:
6bb3463b124b if a filename contains spaces, patch adds quote around it
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1585
diff changeset
   568
            pf = pf[1:-1] # Remove the quotes
6bb3463b124b if a filename contains spaces, patch adds quote around it
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1585
diff changeset
   569
        return pf
1285
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   570
441
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   571
    def is_exec(f, last):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   572
        """check whether a file is executable"""
441
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   573
        return (os.stat(f).st_mode & 0100 != 0)
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   574
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   575
    def set_exec(f, mode):
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   576
        s = os.stat(f).st_mode
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   577
        if (s & 0100 != 0) == mode:
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   578
            return
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   579
        if mode:
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   580
            # Turn on +x for every +r bit when making a file executable
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   581
            # and obey umask.
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   582
            umask = os.umask(0)
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   583
            os.umask(umask)
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   584
            os.chmod(f, s | (s & 0444) >> 2 & ~umask)
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   585
        else:
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   586
            os.chmod(f, s & 0666)
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   587
1420
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   588
    def set_binary(fd):
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   589
        pass
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   590
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   591
    def pconvert(path):
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   592
        return path
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   593
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   594
    def localpath(path):
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   595
        return path
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   596
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   597
    normpath = os.path.normpath
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   598
422
10c43444a38e [PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents: 421
diff changeset
   599
    def makelock(info, pathname):
704
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   600
        try:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   601
            os.symlink(info, pathname)
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   602
        except OSError, why:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   603
            if why.errno == errno.EEXIST:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   604
                raise
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   605
            else:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   606
                _makelock_file(info, pathname)
422
10c43444a38e [PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents: 421
diff changeset
   607
10c43444a38e [PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents: 421
diff changeset
   608
    def readlock(pathname):
704
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   609
        try:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   610
            return os.readlink(pathname)
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   611
        except OSError, why:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   612
            if why.errno == errno.EINVAL:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   613
                return _readlock_file(pathname)
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   614
            else:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   615
                raise
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   616
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   617
    def explain_exit(code):
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   618
        """return a 2-tuple (desc, code) describing a process's status"""
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   619
        if os.WIFEXITED(code):
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   620
            val = os.WEXITSTATUS(code)
1402
9d2c2e6b32b5 i18n part2: use '_' for all strings who are part of the user interface
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1400
diff changeset
   621
            return _("exited with status %d") % val, val
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   622
        elif os.WIFSIGNALED(code):
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   623
            val = os.WTERMSIG(code)
1402
9d2c2e6b32b5 i18n part2: use '_' for all strings who are part of the user interface
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1400
diff changeset
   624
            return _("killed by signal %d") % val, val
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   625
        elif os.WIFSTOPPED(code):
912
302f83b85054 Minor tweak: os.STOPSIG -> os.WSTOPSIG. Pychecker spotted this one.
mark.williamson@cl.cam.ac.uk
parents: 897
diff changeset
   626
            val = os.WSTOPSIG(code)
1402
9d2c2e6b32b5 i18n part2: use '_' for all strings who are part of the user interface
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1400
diff changeset
   627
            return _("stopped by signal %d") % val, val
9d2c2e6b32b5 i18n part2: use '_' for all strings who are part of the user interface
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1400
diff changeset
   628
        raise ValueError(_("invalid exit code"))
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   629
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   630
class chunkbuffer(object):
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   631
    """Allow arbitrary sized chunks of data to be efficiently read from an
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   632
    iterator over chunks of arbitrary size."""
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   633
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   634
    def __init__(self, in_iter, targetsize = 2**16):
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   635
        """in_iter is the iterator that's iterating over the input chunks.
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   636
        targetsize is how big a buffer to try to maintain."""
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   637
        self.in_iter = iter(in_iter)
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   638
        self.buf = ''
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   639
        self.targetsize = int(targetsize)
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   640
        if self.targetsize <= 0:
1402
9d2c2e6b32b5 i18n part2: use '_' for all strings who are part of the user interface
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1400
diff changeset
   641
            raise ValueError(_("targetsize must be greater than 0, was %d") %
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   642
                             targetsize)
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   643
        self.iterempty = False
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   644
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   645
    def fillbuf(self):
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   646
        """Ignore target size; read every chunk from iterator until empty."""
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   647
        if not self.iterempty:
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   648
            collector = cStringIO.StringIO()
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   649
            collector.write(self.buf)
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   650
            for ch in self.in_iter:
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   651
                collector.write(ch)
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   652
            self.buf = collector.getvalue()
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   653
            self.iterempty = True
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   654
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   655
    def read(self, l):
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   656
        """Read L bytes of data from the iterator of chunks of data.
1308
2073e5a71008 Cleanup of tabs and trailing spaces.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1285
diff changeset
   657
        Returns less than L bytes if the iterator runs dry."""
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   658
        if l > len(self.buf) and not self.iterempty:
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   659
            # Clamp to a multiple of self.targetsize
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   660
            targetsize = self.targetsize * ((l // self.targetsize) + 1)
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   661
            collector = cStringIO.StringIO()
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   662
            collector.write(self.buf)
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   663
            collected = len(self.buf)
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   664
            for chunk in self.in_iter:
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   665
                collector.write(chunk)
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   666
                collected += len(chunk)
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   667
                if collected >= targetsize:
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   668
                    break
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   669
            if collected < targetsize:
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   670
                self.iterempty = True
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   671
            self.buf = collector.getvalue()
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   672
        s, self.buf = self.buf[:l], buffer(self.buf, l)
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   673
        return s
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   674
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   675
def filechunkiter(f, size = 65536):
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   676
    """Create a generator that produces all the data in the file size
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   677
    (default 65536) bytes at a time.  Chunks may be less than size
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   678
    bytes if the chunk is the last chunk in the file, or the file is a
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   679
    socket or some other type of file that sometimes reads less data
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   680
    than is requested."""
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   681
    s = f.read(size)
1377
854775b27d1a Fixed a bug in my changes to httprepo.py
Eric Hopper <hopper@omnifarious.org>
parents: 1343
diff changeset
   682
    while len(s) > 0:
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   683
        yield s
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   684
        s = f.read(size)
1320
5f277e73778f Fix up representation of dates in hgweb.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1312
diff changeset
   685
1321
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
   686
def makedate():
1482
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
   687
    lt = time.localtime()
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
   688
    if lt[8] == 1 and time.daylight:
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
   689
        tz = time.altzone
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
   690
    else:
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
   691
        tz = time.timezone
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
   692
    return time.mktime(lt), tz
1329
8f06817bf266 Allow files to be opened in text mode, even on Windows.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1321
diff changeset
   693
1321
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
   694
def datestr(date=None, format='%c'):
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
   695
    """represent a (unixtime, offset) tuple as a localized time.
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
   696
    unixtime is seconds since the epoch, and offset is the time zone's
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
   697
    number of seconds away from UTC."""
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
   698
    t, tz = date or makedate()
1320
5f277e73778f Fix up representation of dates in hgweb.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1312
diff changeset
   699
    return ("%s %+03d%02d" %
5f277e73778f Fix up representation of dates in hgweb.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1312
diff changeset
   700
            (time.strftime(format, time.gmtime(float(t) - tz)),
5f277e73778f Fix up representation of dates in hgweb.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1312
diff changeset
   701
             -tz / 3600,
5f277e73778f Fix up representation of dates in hgweb.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1312
diff changeset
   702
             ((-tz % 3600) / 60)))
1829
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   703
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   704
def walkrepos(path):
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   705
    '''yield every hg repository under path, recursively.'''
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   706
    def errhandler(err):
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   707
        if err.filename == path:
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   708
            raise err
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   709
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   710
    for root, dirs, files in os.walk(path, onerror=errhandler):
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   711
        for d in dirs:
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   712
            if d == '.hg':
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   713
                yield root
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   714
                dirs[:] = []
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   715
                break