mercurial/util.py
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
Wed, 19 Apr 2006 11:41:27 -0700
changeset 2097 4d2c2597876f
parent 2096 f5ebe964c6be
child 2115 fd77b7ee4aac
permissions -rw-r--r--
Fix hg qdiff <file>
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():
2096
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
    23
        try:
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
    24
            pin.write(s)
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
    25
            pin.close()
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
    26
        except IOError, inst:
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
    27
            if inst.errno != errno.EPIPE:
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
    28
                raise
1258
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    29
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    30
    # 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
    31
    # systems, including Windows
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    32
    w = threading.Thread(target=writer)
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    33
    w.start()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    34
    f = pout.read()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    35
    pout.close()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    36
    w.join()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    37
    return f
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
    38
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    39
def tempfilter(s, cmd):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    40
    '''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
    41
    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
    42
    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
    43
    the temporary files generated.'''
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    44
    inname, outname = None, None
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    45
    try:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    46
        infd, inname = tempfile.mkstemp(prefix='hgfin')
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    47
        fp = os.fdopen(infd, 'wb')
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    48
        fp.write(s)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    49
        fp.close()
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    50
        outfd, outname = tempfile.mkstemp(prefix='hgfout')
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    51
        os.close(outfd)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    52
        cmd = cmd.replace('INFILE', inname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    53
        cmd = cmd.replace('OUTFILE', outname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    54
        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
    55
        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
    56
                             (cmd, explain_exit(code)))
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    57
        return open(outname, 'rb').read()
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    58
    finally:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    59
        try:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    60
            if inname: os.unlink(inname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    61
        except: pass
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    62
        try:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    63
            if outname: os.unlink(outname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    64
        except: pass
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
filtertable = {
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    67
    'tempfile:': tempfilter,
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    68
    'pipe:': pipefilter,
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    69
    }
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    70
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    71
def filter(s, cmd):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    72
    "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
    73
    for name, fn in filtertable.iteritems():
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    74
        if cmd.startswith(name):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    75
            return fn(s, cmd[len(name):].lstrip())
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    76
    return pipefilter(s, cmd)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    77
2071
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
    78
def find_in_path(name, path, default=None):
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
    79
    '''find name in search path. path can be string (will be split
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
    80
    with os.pathsep), or iterable thing that returns strings.  if name
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
    81
    found, return path to name. else return default.'''
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
    82
    if isinstance(path, str):
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
    83
        path = path.split(os.pathsep)
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
    84
    for p in path:
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
    85
        p_name = os.path.join(p, name)
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
    86
        if os.path.exists(p_name):
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
    87
            return p_name
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
    88
    return default
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
    89
1285
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    90
def patch(strip, patchname, ui):
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    91
    """apply the patch <patchname> to the working directory.
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    92
    a list of patched files is returned"""
2071
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
    93
    patcher = find_in_path('gpatch', os.environ.get('PATH', ''), 'patch')
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
    94
    fp = os.popen('"%s" -p%d < "%s"' % (patcher, strip, patchname))
1285
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    95
    files = {}
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    96
    for line in fp:
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    97
        line = line.rstrip()
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    98
        ui.status("%s\n" % line)
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
    99
        if line.startswith('patching file '):
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   100
            pf = parse_patch_output(line)
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   101
            files.setdefault(pf, 1)
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   102
    code = fp.close()
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   103
    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
   104
        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
   105
    return files.keys()
1308
2073e5a71008 Cleanup of tabs and trailing spaces.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1285
diff changeset
   106
1015
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
   107
def binary(s):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   108
    """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
   109
    if s and '\0' in s[:4096]:
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
   110
        return True
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
   111
    return False
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
   112
556
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   113
def unique(g):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   114
    """return the uniq elements of iterable g"""
556
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   115
    seen = {}
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   116
    for f in g:
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   117
        if f not in seen:
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   118
            seen[f] = 1
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   119
            yield f
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   120
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   121
class Abort(Exception):
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   122
    """Raised if a command needs to print an error and exit."""
508
42a660abaf75 [PATCH] Harden os.system
mpm@selenic.com
parents: 464
diff changeset
   123
724
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   124
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
   125
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
   126
1563
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   127
def patkind(name, dflt_pat='glob'):
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   128
    """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
   129
    actual pattern."""
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   130
    for prefix in 're', 'glob', 'path', 'relglob', 'relpath', 'relre':
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   131
        if name.startswith(prefix + ':'): return name.split(':', 1)
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   132
    return dflt_pat, name
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   133
1062
6d5a62a549fa pep-0008 cleanup
benoit.boissinot@ens-lyon.fr
parents: 1031
diff changeset
   134
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
   135
    "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
   136
    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
   137
    res = ''
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   138
    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
   139
    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
   140
    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
   141
        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
   142
        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
   143
        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
   144
            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
   145
                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
   146
                res += '.*'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   147
            else:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   148
                res += '[^/]*'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   149
        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
   150
            res += '.'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   151
        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
   152
            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
   153
            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
   154
                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
   155
            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
   156
                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
   157
            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
   158
                res += '\\['
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   159
            else:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   160
                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
   161
                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
   162
                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
   163
                    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
   164
                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
   165
                    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
   166
                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
   167
        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
   168
            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
   169
            res += '(?:'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   170
        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
   171
            res += ')'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   172
            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
   173
        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
   174
            res += '|'
1990
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   175
        elif c == '\\':
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   176
            p = peek()
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   177
            if p:
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   178
                i += 1
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   179
                res += re.escape(p)
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   180
            else:
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   181
                res += re.escape(c)
724
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   182
        else:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   183
            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
   184
    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
   185
812
b65af904d6d7 Reduce the amount of stat traffic generated by a walk.
Bryan O'Sullivan <bos@serpentine.com>
parents: 782
diff changeset
   186
_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
   187
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
   188
def pathto(n1, n2):
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   189
    '''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
   190
    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
   191
    if not n1: return localpath(n2)
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   192
    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
   193
    a.reverse()
bf4e7ef08741 fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
twaldmann@thinkmo.de
parents: 1528
diff changeset
   194
    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
   195
    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
   196
        a.pop()
bf4e7ef08741 fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
twaldmann@thinkmo.de
parents: 1528
diff changeset
   197
        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
   198
    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
   199
    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
   200
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   201
def canonpath(root, cwd, myname):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   202
    """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
   203
    if root == os.sep:
8befbb4e30b2 Handle hg under /
Arun Sharma <arun@sharma-home.net>
parents: 1563
diff changeset
   204
        rootsep = os.sep
8befbb4e30b2 Handle hg under /
Arun Sharma <arun@sharma-home.net>
parents: 1563
diff changeset
   205
    else:
1810
7596611ab3d5 Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1635
diff changeset
   206
        rootsep = root + os.sep
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   207
    name = myname
2090
eb40db373717 fix util.canonpath on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2085
diff changeset
   208
    if not os.path.isabs(name):
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   209
        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
   210
    name = os.path.normpath(name)
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   211
    if name.startswith(rootsep):
1976
df8416346bb7 Enable path validation for copy, rename, debugwalk and other canonpath users.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1958
diff changeset
   212
        name = name[len(rootsep):]
df8416346bb7 Enable path validation for copy, rename, debugwalk and other canonpath users.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1958
diff changeset
   213
        audit_path(name)
df8416346bb7 Enable path validation for copy, rename, debugwalk and other canonpath users.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1958
diff changeset
   214
        return pconvert(name)
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   215
    elif name == root:
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   216
        return ''
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   217
    else:
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   218
        raise Abort('%s not under root' % myname)
897
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   219
1610
84e9b3484ff6 if hgignore contains errors, print message that is not confusing.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1609
diff changeset
   220
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
   221
    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
   222
1610
84e9b3484ff6 if hgignore contains errors, print message that is not confusing.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1609
diff changeset
   223
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
   224
    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
   225
        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
   226
    else:
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   227
        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
   228
    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
   229
1610
84e9b3484ff6 if hgignore contains errors, print message that is not confusing.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1609
diff changeset
   230
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
   231
    """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
   232
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   233
    arguments:
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   234
    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
   235
    cwd - the current working directory, if relevant
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   236
    names - patterns to find
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   237
    inc - patterns to include
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   238
    exc - patterns to exclude
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   239
    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
   240
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   241
    a pattern is one of:
1270
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   242
    'glob:<rooted glob>'
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   243
    're:<rooted regexp>'
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   244
    'path:<rooted path>'
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   245
    'relglob:<relative glob>'
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   246
    'relpath:<relative path>'
1270
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   247
    'relre:<relative regexp>'
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   248
    '<rooted path or regexp>'
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   249
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   250
    returns:
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   251
    a 3-tuple containing
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   252
    - list of explicit non-pattern names passed in
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   253
    - a bool match(filename) function
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   254
    - a bool indicating if any patterns were passed in
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   255
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   256
    todo:
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   257
    make head regex a rooted bool
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   258
    """
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   259
1413
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   260
    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
   261
        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
   262
            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
   263
        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
   264
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   265
    def regex(kind, name, tail):
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   266
        '''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
   267
        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
   268
            return name
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   269
        elif kind == 'path':
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   270
            return '^' + re.escape(name) + '(?:/|$)'
1270
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   271
        elif kind == 'relglob':
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   272
            return head + globre(name, '(?:|.*/)', tail)
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   273
        elif kind == 'relpath':
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   274
            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
   275
        elif kind == 'relre':
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   276
            if name.startswith('^'):
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   277
                return name
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   278
            return '.*' + name
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   279
        return head + globre(name, '', tail)
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   280
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   281
    def matchfn(pats, tail):
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   282
        """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
   283
        if not pats:
f4250806dbeb further fix traceback on invalid .hgignore patterns
Benoit Boissinot <mercurial-bugs@selenic.com>
parents: 1446
diff changeset
   284
            return
1446
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   285
        matches = []
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   286
        for k, p in pats:
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   287
            try:
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   288
                pat = '(?:%s)' % regex(k, p, tail)
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   289
                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
   290
            except re.error:
1611
301d5cd4abc6 make invalid pattern message not confusing.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1610
diff changeset
   291
                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
   292
                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
   293
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   294
        def buildfn(text):
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   295
            for m in matches:
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   296
                r = m(text)
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   297
                if r:
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   298
                    return r
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   299
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   300
        return buildfn
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   301
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   302
    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
   303
        '''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
   304
        root = []
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   305
        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
   306
            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
   307
            root.append(p)
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   308
        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
   309
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   310
    pats = []
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   311
    files = []
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   312
    roots = []
1413
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   313
    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
   314
        if kind in ('glob', 'relpath'):
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   315
            name = canonpath(canonroot, cwd, name)
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   316
            if name == '':
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   317
                kind, name = 'glob', '**'
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   318
        if kind in ('glob', 'path', 're'):
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   319
            pats.append((kind, name))
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   320
        if kind == 'glob':
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   321
            root = globprefix(name)
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   322
            if root: roots.append(root)
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   323
        elif kind == 'relpath':
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   324
            files.append((kind, name))
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   325
            roots.append(name)
897
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   326
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   327
    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
   328
    filematch = matchfn(files, '(?:/|$)') or always
897
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   329
    incmatch = always
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   330
    if inc:
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   331
        incmatch = matchfn(map(patkind, inc), '(?:/|$)')
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   332
    excmatch = lambda fn: False
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   333
    if exc:
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   334
        excmatch = matchfn(map(patkind, exc), '(?:/|$)')
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   335
1031
503aaf19a040 Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1015
diff changeset
   336
    return (roots,
503aaf19a040 Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1015
diff changeset
   337
            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
   338
                        (fn.endswith('/') or
503aaf19a040 Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1015
diff changeset
   339
                         (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
   340
                         (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
   341
                         (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
   342
            (inc or exc or (pats and pats != [('glob', '**')])) and True)
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   343
1882
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   344
def system(cmd, environ={}, cwd=None, onerr=None, errprefix=None):
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   345
    '''enhanced shell command execution.
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   346
    run with environment maybe modified, maybe in different dir.
508
42a660abaf75 [PATCH] Harden os.system
mpm@selenic.com
parents: 464
diff changeset
   347
1882
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   348
    if command fails and onerr is None, return status.  if ui object,
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   349
    print error message and return status, else raise onerr object as
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   350
    exception.'''
1880
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   351
    oldenv = {}
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   352
    for k in environ:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   353
        oldenv[k] = os.environ.get(k)
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   354
    if cwd is not None:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   355
        oldcwd = os.getcwd()
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   356
    try:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   357
        for k, v in environ.iteritems():
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   358
            os.environ[k] = str(v)
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   359
        if cwd is not None and oldcwd != cwd:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   360
            os.chdir(cwd)
1882
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   361
        rc = os.system(cmd)
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   362
        if rc and onerr:
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   363
            errmsg = '%s %s' % (os.path.basename(cmd.split(None, 1)[0]),
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   364
                                explain_exit(rc)[0])
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   365
            if errprefix:
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   366
                errmsg = '%s: %s' % (errprefix, errmsg)
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   367
            try:
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   368
                onerr.warn(errmsg + '\n')
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   369
            except AttributeError:
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   370
                raise onerr(errmsg)
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   371
        return rc
1880
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   372
    finally:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   373
        for k, v in oldenv.iteritems():
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   374
            if v is None:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   375
                del os.environ[k]
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   376
            else:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   377
                os.environ[k] = v
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   378
        if cwd is not None and oldcwd != cwd:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   379
            os.chdir(oldcwd)
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   380
421
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   381
def rename(src, dst):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   382
    """forcibly rename a file"""
421
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   383
    try:
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   384
        os.rename(src, dst)
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   385
    except:
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   386
        os.unlink(dst)
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   387
        os.rename(src, dst)
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   388
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
   389
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
   390
    """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
   391
    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
   392
    # try removing directories that might now be empty
2064
547ede0123a2 util.unlink should only catch OSError.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2054
diff changeset
   393
    try:
547ede0123a2 util.unlink should only catch OSError.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2054
diff changeset
   394
        os.removedirs(os.path.dirname(f))
547ede0123a2 util.unlink should only catch OSError.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2054
diff changeset
   395
    except OSError:
547ede0123a2 util.unlink should only catch OSError.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2054
diff changeset
   396
        pass
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
   397
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   398
def copyfiles(src, dst, hardlink=None):
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   399
    """Copy a directory tree using hardlinks if possible"""
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   400
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   401
    if hardlink is None:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   402
        hardlink = (os.stat(src).st_dev ==
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   403
                    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
   404
1207
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   405
    if os.path.isdir(src):
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   406
        os.mkdir(dst)
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   407
        for name in os.listdir(src):
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   408
            srcname = os.path.join(src, name)
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   409
            dstname = os.path.join(dst, name)
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   410
            copyfiles(srcname, dstname, hardlink)
1207
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   411
    else:
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   412
        if hardlink:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   413
            try:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   414
                os_link(src, dst)
2050
e49d0fa38176 util.copyfiles: only switch to copy if hardlink raises IOError or OSError.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2026
diff changeset
   415
            except (IOError, OSError):
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   416
                hardlink = False
1591
5a3229cf1492 do not copy atime and mtime in util.copyfiles
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1585
diff changeset
   417
                shutil.copy(src, dst)
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   418
        else:
1591
5a3229cf1492 do not copy atime and mtime in util.copyfiles
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1585
diff changeset
   419
            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
   420
1835
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   421
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
   422
    """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
   423
    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
   424
    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
   425
        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
   426
        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
   427
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   428
def opener(base, audit=True):
1090
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   429
    """
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   430
    return a function that opens files relative to base
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   431
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   432
    this function is used to hide the details of COW semantics and
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   433
    remote file access from higher level code.
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   434
    """
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   435
    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
   436
    audit_p = audit
1528
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   437
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   438
    def mktempcopy(name):
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   439
        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
   440
        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
   441
        fp = os.fdopen(fd, "wb")
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   442
        try:
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   443
            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
   444
        except:
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   445
            try: os.unlink(temp)
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   446
            except: pass
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   447
            raise
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   448
        fp.close()
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   449
        st = os.lstat(name)
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   450
        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
   451
        return temp
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   452
2076
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   453
    class atomictempfile(file):
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   454
        """the file will only be copied when rename is called"""
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   455
        def __init__(self, name, mode):
1528
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   456
            self.__name = name
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   457
            self.temp = mktempcopy(name)
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   458
            file.__init__(self, self.temp, mode)
2076
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   459
        def rename(self):
1528
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   460
            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
   461
                file.close(self)
1528
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   462
                rename(self.temp, self.__name)
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   463
        def __del__(self):
2076
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   464
            if not self.closed:
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   465
                try:
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   466
                    os.unlink(self.temp)
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   467
                except: pass
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   468
                file.close(self)
1528
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   469
2076
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   470
    class atomicfile(atomictempfile):
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   471
        """the file will only be copied on close"""
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   472
        def __init__(self, name, mode):
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   473
            atomictempfile.__init__(self, name, mode)
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   474
        def close(self):
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   475
            self.rename()
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   476
        def __del__(self):
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   477
            self.rename()
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   478
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   479
    def o(path, mode="r", text=False, atomic=False, atomictemp=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
   480
        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
   481
            audit_path(path)
1090
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   482
        f = os.path.join(p, path)
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   483
1329
8f06817bf266 Allow files to be opened in text mode, even on Windows.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1321
diff changeset
   484
        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
   485
            mode += "b" # for that other OS
1090
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   486
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   487
        if mode[0] != "r":
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   488
            try:
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   489
                nlink = nlinks(f)
1090
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   490
            except OSError:
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   491
                d = os.path.dirname(f)
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   492
                if not os.path.isdir(d):
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   493
                    os.makedirs(d)
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   494
            else:
1528
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   495
                if atomic:
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   496
                    return atomicfile(f, mode)
2076
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   497
                elif atomictemp:
d007df6daf8e Create an atomic opener that does not automatically rename on close
mason@suse.com
parents: 2026
diff changeset
   498
                    return atomictempfile(f, mode)
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   499
                if nlink > 1:
1528
c9f33196805b add an atomic argument to util.opener
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1521
diff changeset
   500
                    rename(mktempcopy(f), f)
1090
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   501
        return file(f, mode)
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   502
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   503
    return o
1bca39b85615 Move opener to utils
mpm@selenic.com
parents: 1082
diff changeset
   504
704
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   505
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
   506
    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
   507
    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
   508
    os.close(ld)
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   509
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   510
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
   511
    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
   512
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   513
def nlinks(pathname):
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   514
    """Return number of hardlinks for the given file."""
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   515
    return os.stat(pathname).st_nlink
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   516
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   517
if hasattr(os, 'link'):
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   518
    os_link = os.link
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   519
else:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   520
    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
   521
        raise OSError(0, _("Hardlinks not supported"))
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   522
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   523
# Platform specific variants
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   524
if os.name == 'nt':
1420
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   525
    demandload(globals(), "msvcrt")
461
9ae0034f2772 [PATCH] /dev/null for other OS
mpm@selenic.com
parents: 441
diff changeset
   526
    nulldev = 'NUL:'
1609
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   527
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   528
    class winstdout:
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   529
        '''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
   530
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   531
        def __init__(self, fp):
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   532
            self.fp = fp
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   533
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   534
        def __getattr__(self, key):
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   535
            return getattr(self.fp, key)
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   536
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   537
        def close(self):
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   538
            try:
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   539
                self.fp.close()
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   540
            except: pass
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   541
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   542
        def write(self, s):
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   543
            try:
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   544
                return self.fp.write(s)
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   545
            except IOError, inst:
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   546
                if inst.errno != 0: raise
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   547
                self.close()
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   548
                raise IOError(errno.EPIPE, 'Broken pipe')
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   549
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   550
    sys.stdout = winstdout(sys.stdout)
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   551
2054
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   552
    def system_rcpath():
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   553
        return [r'c:\mercurial\mercurial.ini']
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   554
1951
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   555
    def os_rcpath():
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   556
        '''return default os-specific hgrc search path'''
2054
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   557
        return system_rcpath() + [os.path.join(os.path.expanduser('~'),
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   558
                                               'mercurial.ini')]
1292
141951276ba1 Use platform-appropriate rc file names.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1285
diff changeset
   559
1285
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   560
    def parse_patch_output(output_line):
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   561
        """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
   562
        pf = output_line[14:]
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   563
        if pf[0] == '`':
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   564
            pf = pf[1:-1] # Remove the quotes
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   565
        return pf
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   566
2054
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   567
    def testpid(pid):
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   568
        '''return False if pid dead, True if running or not known'''
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   569
        return True
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   570
441
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   571
    def is_exec(f, last):
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   572
        return last
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   573
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   574
    def set_exec(f, mode):
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   575
        pass
515
03f27b1381f9 Whitespace cleanups
mpm@selenic.com
parents: 508
diff changeset
   576
1420
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   577
    def set_binary(fd):
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   578
        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
   579
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   580
    def pconvert(path):
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   581
        return path.replace("\\", "/")
422
10c43444a38e [PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents: 421
diff changeset
   582
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   583
    def localpath(path):
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   584
        return path.replace('/', '\\')
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   585
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   586
    def normpath(path):
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   587
        return pconvert(os.path.normpath(path))
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   588
704
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   589
    makelock = _makelock_file
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   590
    readlock = _readlock_file
461
9ae0034f2772 [PATCH] /dev/null for other OS
mpm@selenic.com
parents: 441
diff changeset
   591
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   592
    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
   593
        return _("exited with status %d") % code, code
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   594
2054
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   595
    try:
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   596
        # override functions with win32 versions if possible
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   597
        from util_win32 import *
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   598
    except ImportError:
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   599
        pass
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   600
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   601
else:
461
9ae0034f2772 [PATCH] /dev/null for other OS
mpm@selenic.com
parents: 441
diff changeset
   602
    nulldev = '/dev/null'
9ae0034f2772 [PATCH] /dev/null for other OS
mpm@selenic.com
parents: 441
diff changeset
   603
1583
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   604
    def rcfiles(path):
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   605
        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
   606
        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
   607
        try:
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   608
            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
   609
                        if f.endswith(".rc")])
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   610
        except OSError, inst: pass
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   611
        return rcs
1951
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   612
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   613
    def os_rcpath():
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   614
        '''return default os-specific hgrc search path'''
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   615
        path = []
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   616
        if len(sys.argv) > 0:
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   617
            path.extend(rcfiles(os.path.dirname(sys.argv[0]) +
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   618
                                  '/../etc/mercurial'))
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   619
        path.extend(rcfiles('/etc/mercurial'))
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   620
        path.append(os.path.expanduser('~/.hgrc'))
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   621
        path = [os.path.normpath(f) for f in path]
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   622
        return path
1292
141951276ba1 Use platform-appropriate rc file names.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1285
diff changeset
   623
1285
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   624
    def parse_patch_output(output_line):
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   625
        """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
   626
        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
   627
        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
   628
            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
   629
        return pf
1285
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   630
441
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   631
    def is_exec(f, last):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   632
        """check whether a file is executable"""
441
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   633
        return (os.stat(f).st_mode & 0100 != 0)
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   634
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   635
    def set_exec(f, mode):
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   636
        s = os.stat(f).st_mode
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   637
        if (s & 0100 != 0) == mode:
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   638
            return
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   639
        if mode:
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   640
            # 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
   641
            # and obey umask.
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   642
            umask = os.umask(0)
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   643
            os.umask(umask)
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   644
            os.chmod(f, s | (s & 0444) >> 2 & ~umask)
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   645
        else:
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   646
            os.chmod(f, s & 0666)
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   647
1420
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   648
    def set_binary(fd):
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   649
        pass
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   650
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   651
    def pconvert(path):
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   652
        return path
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   653
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   654
    def localpath(path):
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   655
        return path
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   656
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   657
    normpath = os.path.normpath
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   658
422
10c43444a38e [PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents: 421
diff changeset
   659
    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
   660
        try:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   661
            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
   662
        except OSError, why:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   663
            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
   664
                raise
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   665
            else:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   666
                _makelock_file(info, pathname)
422
10c43444a38e [PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents: 421
diff changeset
   667
10c43444a38e [PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents: 421
diff changeset
   668
    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
   669
        try:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   670
            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
   671
        except OSError, why:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   672
            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
   673
                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
   674
            else:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   675
                raise
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   676
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1835
diff changeset
   677
    def testpid(pid):
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1835
diff changeset
   678
        '''return False if pid dead, True if running or not sure'''
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1835
diff changeset
   679
        try:
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1835
diff changeset
   680
            os.kill(pid, 0)
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1835
diff changeset
   681
            return True
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1835
diff changeset
   682
        except OSError, inst:
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1835
diff changeset
   683
            return inst.errno != errno.ESRCH
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1835
diff changeset
   684
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   685
    def explain_exit(code):
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   686
        """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
   687
        if os.WIFEXITED(code):
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   688
            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
   689
            return _("exited with status %d") % val, val
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   690
        elif os.WIFSIGNALED(code):
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   691
            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
   692
            return _("killed by signal %d") % val, val
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   693
        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
   694
            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
   695
            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
   696
        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
   697
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   698
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
   699
    """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
   700
    iterator over chunks of arbitrary size."""
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   701
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   702
    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
   703
        """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
   704
        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
   705
        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
   706
        self.buf = ''
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   707
        self.targetsize = int(targetsize)
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   708
        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
   709
            raise ValueError(_("targetsize must be greater than 0, was %d") %
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   710
                             targetsize)
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   711
        self.iterempty = False
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   712
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   713
    def fillbuf(self):
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   714
        """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
   715
        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
   716
            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
   717
            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
   718
            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
   719
                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
   720
            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
   721
            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
   722
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   723
    def read(self, l):
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   724
        """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
   725
        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
   726
        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
   727
            # 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
   728
            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
   729
            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
   730
            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
   731
            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
   732
            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
   733
                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
   734
                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
   735
                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
   736
                    break
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   737
            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
   738
                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
   739
            self.buf = collector.getvalue()
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   740
        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
   741
        return s
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   742
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   743
def filechunkiter(f, size = 65536):
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
   744
    """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
   745
    (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
   746
    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
   747
    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
   748
    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
   749
    s = f.read(size)
1377
854775b27d1a Fixed a bug in my changes to httprepo.py
Eric Hopper <hopper@omnifarious.org>
parents: 1343
diff changeset
   750
    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
   751
        yield s
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
   752
        s = f.read(size)
1320
5f277e73778f Fix up representation of dates in hgweb.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1312
diff changeset
   753
1321
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
   754
def makedate():
1482
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
   755
    lt = time.localtime()
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
   756
    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
   757
        tz = time.altzone
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
   758
    else:
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
   759
        tz = time.timezone
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
   760
    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
   761
1987
04c17fc39c84 add changelog style to command line template.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1976
diff changeset
   762
def datestr(date=None, format='%a %b %d %H:%M:%S %Y', timezone=True):
1321
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
   763
    """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
   764
    unixtime is seconds since the epoch, and offset is the time zone's
1987
04c17fc39c84 add changelog style to command line template.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1976
diff changeset
   765
    number of seconds away from UTC. if timezone is false, do not
04c17fc39c84 add changelog style to command line template.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1976
diff changeset
   766
    append time zone to string."""
1321
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
   767
    t, tz = date or makedate()
1987
04c17fc39c84 add changelog style to command line template.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1976
diff changeset
   768
    s = time.strftime(format, time.gmtime(float(t) - tz))
04c17fc39c84 add changelog style to command line template.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1976
diff changeset
   769
    if timezone:
04c17fc39c84 add changelog style to command line template.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1976
diff changeset
   770
        s += " %+03d%02d" % (-tz / 3600, ((-tz % 3600) / 60))
04c17fc39c84 add changelog style to command line template.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1976
diff changeset
   771
    return s
1829
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   772
1903
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   773
def shortuser(user):
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   774
    """Return a short representation of a user name or email address."""
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   775
    f = user.find('@')
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   776
    if f >= 0:
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   777
        user = user[:f]
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   778
    f = user.find('<')
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   779
    if f >= 0:
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   780
        user = user[f+1:]
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   781
    return user
1920
b7cc0f323a4c merge with crew.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1903 1882
diff changeset
   782
1829
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   783
def walkrepos(path):
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   784
    '''yield every hg repository under path, recursively.'''
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   785
    def errhandler(err):
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   786
        if err.filename == path:
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   787
            raise err
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   788
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   789
    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
   790
        for d in dirs:
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   791
            if d == '.hg':
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   792
                yield root
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   793
                dirs[:] = []
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
   794
                break
1951
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   795
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   796
_rcpath = None
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   797
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   798
def rcpath():
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   799
    '''return hgrc search path. if env var HGRCPATH is set, use it.
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   800
    for each item in path, if directory, use files ending in .rc,
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   801
    else use item.
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   802
    make HGRCPATH empty to only look in .hg/hgrc of current repo.
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   803
    if no HGRCPATH, use default os-specific path.'''
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   804
    global _rcpath
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   805
    if _rcpath is None:
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   806
        if 'HGRCPATH' in os.environ:
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   807
            _rcpath = []
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   808
            for p in os.environ['HGRCPATH'].split(os.pathsep):
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   809
                if not p: continue
1956
16750010813d use a proper test instead of catching every exception
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1951
diff changeset
   810
                if os.path.isdir(p):
1951
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   811
                    for f in os.listdir(p):
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   812
                        if f.endswith('.rc'):
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   813
                            _rcpath.append(os.path.join(p, f))
1956
16750010813d use a proper test instead of catching every exception
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1951
diff changeset
   814
                else:
16750010813d use a proper test instead of catching every exception
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1951
diff changeset
   815
                    _rcpath.append(p)
1951
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   816
        else:
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   817
            _rcpath = os_rcpath()
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   818
    return _rcpath