mercurial/util.py
author Matt Mackall <mpm@selenic.com>
Tue, 06 Feb 2007 16:12:22 -0600
changeset 4068 5b1f663ef86d
parent 4059 431f3c1d3a37
parent 4067 c620376b8fd6
child 4069 3fef134832d8
permissions -rw-r--r--
Merge with stable
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>
2859
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2793
diff changeset
     5
 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2793
diff changeset
     6
 Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
     7
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
     8
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
     9
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
    10
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
    11
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
    12
platform-specific details from the core.
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
    13
"""
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
    14
3891
6b4127c7d52a Simplify i18n imports
Matt Mackall <mpm@selenic.com>
parents: 3877
diff changeset
    15
from i18n import _
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents: 3860
diff changeset
    16
import cStringIO, errno, getpass, popen2, re, shutil, sys, tempfile
4059
431f3c1d3a37 Merge with crew-stable
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4017 4057
diff changeset
    17
import os, threading, time, calendar, ConfigParser, locale, glob
3769
96095d9ff1f8 Add encoding detection
Matt Mackall <mpm@selenic.com>
parents: 3767
diff changeset
    18
4057
3600b84656d3 Fallback to ascii if getpreferredencoding raises an exception
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4055
diff changeset
    19
try:
3600b84656d3 Fallback to ascii if getpreferredencoding raises an exception
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4055
diff changeset
    20
    _encoding = os.environ.get("HGENCODING") or locale.getpreferredencoding() \
3600b84656d3 Fallback to ascii if getpreferredencoding raises an exception
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4055
diff changeset
    21
                or "ascii"
3600b84656d3 Fallback to ascii if getpreferredencoding raises an exception
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4055
diff changeset
    22
except locale.Error:
3600b84656d3 Fallback to ascii if getpreferredencoding raises an exception
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4055
diff changeset
    23
    _encoding = 'ascii'
3770
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    24
_encodingmode = os.environ.get("HGENCODINGMODE", "strict")
3835
d1ce5461beed Allow the user to specify the fallback encoding for the changelog
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3813
diff changeset
    25
_fallbackencoding = 'ISO-8859-1'
3770
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    26
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    27
def tolocal(s):
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    28
    """
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    29
    Convert a string from internal UTF-8 to local encoding
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    30
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    31
    All internal strings should be UTF-8 but some repos before the
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    32
    implementation of locale support may contain latin1 or possibly
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    33
    other character sets. We attempt to decode everything strictly
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    34
    using UTF-8, then Latin-1, and failing that, we use UTF-8 and
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    35
    replace unknown characters.
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    36
    """
3835
d1ce5461beed Allow the user to specify the fallback encoding for the changelog
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3813
diff changeset
    37
    for e in ('UTF-8', _fallbackencoding):
3770
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    38
        try:
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    39
            u = s.decode(e) # attempt strict decoding
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    40
            return u.encode(_encoding, "replace")
3843
abaa2cd00d2b make transcoding more robust
Matt Mackall <mpm@selenic.com>
parents: 3835
diff changeset
    41
        except LookupError, k:
abaa2cd00d2b make transcoding more robust
Matt Mackall <mpm@selenic.com>
parents: 3835
diff changeset
    42
            raise Abort(_("%s, please check your locale settings") % k)
3770
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    43
        except UnicodeDecodeError:
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    44
            pass
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    45
    u = s.decode("utf-8", "replace") # last ditch
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    46
    return u.encode(_encoding, "replace")
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    47
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    48
def fromlocal(s):
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    49
    """
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    50
    Convert a string from the local character encoding to UTF-8
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    51
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    52
    We attempt to decode strings using the encoding mode set by
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    53
    HG_ENCODINGMODE, which defaults to 'strict'. In this mode, unknown
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    54
    characters will cause an error message. Other modes include
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    55
    'replace', which replaces unknown characters with a special
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    56
    Unicode character, and 'ignore', which drops the character.
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    57
    """
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    58
    try:
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    59
        return s.decode(_encoding, _encodingmode).encode("utf-8")
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    60
    except UnicodeDecodeError, inst:
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    61
        sub = s[max(0, inst.start-10):inst.start+10]
3843
abaa2cd00d2b make transcoding more robust
Matt Mackall <mpm@selenic.com>
parents: 3835
diff changeset
    62
        raise Abort("decoding near '%s': %s!" % (sub, inst))
abaa2cd00d2b make transcoding more robust
Matt Mackall <mpm@selenic.com>
parents: 3835
diff changeset
    63
    except LookupError, k:
abaa2cd00d2b make transcoding more robust
Matt Mackall <mpm@selenic.com>
parents: 3835
diff changeset
    64
        raise Abort(_("%s, please check your locale settings") % k)
3770
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    65
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    66
def locallen(s):
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    67
    """Find the length in characters of a local string"""
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    68
    return len(s.decode(_encoding, "replace"))
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    69
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    70
def localsub(s, a, b=None):
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    71
    try:
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    72
        u = s.decode(_encoding, _encodingmode)
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    73
        if b is not None:
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    74
            u = u[a:b]
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    75
        else:
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    76
            u = u[:a]
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    77
        return u.encode(_encoding, _encodingmode)
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    78
    except UnicodeDecodeError, inst:
f96c158ea3a3 Add functions for transcoding and manipulating multibyte strings
Matt Mackall <mpm@selenic.com>
parents: 3769
diff changeset
    79
        sub = s[max(0, inst.start-10), inst.start+10]
3843
abaa2cd00d2b make transcoding more robust
Matt Mackall <mpm@selenic.com>
parents: 3835
diff changeset
    80
        raise Abort(_("decoding near '%s': %s!\n") % (sub, inst))
1258
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
    81
2609
6c5b1b5cc160 util.parsedate should understand dates from hg export
Chris Mason <mason@suse.com>
parents: 2601
diff changeset
    82
# used by parsedate
3808
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    83
defaultdateformats = (
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    84
    '%Y-%m-%d %H:%M:%S',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    85
    '%Y-%m-%d %I:%M:%S%p',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    86
    '%Y-%m-%d %H:%M',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    87
    '%Y-%m-%d %I:%M%p',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    88
    '%Y-%m-%d',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    89
    '%m-%d',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    90
    '%m/%d',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    91
    '%m/%d/%y',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    92
    '%m/%d/%Y',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    93
    '%a %b %d %H:%M:%S %Y',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    94
    '%a %b %d %I:%M:%S%p %Y',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    95
    '%b %d %H:%M:%S %Y',
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
    96
    '%b %d %I:%M:%S%p %Y',
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
    97
    '%b %d %H:%M:%S',
3808
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    98
    '%b %d %I:%M:%S%p',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    99
    '%b %d %H:%M',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   100
    '%b %d %I:%M%p',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   101
    '%b %d %Y',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   102
    '%b %d',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   103
    '%H:%M:%S',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   104
    '%I:%M:%SP',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   105
    '%H:%M',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   106
    '%I:%M%p',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   107
)
2609
6c5b1b5cc160 util.parsedate should understand dates from hg export
Chris Mason <mason@suse.com>
parents: 2601
diff changeset
   108
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
   109
extendeddateformats = defaultdateformats + (
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
   110
    "%Y",
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
   111
    "%Y-%m",
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
   112
    "%b",
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
   113
    "%b %Y",
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
   114
    )
2609
6c5b1b5cc160 util.parsedate should understand dates from hg export
Chris Mason <mason@suse.com>
parents: 2601
diff changeset
   115
2153
635653cd73ab move SignalInterrupt class into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   116
class SignalInterrupt(Exception):
635653cd73ab move SignalInterrupt class into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   117
    """Exception raised on SIGTERM and SIGHUP."""
635653cd73ab move SignalInterrupt class into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   118
3425
ec6f400cff4d Use a case-sensitive version of SafeConfigParser everywhere
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3257
diff changeset
   119
# like SafeConfigParser but with case-sensitive keys
ec6f400cff4d Use a case-sensitive version of SafeConfigParser everywhere
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3257
diff changeset
   120
class configparser(ConfigParser.SafeConfigParser):
ec6f400cff4d Use a case-sensitive version of SafeConfigParser everywhere
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3257
diff changeset
   121
    def optionxform(self, optionstr):
ec6f400cff4d Use a case-sensitive version of SafeConfigParser everywhere
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3257
diff changeset
   122
        return optionstr
ec6f400cff4d Use a case-sensitive version of SafeConfigParser everywhere
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3257
diff changeset
   123
3145
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   124
def cachefunc(func):
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   125
    '''cache the result of function calls'''
3147
97420a49188d add comments in cachefunc
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3145
diff changeset
   126
    # XXX doesn't handle keywords args
3145
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   127
    cache = {}
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   128
    if func.func_code.co_argcount == 1:
3147
97420a49188d add comments in cachefunc
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3145
diff changeset
   129
        # we gain a small amount of time because
97420a49188d add comments in cachefunc
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3145
diff changeset
   130
        # we don't need to pack/unpack the list
3145
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   131
        def f(arg):
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   132
            if arg not in cache:
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   133
                cache[arg] = func(arg)
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   134
            return cache[arg]
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   135
    else:
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   136
        def f(*args):
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   137
            if args not in cache:
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   138
                cache[args] = func(*args)
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   139
            return cache[args]
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   140
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   141
    return f
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   142
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   143
def pipefilter(s, cmd):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   144
    '''filter string S through command CMD, returning its output'''
1258
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   145
    (pout, pin) = popen2.popen2(cmd, -1, 'b')
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   146
    def writer():
2096
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
   147
        try:
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
   148
            pin.write(s)
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
   149
            pin.close()
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
   150
        except IOError, inst:
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
   151
            if inst.errno != errno.EPIPE:
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
   152
                raise
1258
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   153
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   154
    # 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
   155
    # systems, including Windows
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   156
    w = threading.Thread(target=writer)
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   157
    w.start()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   158
    f = pout.read()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   159
    pout.close()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   160
    w.join()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   161
    return f
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   162
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   163
def tempfilter(s, cmd):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   164
    '''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
   165
    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
   166
    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
   167
    the temporary files generated.'''
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   168
    inname, outname = None, None
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   169
    try:
2165
d821918e3bee Use better names (hg-{usage}-{random}.{suffix}) for temporary files.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2153
diff changeset
   170
        infd, inname = tempfile.mkstemp(prefix='hg-filter-in-')
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   171
        fp = os.fdopen(infd, 'wb')
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   172
        fp.write(s)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   173
        fp.close()
2165
d821918e3bee Use better names (hg-{usage}-{random}.{suffix}) for temporary files.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2153
diff changeset
   174
        outfd, outname = tempfile.mkstemp(prefix='hg-filter-out-')
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   175
        os.close(outfd)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   176
        cmd = cmd.replace('INFILE', inname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   177
        cmd = cmd.replace('OUTFILE', outname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   178
        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
   179
        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
   180
                             (cmd, explain_exit(code)))
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   181
        return open(outname, 'rb').read()
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   182
    finally:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   183
        try:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   184
            if inname: os.unlink(inname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   185
        except: pass
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   186
        try:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   187
            if outname: os.unlink(outname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   188
        except: pass
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   189
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   190
filtertable = {
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   191
    'tempfile:': tempfilter,
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   192
    'pipe:': pipefilter,
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   193
    }
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   194
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   195
def filter(s, cmd):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   196
    "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
   197
    for name, fn in filtertable.iteritems():
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   198
        if cmd.startswith(name):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   199
            return fn(s, cmd[len(name):].lstrip())
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   200
    return pipefilter(s, cmd)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   201
2071
67a0a3852024 import: use gpatch if present on system. patch is broken on solaris.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2064
diff changeset
   202
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
   203
    '''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
   204
    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
   205
    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
   206
    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
   207
        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
   208
    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
   209
        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
   210
        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
   211
            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
   212
    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
   213
1015
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
   214
def binary(s):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   215
    """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
   216
    if s and '\0' in s[:4096]:
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
   217
        return True
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
   218
    return False
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
   219
556
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   220
def unique(g):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   221
    """return the uniq elements of iterable g"""
556
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   222
    seen = {}
3535
4d97184a06ad Make util.unique return a list
Matt Mackall <mpm@selenic.com>
parents: 3533
diff changeset
   223
    l = []
556
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   224
    for f in g:
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   225
        if f not in seen:
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   226
            seen[f] = 1
3535
4d97184a06ad Make util.unique return a list
Matt Mackall <mpm@selenic.com>
parents: 3533
diff changeset
   227
            l.append(f)
4d97184a06ad Make util.unique return a list
Matt Mackall <mpm@selenic.com>
parents: 3533
diff changeset
   228
    return l
556
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   229
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   230
class Abort(Exception):
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   231
    """Raised if a command needs to print an error and exit."""
508
42a660abaf75 [PATCH] Harden os.system
mpm@selenic.com
parents: 464
diff changeset
   232
3564
eda9e7c9300d New UnexpectedOutput exception to catch server errors in localrepo.stream_in
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3551
diff changeset
   233
class UnexpectedOutput(Abort):
eda9e7c9300d New UnexpectedOutput exception to catch server errors in localrepo.stream_in
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3551
diff changeset
   234
    """Raised to print an error with part of output and exit."""
eda9e7c9300d New UnexpectedOutput exception to catch server errors in localrepo.stream_in
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3551
diff changeset
   235
724
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   236
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
   237
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
   238
4054
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   239
def expand_glob(pats):
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   240
    '''On Windows, expand the implicit globs in a list of patterns'''
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   241
    if os.name != 'nt':
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   242
        return list(pats)
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   243
    ret = []
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   244
    for p in pats:
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   245
        kind, name = patkind(p, None)
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   246
        if kind is None:
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   247
            globbed = glob.glob(name)
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   248
            if globbed:
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   249
                ret.extend(globbed)
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   250
                continue
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   251
            # if we couldn't expand the glob, just keep it around
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   252
        ret.append(p)
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   253
    return ret
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   254
1563
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   255
def patkind(name, dflt_pat='glob'):
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   256
    """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
   257
    actual pattern."""
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   258
    for prefix in 're', 'glob', 'path', 'relglob', 'relpath', 'relre':
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   259
        if name.startswith(prefix + ':'): return name.split(':', 1)
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   260
    return dflt_pat, name
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   261
1062
6d5a62a549fa pep-0008 cleanup
benoit.boissinot@ens-lyon.fr
parents: 1031
diff changeset
   262
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
   263
    "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
   264
    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
   265
    res = ''
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   266
    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
   267
    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
   268
    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
   269
        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
   270
        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
   271
        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
   272
            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
   273
                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
   274
                res += '.*'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   275
            else:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   276
                res += '[^/]*'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   277
        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
   278
            res += '.'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   279
        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
   280
            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
   281
            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
   282
                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
   283
            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
   284
                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
   285
            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
   286
                res += '\\['
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   287
            else:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   288
                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
   289
                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
   290
                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
   291
                    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
   292
                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
   293
                    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
   294
                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
   295
        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
   296
            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
   297
            res += '(?:'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   298
        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
   299
            res += ')'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   300
            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
   301
        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
   302
            res += '|'
1990
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   303
        elif c == '\\':
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   304
            p = peek()
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   305
            if p:
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   306
                i += 1
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   307
                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
   308
            else:
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   309
                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
   310
        else:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   311
            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
   312
    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
   313
812
b65af904d6d7 Reduce the amount of stat traffic generated by a walk.
Bryan O'Sullivan <bos@serpentine.com>
parents: 782
diff changeset
   314
_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
   315
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
   316
def pathto(n1, n2):
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   317
    '''return the relative path from one place to another.
3669
48768b1ab23c fix util.pathto
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3629
diff changeset
   318
    n1 should use os.sep to separate directories
48768b1ab23c fix util.pathto
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3629
diff changeset
   319
    n2 should use "/" to separate directories
48768b1ab23c fix util.pathto
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3629
diff changeset
   320
    returns an os.sep-separated path.
48768b1ab23c fix util.pathto
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3629
diff changeset
   321
    '''
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   322
    if not n1: return localpath(n2)
3669
48768b1ab23c fix util.pathto
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3629
diff changeset
   323
    a, b = n1.split(os.sep), n2.split('/')
1541
bf4e7ef08741 fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
twaldmann@thinkmo.de
parents: 1528
diff changeset
   324
    a.reverse()
bf4e7ef08741 fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
twaldmann@thinkmo.de
parents: 1528
diff changeset
   325
    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
   326
    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
   327
        a.pop()
bf4e7ef08741 fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
twaldmann@thinkmo.de
parents: 1528
diff changeset
   328
        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
   329
    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
   330
    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
   331
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   332
def canonpath(root, cwd, myname):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   333
    """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
   334
    if root == os.sep:
8befbb4e30b2 Handle hg under /
Arun Sharma <arun@sharma-home.net>
parents: 1563
diff changeset
   335
        rootsep = os.sep
2271
90b122730d32 Make it possible to use the root directory as the root of a repository.
Manpreet Singh <junkblocker@yahoo.com>
parents: 2263
diff changeset
   336
    elif root.endswith(os.sep):
90b122730d32 Make it possible to use the root directory as the root of a repository.
Manpreet Singh <junkblocker@yahoo.com>
parents: 2263
diff changeset
   337
        rootsep = root
1566
8befbb4e30b2 Handle hg under /
Arun Sharma <arun@sharma-home.net>
parents: 1563
diff changeset
   338
    else:
1810
7596611ab3d5 Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1635
diff changeset
   339
        rootsep = root + os.sep
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   340
    name = myname
2090
eb40db373717 fix util.canonpath on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2085
diff changeset
   341
    if not os.path.isabs(name):
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   342
        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
   343
    name = os.path.normpath(name)
2278
3711e23ab10a Make hg status work for repositories in root directory on windows (issue 228)
Manpreet Singh <junkblocker@yahoo.com>
parents: 2271
diff changeset
   344
    if name != rootsep and 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
   345
        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
   346
        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
   347
        return pconvert(name)
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   348
    elif name == root:
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   349
        return ''
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   350
    else:
2115
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   351
        # Determine whether `name' is in the hierarchy at or beneath `root',
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   352
        # by iterating name=dirname(name) until that causes no change (can't
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   353
        # check name == '/', because that doesn't work on windows).  For each
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   354
        # `name', compare dev/inode numbers.  If they match, the list `rel'
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   355
        # holds the reversed list of components making up the relative file
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   356
        # name we want.
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   357
        root_st = os.stat(root)
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   358
        rel = []
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   359
        while True:
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   360
            try:
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   361
                name_st = os.stat(name)
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   362
            except OSError:
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   363
                break
2193
fb28ce04b349 add util.samestat function for windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2177
diff changeset
   364
            if samestat(name_st, root_st):
2115
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   365
                rel.reverse()
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   366
                name = os.path.join(*rel)
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   367
                audit_path(name)
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   368
                return pconvert(name)
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   369
            dirname, basename = os.path.split(name)
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   370
            rel.append(basename)
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   371
            if dirname == name:
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   372
                break
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   373
            name = dirname
fd77b7ee4aac Fix issue 165: `hg status' with abs path containing a symlink-to-dir fails
Jim Meyering <list+hg@meyering.net>
parents: 2096
diff changeset
   374
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   375
        raise Abort('%s not under root' % myname)
897
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   376
1610
84e9b3484ff6 if hgignore contains errors, print message that is not confusing.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1609
diff changeset
   377
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
   378
    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
   379
4055
e37786b29bed docopy: deal with globs on windows in a better way
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4054
diff changeset
   380
def cmdmatcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head='',
e37786b29bed docopy: deal with globs on windows in a better way
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4054
diff changeset
   381
               src=None, globbed=False):
e37786b29bed docopy: deal with globs on windows in a better way
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4054
diff changeset
   382
    if not globbed:
e37786b29bed docopy: deal with globs on windows in a better way
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4054
diff changeset
   383
        names = expand_glob(names)
4054
e6d54283c090 Explicitly expand globs on Windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3905
diff changeset
   384
    return _matcher(canonroot, cwd, names, inc, exc, head, 'relpath', src)
1413
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   385
1610
84e9b3484ff6 if hgignore contains errors, print message that is not confusing.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1609
diff changeset
   386
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
   387
    """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
   388
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   389
    arguments:
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   390
    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
   391
    cwd - the current working directory, if relevant
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   392
    names - patterns to find
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   393
    inc - patterns to include
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   394
    exc - patterns to exclude
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   395
    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
   396
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   397
    a pattern is one of:
1270
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   398
    'glob:<rooted glob>'
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   399
    're:<rooted regexp>'
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   400
    'path:<rooted path>'
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   401
    'relglob:<relative glob>'
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   402
    'relpath:<relative path>'
1270
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   403
    'relre:<relative regexp>'
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   404
    '<rooted path or regexp>'
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   405
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   406
    returns:
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   407
    a 3-tuple containing
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   408
    - list of explicit non-pattern names passed in
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   409
    - a bool match(filename) function
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   410
    - a bool indicating if any patterns were passed in
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   411
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   412
    todo:
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   413
    make head regex a rooted bool
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   414
    """
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   415
1413
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   416
    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
   417
        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
   418
            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
   419
        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
   420
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   421
    def regex(kind, name, tail):
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   422
        '''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
   423
        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
   424
            return name
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   425
        elif kind == 'path':
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   426
            return '^' + re.escape(name) + '(?:/|$)'
1270
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   427
        elif kind == 'relglob':
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   428
            return head + globre(name, '(?:|.*/)', tail)
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   429
        elif kind == 'relpath':
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   430
            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
   431
        elif kind == 'relre':
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   432
            if name.startswith('^'):
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   433
                return name
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   434
            return '.*' + name
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   435
        return head + globre(name, '', tail)
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   436
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   437
    def matchfn(pats, tail):
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   438
        """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
   439
        if not pats:
f4250806dbeb further fix traceback on invalid .hgignore patterns
Benoit Boissinot <mercurial-bugs@selenic.com>
parents: 1446
diff changeset
   440
            return
1446
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   441
        matches = []
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   442
        for k, p in pats:
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   443
            try:
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   444
                pat = '(?:%s)' % regex(k, p, tail)
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   445
                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
   446
            except re.error:
1611
301d5cd4abc6 make invalid pattern message not confusing.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1610
diff changeset
   447
                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
   448
                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
   449
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   450
        def buildfn(text):
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   451
            for m in matches:
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   452
                r = m(text)
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   453
                if r:
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   454
                    return r
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   455
4babaa52badf abort on invalid pattern in matcher
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1420
diff changeset
   456
        return buildfn
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   457
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   458
    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
   459
        '''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
   460
        root = []
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   461
        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
   462
            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
   463
            root.append(p)
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   464
        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
   465
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   466
    pats = []
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   467
    files = []
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   468
    roots = []
1413
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   469
    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
   470
        if kind in ('glob', 'relpath'):
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   471
            name = canonpath(canonroot, cwd, name)
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   472
            if name == '':
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   473
                kind, name = 'glob', '**'
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   474
        if kind in ('glob', 'path', 're'):
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   475
            pats.append((kind, name))
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   476
        if kind == 'glob':
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   477
            root = globprefix(name)
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   478
            if root: roots.append(root)
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   479
        elif kind == 'relpath':
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   480
            files.append((kind, name))
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   481
            roots.append(name)
897
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   482
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   483
    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
   484
    filematch = matchfn(files, '(?:/|$)') or always
897
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   485
    incmatch = always
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   486
    if inc:
2480
519a1011db91 fix -I/-X when relative paths used or in subdir
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2471
diff changeset
   487
        inckinds = [patkind(canonpath(canonroot, cwd, i)) for i in inc]
519a1011db91 fix -I/-X when relative paths used or in subdir
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2471
diff changeset
   488
        incmatch = matchfn(inckinds, '(?:/|$)')
897
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   489
    excmatch = lambda fn: False
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   490
    if exc:
2480
519a1011db91 fix -I/-X when relative paths used or in subdir
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2471
diff changeset
   491
        exckinds = [patkind(canonpath(canonroot, cwd, x)) for x in exc]
519a1011db91 fix -I/-X when relative paths used or in subdir
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2471
diff changeset
   492
        excmatch = matchfn(exckinds, '(?:/|$)')
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   493
1031
503aaf19a040 Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1015
diff changeset
   494
    return (roots,
503aaf19a040 Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1015
diff changeset
   495
            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
   496
                        (fn.endswith('/') or
503aaf19a040 Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1015
diff changeset
   497
                         (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
   498
                         (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
   499
                         (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
   500
            (inc or exc or (pats and pats != [('glob', '**')])) and True)
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   501
1882
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   502
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
   503
    '''enhanced shell command execution.
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   504
    run with environment maybe modified, maybe in different dir.
508
42a660abaf75 [PATCH] Harden os.system
mpm@selenic.com
parents: 464
diff changeset
   505
1882
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   506
    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
   507
    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
   508
    exception.'''
2601
00fc88b0b256 move most of tag code to localrepository class.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
   509
    def py2shell(val):
00fc88b0b256 move most of tag code to localrepository class.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
   510
        'convert python object into string that is useful to shell'
00fc88b0b256 move most of tag code to localrepository class.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
   511
        if val in (None, False):
00fc88b0b256 move most of tag code to localrepository class.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
   512
            return '0'
00fc88b0b256 move most of tag code to localrepository class.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
   513
        if val == True:
00fc88b0b256 move most of tag code to localrepository class.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
   514
            return '1'
00fc88b0b256 move most of tag code to localrepository class.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
   515
        return str(val)
1880
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   516
    oldenv = {}
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   517
    for k in environ:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   518
        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
   519
    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
   520
        oldcwd = os.getcwd()
3905
a8c0365b2ace util.system: fix quoting on windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3860
diff changeset
   521
    origcmd = cmd
a8c0365b2ace util.system: fix quoting on windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3860
diff changeset
   522
    if os.name == 'nt':
a8c0365b2ace util.system: fix quoting on windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3860
diff changeset
   523
        cmd = '"%s"' % cmd
1880
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   524
    try:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   525
        for k, v in environ.iteritems():
2601
00fc88b0b256 move most of tag code to localrepository class.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
   526
            os.environ[k] = py2shell(v)
1880
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   527
        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
   528
            os.chdir(cwd)
1882
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   529
        rc = os.system(cmd)
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   530
        if rc and onerr:
3905
a8c0365b2ace util.system: fix quoting on windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3860
diff changeset
   531
            errmsg = '%s %s' % (os.path.basename(origcmd.split(None, 1)[0]),
1882
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   532
                                explain_exit(rc)[0])
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   533
            if errprefix:
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   534
                errmsg = '%s: %s' % (errprefix, errmsg)
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   535
            try:
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   536
                onerr.warn(errmsg + '\n')
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   537
            except AttributeError:
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   538
                raise onerr(errmsg)
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   539
        return rc
1880
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   540
    finally:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   541
        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
   542
            if v is None:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   543
                del os.environ[k]
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   544
            else:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   545
                os.environ[k] = v
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   546
        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
   547
            os.chdir(oldcwd)
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   548
421
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   549
def rename(src, dst):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   550
    """forcibly rename a file"""
421
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   551
    try:
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   552
        os.rename(src, dst)
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   553
    except OSError, err:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   554
        # on windows, rename to existing file is not allowed, so we
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   555
        # must delete destination first. but if file is open, unlink
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   556
        # schedules it for delete but does not delete it. rename
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   557
        # happens immediately even for open files, so we create
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   558
        # temporary file, delete it, rename destination to that name,
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   559
        # then delete that. then rename is safe to do.
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   560
        fd, temp = tempfile.mkstemp(dir=os.path.dirname(dst) or '.')
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   561
        os.close(fd)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   562
        os.unlink(temp)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   563
        os.rename(dst, temp)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   564
        os.unlink(temp)
421
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   565
        os.rename(src, dst)
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   566
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
   567
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
   568
    """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
   569
    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
   570
    # 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
   571
    try:
547ede0123a2 util.unlink should only catch OSError.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2054
diff changeset
   572
        os.removedirs(os.path.dirname(f))
547ede0123a2 util.unlink should only catch OSError.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2054
diff changeset
   573
    except OSError:
547ede0123a2 util.unlink should only catch OSError.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2054
diff changeset
   574
        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
   575
3629
4cfb72bcb978 util: add copyfile function
Matt Mackall <mpm@selenic.com>
parents: 3568
diff changeset
   576
def copyfile(src, dest):
4cfb72bcb978 util: add copyfile function
Matt Mackall <mpm@selenic.com>
parents: 3568
diff changeset
   577
    "copy a file, preserving mode"
4cfb72bcb978 util: add copyfile function
Matt Mackall <mpm@selenic.com>
parents: 3568
diff changeset
   578
    try:
4cfb72bcb978 util: add copyfile function
Matt Mackall <mpm@selenic.com>
parents: 3568
diff changeset
   579
        shutil.copyfile(src, dest)
4cfb72bcb978 util: add copyfile function
Matt Mackall <mpm@selenic.com>
parents: 3568
diff changeset
   580
        shutil.copymode(src, dest)
4cfb72bcb978 util: add copyfile function
Matt Mackall <mpm@selenic.com>
parents: 3568
diff changeset
   581
    except shutil.Error, inst:
4067
c620376b8fd6 Fix wrong module reference in copyfile exception
Andrei Vermel <avermel@mail.ru>
parents: 4057
diff changeset
   582
        raise Abort(str(inst))
3629
4cfb72bcb978 util: add copyfile function
Matt Mackall <mpm@selenic.com>
parents: 3568
diff changeset
   583
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   584
def copyfiles(src, dst, hardlink=None):
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   585
    """Copy a directory tree using hardlinks if possible"""
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   586
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   587
    if hardlink is None:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   588
        hardlink = (os.stat(src).st_dev ==
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   589
                    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
   590
1207
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   591
    if os.path.isdir(src):
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   592
        os.mkdir(dst)
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   593
        for name in os.listdir(src):
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   594
            srcname = os.path.join(src, name)
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   595
            dstname = os.path.join(dst, name)
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   596
            copyfiles(srcname, dstname, hardlink)
1207
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   597
    else:
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   598
        if hardlink:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   599
            try:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   600
                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
   601
            except (IOError, OSError):
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   602
                hardlink = False
1591
5a3229cf1492 do not copy atime and mtime in util.copyfiles
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1585
diff changeset
   603
                shutil.copy(src, dst)
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   604
        else:
1591
5a3229cf1492 do not copy atime and mtime in util.copyfiles
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1585
diff changeset
   605
            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
   606
1835
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   607
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
   608
    """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
   609
    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
   610
    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
   611
        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
   612
        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
   613
704
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   614
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
   615
    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
   616
    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
   617
    os.close(ld)
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   618
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   619
def _readlock_file(pathname):
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   620
    return posixfile(pathname).read()
704
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   621
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   622
def nlinks(pathname):
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   623
    """Return number of hardlinks for the given file."""
2448
b77a2ef61b81 replace os.stat with os.lstat in some where.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2314
diff changeset
   624
    return os.lstat(pathname).st_nlink
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   625
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   626
if hasattr(os, 'link'):
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   627
    os_link = os.link
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   628
else:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   629
    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
   630
        raise OSError(0, _("Hardlinks not supported"))
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   631
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   632
def fstat(fp):
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   633
    '''stat file object that may not have fileno method.'''
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   634
    try:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   635
        return os.fstat(fp.fileno())
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   636
    except AttributeError:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   637
        return os.stat(fp.name)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   638
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   639
posixfile = file
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   640
2250
45aef5ddcdbe windows: revlog.lazyparser not always safe to use.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2237
diff changeset
   641
def is_win_9x():
45aef5ddcdbe windows: revlog.lazyparser not always safe to use.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2237
diff changeset
   642
    '''return true if run on windows 95, 98 or me.'''
45aef5ddcdbe windows: revlog.lazyparser not always safe to use.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2237
diff changeset
   643
    try:
45aef5ddcdbe windows: revlog.lazyparser not always safe to use.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2237
diff changeset
   644
        return sys.getwindowsversion()[3] == 1
45aef5ddcdbe windows: revlog.lazyparser not always safe to use.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2237
diff changeset
   645
    except AttributeError:
45aef5ddcdbe windows: revlog.lazyparser not always safe to use.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2237
diff changeset
   646
        return os.name == 'nt' and 'command' in os.environ.get('comspec', '')
45aef5ddcdbe windows: revlog.lazyparser not always safe to use.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2237
diff changeset
   647
3721
98f2507c5551 only print a warning when no username is specified
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3677
diff changeset
   648
getuser_fallback = None
98f2507c5551 only print a warning when no username is specified
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3677
diff changeset
   649
98f2507c5551 only print a warning when no username is specified
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3677
diff changeset
   650
def getuser():
98f2507c5551 only print a warning when no username is specified
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3677
diff changeset
   651
    '''return name of current user'''
98f2507c5551 only print a warning when no username is specified
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3677
diff changeset
   652
    try:
98f2507c5551 only print a warning when no username is specified
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3677
diff changeset
   653
        return getpass.getuser()
98f2507c5551 only print a warning when no username is specified
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3677
diff changeset
   654
    except ImportError:
98f2507c5551 only print a warning when no username is specified
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3677
diff changeset
   655
        # import of pwd will fail on windows - try fallback
98f2507c5551 only print a warning when no username is specified
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3677
diff changeset
   656
        if getuser_fallback:
98f2507c5551 only print a warning when no username is specified
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3677
diff changeset
   657
            return getuser_fallback()
98f2507c5551 only print a warning when no username is specified
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3677
diff changeset
   658
    # raised if win32api not available
98f2507c5551 only print a warning when no username is specified
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3677
diff changeset
   659
    raise Abort(_('user name not available - set USERNAME '
98f2507c5551 only print a warning when no username is specified
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3677
diff changeset
   660
                  'environment variable'))
98f2507c5551 only print a warning when no username is specified
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3677
diff changeset
   661
3551
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   662
def username(uid=None):
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   663
    """Return the name of the user with the given uid.
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   664
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   665
    If uid is None, return the name of the current user."""
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   666
    try:
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   667
        import pwd
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   668
        if uid is None:
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   669
            uid = os.getuid()
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   670
        try:
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   671
            return pwd.getpwuid(uid)[0]
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   672
        except KeyError:
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   673
            return str(uid)
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   674
    except ImportError:
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   675
        return None
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   676
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   677
def groupname(gid=None):
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   678
    """Return the name of the group with the given gid.
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   679
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   680
    If gid is None, return the name of the current group."""
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   681
    try:
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   682
        import grp
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   683
        if gid is None:
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   684
            gid = os.getgid()
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   685
        try:
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   686
            return grp.getgrgid(gid)[0]
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   687
        except KeyError:
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   688
            return str(gid)
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   689
    except ImportError:
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   690
        return None
3b07e223534b Only read .hg/hgrc files from trusted users/groups
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3466
diff changeset
   691
3784
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   692
# File system features
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   693
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   694
def checkfolding(path):
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   695
    """
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   696
    Check whether the given path is on a case-sensitive filesystem
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   697
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   698
    Requires a path (like /foo/.hg) ending with a foldable final
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   699
    directory component.
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   700
    """
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   701
    s1 = os.stat(path)
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   702
    d, b = os.path.split(path)
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   703
    p2 = os.path.join(d, b.upper())
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   704
    if path == p2:
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   705
        p2 = os.path.join(d, b.lower())
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   706
    try:
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   707
        s2 = os.stat(p2)
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   708
        if s2 == s1:
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   709
            return False
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   710
        return True
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   711
    except:
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   712
        return True
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   713
3994
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   714
def checkexec(path):
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   715
    """
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   716
    Check whether the given path is on a filesystem with UNIX-like exec flags
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   717
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   718
    Requires a directory (like /foo/.hg)
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   719
    """
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   720
    fh, fn = tempfile.mkstemp("", "", path)
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   721
    os.close(fh)
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   722
    m = os.stat(fn).st_mode
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   723
    os.chmod(fn, m ^ 0111)
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   724
    r = (os.stat(fn).st_mode != m)
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   725
    os.unlink(fn)
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   726
    return r
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   727
3996
c190df14338c exec: add execfunc to simplify exec flag support on non-exec filesystems
Matt Mackall <mpm@selenic.com>
parents: 3995
diff changeset
   728
def execfunc(path, fallback):
c190df14338c exec: add execfunc to simplify exec flag support on non-exec filesystems
Matt Mackall <mpm@selenic.com>
parents: 3995
diff changeset
   729
    '''return an is_exec() function with default to fallback'''
c190df14338c exec: add execfunc to simplify exec flag support on non-exec filesystems
Matt Mackall <mpm@selenic.com>
parents: 3995
diff changeset
   730
    if checkexec(path):
3997
3f0ba82c103f exec: remove last flag from is_exec
Matt Mackall <mpm@selenic.com>
parents: 3996
diff changeset
   731
        return lambda x: is_exec(os.path.join(path, x))
3996
c190df14338c exec: add execfunc to simplify exec flag support on non-exec filesystems
Matt Mackall <mpm@selenic.com>
parents: 3995
diff changeset
   732
    return fallback
c190df14338c exec: add execfunc to simplify exec flag support on non-exec filesystems
Matt Mackall <mpm@selenic.com>
parents: 3995
diff changeset
   733
4002
d7b9ec589546 symlinks: use is_link wherever is_exec is used
Matt Mackall <mpm@selenic.com>
parents: 4000
diff changeset
   734
def checklink(path):
3998
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   735
    """check whether the given path is on a symlink-capable filesystem"""
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   736
    # mktemp is not racy because symlink creation will fail if the
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   737
    # file already exists
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   738
    name = tempfile.mktemp(dir=path)
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   739
    try:
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   740
        os.symlink(".", name)
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   741
        os.unlink(name)
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   742
        return True
4017
ea6174c96ae1 catch AttributeError in util.checklink
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4002
diff changeset
   743
    except (OSError, AttributeError):
3998
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   744
        return False
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   745
4000
3297aa945cf2 symlinks: add a linkfunc
Matt Mackall <mpm@selenic.com>
parents: 3999
diff changeset
   746
def linkfunc(path, fallback):
3297aa945cf2 symlinks: add a linkfunc
Matt Mackall <mpm@selenic.com>
parents: 3999
diff changeset
   747
    '''return an is_link() function with default to fallback'''
3297aa945cf2 symlinks: add a linkfunc
Matt Mackall <mpm@selenic.com>
parents: 3999
diff changeset
   748
    if checklink(path):
3297aa945cf2 symlinks: add a linkfunc
Matt Mackall <mpm@selenic.com>
parents: 3999
diff changeset
   749
        return lambda x: is_link(os.path.join(path, x))
3297aa945cf2 symlinks: add a linkfunc
Matt Mackall <mpm@selenic.com>
parents: 3999
diff changeset
   750
    return fallback
3297aa945cf2 symlinks: add a linkfunc
Matt Mackall <mpm@selenic.com>
parents: 3999
diff changeset
   751
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   752
# Platform specific variants
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   753
if os.name == 'nt':
3877
abaee83ce0a6 Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents: 3860
diff changeset
   754
    import msvcrt
461
9ae0034f2772 [PATCH] /dev/null for other OS
mpm@selenic.com
parents: 441
diff changeset
   755
    nulldev = 'NUL:'
1609
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   756
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   757
    class winstdout:
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   758
        '''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
   759
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   760
        def __init__(self, fp):
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   761
            self.fp = fp
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   762
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   763
        def __getattr__(self, key):
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   764
            return getattr(self.fp, key)
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   765
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   766
        def close(self):
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   767
            try:
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   768
                self.fp.close()
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   769
            except: pass
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   770
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   771
        def write(self, s):
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   772
            try:
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   773
                return self.fp.write(s)
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   774
            except IOError, inst:
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   775
                if inst.errno != 0: raise
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   776
                self.close()
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   777
                raise IOError(errno.EPIPE, 'Broken pipe')
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   778
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   779
    sys.stdout = winstdout(sys.stdout)
c50bddfbc812 eliminate backtrace when piping output on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1594
diff changeset
   780
2054
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   781
    def system_rcpath():
2117
760339ccc799 fix issue 217.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2115
diff changeset
   782
        try:
760339ccc799 fix issue 217.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2115
diff changeset
   783
            return system_rcpath_win32()
760339ccc799 fix issue 217.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2115
diff changeset
   784
        except:
760339ccc799 fix issue 217.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2115
diff changeset
   785
            return [r'c:\mercurial\mercurial.ini']
2054
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   786
1951
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   787
    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
   788
        '''return default os-specific hgrc search path'''
2280
09ed44225571 On Windows look for mercurial.ini in $USERPROFILE, too, if available
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2278
diff changeset
   789
        path = system_rcpath()
2284
d6392a7c03dd On win98 os.path.expanuser('~') does not result in a useable directory.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 2280
diff changeset
   790
        path.append(user_rcpath())
2280
09ed44225571 On Windows look for mercurial.ini in $USERPROFILE, too, if available
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2278
diff changeset
   791
        userprofile = os.environ.get('USERPROFILE')
09ed44225571 On Windows look for mercurial.ini in $USERPROFILE, too, if available
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2278
diff changeset
   792
        if userprofile:
09ed44225571 On Windows look for mercurial.ini in $USERPROFILE, too, if available
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2278
diff changeset
   793
            path.append(os.path.join(userprofile, 'mercurial.ini'))
09ed44225571 On Windows look for mercurial.ini in $USERPROFILE, too, if available
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2278
diff changeset
   794
        return path
1292
141951276ba1 Use platform-appropriate rc file names.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1285
diff changeset
   795
2284
d6392a7c03dd On win98 os.path.expanuser('~') does not result in a useable directory.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 2280
diff changeset
   796
    def user_rcpath():
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3669
diff changeset
   797
        '''return os-specific hgrc search path to the user dir'''
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3669
diff changeset
   798
        return os.path.join(os.path.expanduser('~'), 'mercurial.ini')
2284
d6392a7c03dd On win98 os.path.expanuser('~') does not result in a useable directory.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 2280
diff changeset
   799
1285
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   800
    def parse_patch_output(output_line):
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   801
        """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
   802
        pf = output_line[14:]
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   803
        if pf[0] == '`':
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   804
            pf = pf[1:-1] # Remove the quotes
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   805
        return pf
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   806
2054
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   807
    def testpid(pid):
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   808
        '''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
   809
        return True
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   810
441
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   811
    def set_exec(f, mode):
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   812
        pass
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   813
3999
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   814
    def set_link(f, mode):
441
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   815
        pass
515
03f27b1381f9 Whitespace cleanups
mpm@selenic.com
parents: 508
diff changeset
   816
1420
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   817
    def set_binary(fd):
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   818
        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
   819
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   820
    def pconvert(path):
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   821
        return path.replace("\\", "/")
422
10c43444a38e [PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents: 421
diff changeset
   822
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   823
    def localpath(path):
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   824
        return path.replace('/', '\\')
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   825
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   826
    def normpath(path):
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   827
        return pconvert(os.path.normpath(path))
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   828
704
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   829
    makelock = _makelock_file
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   830
    readlock = _readlock_file
461
9ae0034f2772 [PATCH] /dev/null for other OS
mpm@selenic.com
parents: 441
diff changeset
   831
2193
fb28ce04b349 add util.samestat function for windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2177
diff changeset
   832
    def samestat(s1, s2):
fb28ce04b349 add util.samestat function for windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2177
diff changeset
   833
        return False
fb28ce04b349 add util.samestat function for windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2177
diff changeset
   834
2791
f4d916351366 Add portable shell-quoting function; teach mq to use it.
Brendan Cully <brendan@kublai.com>
parents: 2760
diff changeset
   835
    def shellquote(s):
f4d916351366 Add portable shell-quoting function; teach mq to use it.
Brendan Cully <brendan@kublai.com>
parents: 2760
diff changeset
   836
        return '"%s"' % s.replace('"', '\\"')
f4d916351366 Add portable shell-quoting function; teach mq to use it.
Brendan Cully <brendan@kublai.com>
parents: 2760
diff changeset
   837
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   838
    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
   839
        return _("exited with status %d") % code, code
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   840
3677
1a0fa3914c46 Avoid looking up usernames if the current user owns the .hgrc file
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   841
    # if you change this stub into a real check, please try to implement the
1a0fa3914c46 Avoid looking up usernames if the current user owns the .hgrc file
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   842
    # username and groupname functions above, too.
1a0fa3914c46 Avoid looking up usernames if the current user owns the .hgrc file
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   843
    def isowner(fp, st=None):
1a0fa3914c46 Avoid looking up usernames if the current user owns the .hgrc file
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   844
        return True
1a0fa3914c46 Avoid looking up usernames if the current user owns the .hgrc file
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   845
2054
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   846
    try:
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   847
        # override functions with win32 versions if possible
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   848
        from util_win32 import *
2250
45aef5ddcdbe windows: revlog.lazyparser not always safe to use.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2237
diff changeset
   849
        if not is_win_9x():
45aef5ddcdbe windows: revlog.lazyparser not always safe to use.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2237
diff changeset
   850
            posixfile = posixfile_nt
2054
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   851
    except ImportError:
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   852
        pass
e18beba54a7e fix exception handling on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2050
diff changeset
   853
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   854
else:
461
9ae0034f2772 [PATCH] /dev/null for other OS
mpm@selenic.com
parents: 441
diff changeset
   855
    nulldev = '/dev/null'
3995
a4e79f86d304 pull umask-checking up
Matt Mackall <mpm@selenic.com>
parents: 3994
diff changeset
   856
    _umask = os.umask(0)
a4e79f86d304 pull umask-checking up
Matt Mackall <mpm@selenic.com>
parents: 3994
diff changeset
   857
    os.umask(_umask)
461
9ae0034f2772 [PATCH] /dev/null for other OS
mpm@selenic.com
parents: 441
diff changeset
   858
1583
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   859
    def rcfiles(path):
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   860
        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
   861
        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
   862
        try:
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   863
            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
   864
                        if f.endswith(".rc")])
3131
cff3c58a5766 fix warnings spotted by pychecker
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3098
diff changeset
   865
        except OSError:
cff3c58a5766 fix warnings spotted by pychecker
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3098
diff changeset
   866
            pass
1583
32a4e6802864 make mercurial look in more places for config files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1482
diff changeset
   867
        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
   868
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   869
    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
   870
        '''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
   871
        path = []
2263
2f64cbaa1e92 make reason for sys.argv change obvious in code.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2262
diff changeset
   872
        # old mod_python does not set sys.argv
2261
20cf545b4725 Check existance of sys.argv for the use from mod_python.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 2237
diff changeset
   873
        if len(getattr(sys, 'argv', [])) > 0:
1951
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
   874
            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
   875
                                  '/../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
   876
        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
   877
        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
   878
        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
   879
        return path
1292
141951276ba1 Use platform-appropriate rc file names.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1285
diff changeset
   880
1285
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   881
    def parse_patch_output(output_line):
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   882
        """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
   883
        pf = output_line[14:]
2579
0875cda033fd use __contains__, index or split instead of str.find
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2546
diff changeset
   884
        if pf.startswith("'") and pf.endswith("'") and " " in pf:
1593
6bb3463b124b if a filename contains spaces, patch adds quote around it
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1585
diff changeset
   885
            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
   886
        return pf
1285
1546c2aa6b30 Make 'hg import' platform independent.
Volker Kleinfeld <Volker.Kleinfeld@gmx.de>
parents: 1270
diff changeset
   887
3997
3f0ba82c103f exec: remove last flag from is_exec
Matt Mackall <mpm@selenic.com>
parents: 3996
diff changeset
   888
    def is_exec(f):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   889
        """check whether a file is executable"""
2448
b77a2ef61b81 replace os.stat with os.lstat in some where.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2314
diff changeset
   890
        return (os.lstat(f).st_mode & 0100 != 0)
441
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   891
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   892
    def set_exec(f, mode):
2448
b77a2ef61b81 replace os.stat with os.lstat in some where.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2314
diff changeset
   893
        s = os.lstat(f).st_mode
441
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   894
        if (s & 0100 != 0) == mode:
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   895
            return
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   896
        if mode:
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   897
            # 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
   898
            # and obey umask.
3995
a4e79f86d304 pull umask-checking up
Matt Mackall <mpm@selenic.com>
parents: 3994
diff changeset
   899
            os.chmod(f, s | (s & 0444) >> 2 & ~_umask)
441
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   900
        else:
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   901
            os.chmod(f, s & 0666)
e8af362cfb01 Permission handling for the other OS
mpm@selenic.com
parents: 422
diff changeset
   902
3999
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   903
    def is_link(f):
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   904
        """check whether a file is a symlink"""
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   905
        return (os.lstat(f).st_mode & 0120000 == 0120000)
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   906
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   907
    def set_link(f, mode):
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   908
        """make a file a symbolic link/regular file
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   909
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   910
        if a file is changed to a link, its contents become the link data
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   911
        if a link is changed to a file, its link data become its contents
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   912
        """
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   913
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   914
        m = is_link(f)
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   915
        if m == bool(mode):
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   916
            return
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   917
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   918
        if mode: # switch file to link
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   919
            data = file(f).read()
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   920
            os.unlink(f)
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   921
            os.symlink(data, f)
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   922
        else:
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   923
            data = os.readlink(f)
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   924
            os.unlink(f)
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   925
            file(f, "w").write(data)
0b740dcf0cf1 symlinks: add basic symlink functions to util.py
Matt Mackall <mpm@selenic.com>
parents: 3998
diff changeset
   926
1420
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   927
    def set_binary(fd):
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   928
        pass
b32b3509c7ab Avoid insertion/deletion of CRs on stdio during hg serve
olivier.maquelin@intel.com
parents: 1415
diff changeset
   929
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   930
    def pconvert(path):
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   931
        return path
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   932
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   933
    def localpath(path):
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   934
        return path
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   935
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   936
    normpath = os.path.normpath
2193
fb28ce04b349 add util.samestat function for windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2177
diff changeset
   937
    samestat = os.path.samestat
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   938
422
10c43444a38e [PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents: 421
diff changeset
   939
    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
   940
        try:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   941
            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
   942
        except OSError, why:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   943
            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
   944
                raise
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   945
            else:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   946
                _makelock_file(info, pathname)
422
10c43444a38e [PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents: 421
diff changeset
   947
10c43444a38e [PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents: 421
diff changeset
   948
    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
   949
        try:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   950
            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
   951
        except OSError, why:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   952
            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
   953
                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
   954
            else:
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   955
                raise
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   956
2791
f4d916351366 Add portable shell-quoting function; teach mq to use it.
Brendan Cully <brendan@kublai.com>
parents: 2760
diff changeset
   957
    def shellquote(s):
f4d916351366 Add portable shell-quoting function; teach mq to use it.
Brendan Cully <brendan@kublai.com>
parents: 2760
diff changeset
   958
        return "'%s'" % s.replace("'", "'\\''")
f4d916351366 Add portable shell-quoting function; teach mq to use it.
Brendan Cully <brendan@kublai.com>
parents: 2760
diff changeset
   959
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1835
diff changeset
   960
    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
   961
        '''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
   962
        try:
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1835
diff changeset
   963
            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
   964
            return True
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1835
diff changeset
   965
        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
   966
            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
   967
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   968
    def explain_exit(code):
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   969
        """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
   970
        if os.WIFEXITED(code):
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   971
            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
   972
            return _("exited with status %d") % val, val
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   973
        elif os.WIFSIGNALED(code):
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   974
            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
   975
            return _("killed by signal %d") % val, val
782
cdb9e95b2fab Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents: 742
diff changeset
   976
        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
   977
            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
   978
            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
   979
        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
   980
3677
1a0fa3914c46 Avoid looking up usernames if the current user owns the .hgrc file
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   981
    def isowner(fp, st=None):
1a0fa3914c46 Avoid looking up usernames if the current user owns the .hgrc file
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   982
        """Return True if the file object f belongs to the current user.
1a0fa3914c46 Avoid looking up usernames if the current user owns the .hgrc file
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   983
1a0fa3914c46 Avoid looking up usernames if the current user owns the .hgrc file
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   984
        The return value of a util.fstat(f) may be passed as the st argument.
1a0fa3914c46 Avoid looking up usernames if the current user owns the .hgrc file
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   985
        """
1a0fa3914c46 Avoid looking up usernames if the current user owns the .hgrc file
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   986
        if st is None:
3859
8c24b6fd5866 fix errors spotted by pychecker
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3854
diff changeset
   987
            st = fstat(fp)
3677
1a0fa3914c46 Avoid looking up usernames if the current user owns the .hgrc file
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   988
        return st.st_uid == os.getuid()
1a0fa3914c46 Avoid looking up usernames if the current user owns the .hgrc file
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
   989
3852
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
   990
def _buildencodefun():
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
   991
    e = '_'
3860
8e907b86126b fix reserved char on windows, '[]+' are allowed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3859
diff changeset
   992
    win_reserved = [ord(x) for x in '\\:*?"<>|']
3852
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
   993
    cmap = dict([ (chr(x), chr(x)) for x in xrange(127) ])
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
   994
    for x in (range(32) + range(126, 256) + win_reserved):
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
   995
        cmap[chr(x)] = "~%02x" % x
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
   996
    for x in range(ord("A"), ord("Z")+1) + [ord(e)]:
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
   997
        cmap[chr(x)] = e + chr(x).lower()
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
   998
    dmap = {}
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
   999
    for k, v in cmap.iteritems():
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1000
        dmap[v] = k
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1001
    def decode(s):
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1002
        i = 0
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1003
        while i < len(s):
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1004
            for l in xrange(1, 4):
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1005
                try:
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1006
                    yield dmap[s[i:i+l]]
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1007
                    i += l
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1008
                    break
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1009
                except KeyError:
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1010
                    pass
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1011
            else:
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1012
                raise KeyError
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1013
    return (lambda s: "".join([cmap[c] for c in s]),
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1014
            lambda s: "".join(list(decode(s))))
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1015
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1016
encodefilename, decodefilename = _buildencodefun()
8a9a1a7e1698 create the encode and decode functions for the store
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3784
diff changeset
  1017
3853
c0b449154a90 switch to the .hg/store layout, fix the tests
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3852
diff changeset
  1018
def encodedopener(openerfn, fn):
c0b449154a90 switch to the .hg/store layout, fix the tests
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3852
diff changeset
  1019
    def o(path, *args, **kw):
c0b449154a90 switch to the .hg/store layout, fix the tests
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3852
diff changeset
  1020
        return openerfn(fn(path), *args, **kw)
c0b449154a90 switch to the .hg/store layout, fix the tests
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3852
diff changeset
  1021
    return o
3677
1a0fa3914c46 Avoid looking up usernames if the current user owns the .hgrc file
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3673
diff changeset
  1022
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1023
def opener(base, audit=True):
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1024
    """
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1025
    return a function that opens files relative to base
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1026
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1027
    this function is used to hide the details of COW semantics and
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1028
    remote file access from higher level code.
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1029
    """
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1030
    p = base
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1031
    audit_p = audit
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1032
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1033
    def mktempcopy(name):
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1034
        d, fn = os.path.split(name)
2177
6886bc0b77af merge with crew.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2165 2176
diff changeset
  1035
        fd, temp = tempfile.mkstemp(prefix='.%s-' % fn, dir=d)
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1036
        os.close(fd)
2237
4a069064a39b reduce memory used by util.opener when making a temp copy of a file.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2220
diff changeset
  1037
        ofp = posixfile(temp, "wb")
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1038
        try:
2220
6d3cc2a982f3 add filename to IOError if read of file fails.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2193
diff changeset
  1039
            try:
2237
4a069064a39b reduce memory used by util.opener when making a temp copy of a file.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2220
diff changeset
  1040
                ifp = posixfile(name, "rb")
2220
6d3cc2a982f3 add filename to IOError if read of file fails.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2193
diff changeset
  1041
            except IOError, inst:
6d3cc2a982f3 add filename to IOError if read of file fails.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2193
diff changeset
  1042
                if not getattr(inst, 'filename', None):
6d3cc2a982f3 add filename to IOError if read of file fails.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2193
diff changeset
  1043
                    inst.filename = name
6d3cc2a982f3 add filename to IOError if read of file fails.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2193
diff changeset
  1044
                raise
2237
4a069064a39b reduce memory used by util.opener when making a temp copy of a file.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2220
diff changeset
  1045
            for chunk in filechunkiter(ifp):
4a069064a39b reduce memory used by util.opener when making a temp copy of a file.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2220
diff changeset
  1046
                ofp.write(chunk)
4a069064a39b reduce memory used by util.opener when making a temp copy of a file.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2220
diff changeset
  1047
            ifp.close()
4a069064a39b reduce memory used by util.opener when making a temp copy of a file.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2220
diff changeset
  1048
            ofp.close()
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1049
        except:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1050
            try: os.unlink(temp)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1051
            except: pass
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1052
            raise
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1053
        st = os.lstat(name)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1054
        os.chmod(temp, st.st_mode)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1055
        return temp
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1056
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1057
    class atomictempfile(posixfile):
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1058
        """the file will only be copied when rename is called"""
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1059
        def __init__(self, name, mode):
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1060
            self.__name = name
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1061
            self.temp = mktempcopy(name)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1062
            posixfile.__init__(self, self.temp, mode)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1063
        def rename(self):
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1064
            if not self.closed:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1065
                posixfile.close(self)
2308
cb520d961d6a Use platform path for renaming file in util.atomictempfile.rename()
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2284
diff changeset
  1066
                rename(self.temp, localpath(self.__name))
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1067
        def __del__(self):
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1068
            if not self.closed:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1069
                try:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1070
                    os.unlink(self.temp)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1071
                except: pass
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1072
                posixfile.close(self)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1073
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1074
    class atomicfile(atomictempfile):
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1075
        """the file will only be copied on close"""
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1076
        def __init__(self, name, mode):
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1077
            atomictempfile.__init__(self, name, mode)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1078
        def close(self):
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1079
            self.rename()
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1080
        def __del__(self):
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1081
            self.rename()
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1082
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1083
    def o(path, mode="r", text=False, atomic=False, atomictemp=False):
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1084
        if audit_p:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1085
            audit_path(path)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1086
        f = os.path.join(p, path)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1087
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1088
        if not text:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1089
            mode += "b" # for that other OS
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1090
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1091
        if mode[0] != "r":
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1092
            try:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1093
                nlink = nlinks(f)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1094
            except OSError:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1095
                d = os.path.dirname(f)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1096
                if not os.path.isdir(d):
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1097
                    os.makedirs(d)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1098
            else:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1099
                if atomic:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1100
                    return atomicfile(f, mode)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1101
                elif atomictemp:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1102
                    return atomictempfile(f, mode)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1103
                if nlink > 1:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1104
                    rename(mktempcopy(f), f)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1105
        return posixfile(f, mode)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1106
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1107
    return o
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1108
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1109
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
  1110
    """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
  1111
    iterator over chunks of arbitrary size."""
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
  1112
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1113
    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
  1114
        """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
  1115
        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
  1116
        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
  1117
        self.buf = ''
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1118
        self.targetsize = int(targetsize)
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
  1119
        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
  1120
            raise ValueError(_("targetsize must be greater than 0, was %d") %
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
  1121
                             targetsize)
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1122
        self.iterempty = False
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
  1123
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1124
    def fillbuf(self):
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
  1125
        """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
  1126
        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
  1127
            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
  1128
            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
  1129
            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
  1130
                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
  1131
            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
  1132
            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
  1133
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1134
    def read(self, l):
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
  1135
        """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
  1136
        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
  1137
        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
  1138
            # 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
  1139
            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
  1140
            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
  1141
            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
  1142
            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
  1143
            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
  1144
                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
  1145
                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
  1146
                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
  1147
                    break
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1148
            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
  1149
                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
  1150
            self.buf = collector.getvalue()
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
  1151
        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
  1152
        return s
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1153
2462
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1154
def filechunkiter(f, size=65536, limit=None):
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1155
    """Create a generator that produces the data in the file size
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1156
    (default 65536) bytes at a time, up to optional limit (default is
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1157
    to read all data).  Chunks may be less than size bytes if the
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1158
    chunk is the last chunk in the file, or the file is a socket or
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1159
    some other type of file that sometimes reads less data than is
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1160
    requested."""
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1161
    assert size >= 0
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1162
    assert limit is None or limit >= 0
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1163
    while True:
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1164
        if limit is None: nbytes = size
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1165
        else: nbytes = min(limit, size)
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1166
        s = nbytes and f.read(nbytes)
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1167
        if not s: break
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1168
        if limit: limit -= len(s)
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1169
        yield s
1320
5f277e73778f Fix up representation of dates in hgweb.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1312
diff changeset
  1170
1321
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
  1171
def makedate():
1482
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
  1172
    lt = time.localtime()
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
  1173
    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
  1174
        tz = time.altzone
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
  1175
    else:
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
  1176
        tz = time.timezone
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
  1177
    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
  1178
1987
04c17fc39c84 add changelog style to command line template.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1976
diff changeset
  1179
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
  1180
    """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
  1181
    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
  1182
    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
  1183
    append time zone to string."""
1321
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
  1184
    t, tz = date or makedate()
1987
04c17fc39c84 add changelog style to command line template.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1976
diff changeset
  1185
    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
  1186
    if timezone:
04c17fc39c84 add changelog style to command line template.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1976
diff changeset
  1187
        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
  1188
    return s
1829
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1189
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1190
def strdate(string, format, defaults):
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1191
    """parse a localized time string and return a (unixtime, offset) tuple.
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1192
    if the string cannot be parsed, ValueError is raised."""
3809
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1193
    def timezone(string):
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1194
        tz = string.split()[-1]
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1195
        if tz[0] in "+-" and len(tz) == 5 and tz[1:].isdigit():
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1196
            tz = int(tz)
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1197
            offset = - 3600 * (tz / 100) - 60 * (tz % 100)
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1198
            return offset
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1199
        if tz == "GMT" or tz == "UTC":
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1200
            return 0
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1201
        return None
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1202
3255
e96d2956eb4a util.strdate: compute timestamp using UTC, not local timezone
Jose M. Prieto <jmprieto@gmx.net>
parents: 3176
diff changeset
  1203
    # NOTE: unixtime = localunixtime + offset
3809
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1204
    offset, date = timezone(string), string
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1205
    if offset != None:
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1206
        date = " ".join(string.split()[:-1])
3808
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
  1207
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1208
    # add missing elements from defaults
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1209
    for part in defaults:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1210
        found = [True for p in part if ("%"+p) in format]
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1211
        if not found:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1212
            date += "@" + defaults[part]
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1213
            format += "@%" + part[0]
3808
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
  1214
3256
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
  1215
    timetuple = time.strptime(date, format)
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
  1216
    localunixtime = int(calendar.timegm(timetuple))
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
  1217
    if offset is None:
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
  1218
        # local timezone
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
  1219
        unixtime = int(time.mktime(timetuple))
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
  1220
        offset = unixtime - localunixtime
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
  1221
    else:
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
  1222
        unixtime = localunixtime + offset
3255
e96d2956eb4a util.strdate: compute timestamp using UTC, not local timezone
Jose M. Prieto <jmprieto@gmx.net>
parents: 3176
diff changeset
  1223
    return unixtime, offset
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1224
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1225
def parsedate(string, formats=None, defaults=None):
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1226
    """parse a localized time string and return a (unixtime, offset) tuple.
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1227
    The date may be a "unixtime offset" string or in one of the specified
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1228
    formats."""
3807
e43b48f0f718 parsedate: allow '' for epoch
Matt Mackall <mpm@selenic.com>
parents: 3806
diff changeset
  1229
    if not string:
e43b48f0f718 parsedate: allow '' for epoch
Matt Mackall <mpm@selenic.com>
parents: 3806
diff changeset
  1230
        return 0, 0
2609
6c5b1b5cc160 util.parsedate should understand dates from hg export
Chris Mason <mason@suse.com>
parents: 2601
diff changeset
  1231
    if not formats:
6c5b1b5cc160 util.parsedate should understand dates from hg export
Chris Mason <mason@suse.com>
parents: 2601
diff changeset
  1232
        formats = defaultdateformats
3808
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
  1233
    string = string.strip()
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1234
    try:
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1235
        when, offset = map(int, string.split(' '))
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1236
    except ValueError:
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1237
        # fill out defaults
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1238
        if not defaults:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1239
            defaults = {}
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1240
        now = makedate()
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1241
        for part in "d mb yY HI M S".split():
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1242
            if part not in defaults:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1243
                if part[0] in "HMS":
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1244
                    defaults[part] = "00"
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1245
                elif part[0] in "dm":
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1246
                    defaults[part] = "1"
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1247
                else:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1248
                    defaults[part] = datestr(now, "%" + part[0], False)
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1249
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1250
        for format in formats:
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1251
            try:
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1252
                when, offset = strdate(string, format, defaults)
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1253
            except ValueError:
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1254
                pass
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1255
            else:
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1256
                break
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1257
        else:
3806
92a3532a01d9 parsedate: use Abort rather than ValueError
Matt Mackall <mpm@selenic.com>
parents: 3784
diff changeset
  1258
            raise Abort(_('invalid date: %r ') % string)
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1259
    # validate explicit (probably user-specified) date and
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1260
    # time zone offset. values must fit in signed 32 bits for
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1261
    # current 32-bit linux runtimes. timezones go from UTC-12
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1262
    # to UTC+14
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1263
    if abs(when) > 0x7fffffff:
3806
92a3532a01d9 parsedate: use Abort rather than ValueError
Matt Mackall <mpm@selenic.com>
parents: 3784
diff changeset
  1264
        raise Abort(_('date exceeds 32 bits: %d') % when)
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1265
    if offset < -50400 or offset > 43200:
3806
92a3532a01d9 parsedate: use Abort rather than ValueError
Matt Mackall <mpm@selenic.com>
parents: 3784
diff changeset
  1266
        raise Abort(_('impossible time zone offset: %d') % offset)
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1267
    return when, offset
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1268
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1269
def matchdate(date):
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1270
    """Return a function that matches a given date match specifier
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1271
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1272
    Formats include:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1273
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1274
    '{date}' match a given date to the accuracy provided
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1275
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1276
    '<{date}' on or before a given date
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1277
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1278
    '>{date}' on or after a given date
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1279
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1280
    """
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1281
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1282
    def lower(date):
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1283
        return parsedate(date, extendeddateformats)[0]
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1284
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1285
    def upper(date):
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1286
        d = dict(mb="12", HI="23", M="59", S="59")
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1287
        for days in "31 30 29".split():
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1288
            try:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1289
                d["d"] = days
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1290
                return parsedate(date, extendeddateformats, d)[0]
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1291
            except:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1292
                pass
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1293
        d["d"] = "28"
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1294
        return parsedate(date, extendeddateformats, d)[0]
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1295
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1296
    if date[0] == "<":
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1297
        when = upper(date[1:])
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1298
        return lambda x: x <= when
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1299
    elif date[0] == ">":
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1300
        when = lower(date[1:])
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1301
        return lambda x: x >= when
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1302
    elif date[0] == "-":
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1303
        try:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1304
            days = int(date[1:])
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1305
        except ValueError:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1306
            raise Abort(_("invalid day spec: %s") % date[1:])
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1307
        when = makedate()[0] - days * 3600 * 24
3813
fc5ba0ab7f45 Add --date support to log
Matt Mackall <mpm@selenic.com>
parents: 3812
diff changeset
  1308
        return lambda x: x >= when
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1309
    elif " to " in date:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1310
        a, b = date.split(" to ")
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1311
        start, stop = lower(a), upper(b)
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1312
        return lambda x: x >= start and x <= stop
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1313
    else:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1314
        start, stop = lower(date), upper(date)
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1315
        return lambda x: x >= start and x <= stop
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1316
1903
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1317
def shortuser(user):
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1318
    """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
  1319
    f = user.find('@')
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1320
    if f >= 0:
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1321
        user = user[:f]
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1322
    f = user.find('<')
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1323
    if f >= 0:
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1324
        user = user[f+1:]
3176
7492b33bdd9f shortuser should stop before the first space character.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3147
diff changeset
  1325
    f = user.find(' ')
7492b33bdd9f shortuser should stop before the first space character.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3147
diff changeset
  1326
    if f >= 0:
7492b33bdd9f shortuser should stop before the first space character.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3147
diff changeset
  1327
        user = user[:f]
3533
bb44489b901f shortname: truncate at '.' too
Matt Mackall <mpm@selenic.com>
parents: 3466
diff changeset
  1328
    f = user.find('.')
bb44489b901f shortname: truncate at '.' too
Matt Mackall <mpm@selenic.com>
parents: 3466
diff changeset
  1329
    if f >= 0:
bb44489b901f shortname: truncate at '.' too
Matt Mackall <mpm@selenic.com>
parents: 3466
diff changeset
  1330
        user = user[:f]
1903
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1331
    return user
1920
b7cc0f323a4c merge with crew.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1903 1882
diff changeset
  1332
3767
1861fa38a6a7 Move ellipsis code to util.ellipsis() and improve maxlength handling.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3721
diff changeset
  1333
def ellipsis(text, maxlength=400):
1861fa38a6a7 Move ellipsis code to util.ellipsis() and improve maxlength handling.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3721
diff changeset
  1334
    """Trim string to at most maxlength (default: 400) characters."""
1861fa38a6a7 Move ellipsis code to util.ellipsis() and improve maxlength handling.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3721
diff changeset
  1335
    if len(text) <= maxlength:
1861fa38a6a7 Move ellipsis code to util.ellipsis() and improve maxlength handling.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3721
diff changeset
  1336
        return text
1861fa38a6a7 Move ellipsis code to util.ellipsis() and improve maxlength handling.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3721
diff changeset
  1337
    else:
1861fa38a6a7 Move ellipsis code to util.ellipsis() and improve maxlength handling.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3721
diff changeset
  1338
        return "%s..." % (text[:maxlength-3])
1861fa38a6a7 Move ellipsis code to util.ellipsis() and improve maxlength handling.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3721
diff changeset
  1339
1829
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1340
def walkrepos(path):
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1341
    '''yield every hg repository under path, recursively.'''
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1342
    def errhandler(err):
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1343
        if err.filename == path:
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1344
            raise err
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1345
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1346
    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
  1347
        for d in dirs:
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1348
            if d == '.hg':
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1349
                yield root
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1350
                dirs[:] = []
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1351
                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
  1352
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
  1353
_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
  1354
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
  1355
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
  1356
    '''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
  1357
    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
  1358
    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
  1359
    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
  1360
    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
  1361
    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
  1362
    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
  1363
        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
  1364
            _rcpath = []
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
  1365
            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
  1366
                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
  1367
                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
  1368
                    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
  1369
                        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
  1370
                            _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
  1371
                else:
16750010813d use a proper test instead of catching every exception
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1951
diff changeset
  1372
                    _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
  1373
        else:
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
  1374
            _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
  1375
    return _rcpath
2612
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1376
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1377
def bytecount(nbytes):
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1378
    '''return byte count formatted as readable string, with units'''
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1379
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1380
    units = (
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1381
        (100, 1<<30, _('%.0f GB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1382
        (10, 1<<30, _('%.1f GB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1383
        (1, 1<<30, _('%.2f GB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1384
        (100, 1<<20, _('%.0f MB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1385
        (10, 1<<20, _('%.1f MB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1386
        (1, 1<<20, _('%.2f MB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1387
        (100, 1<<10, _('%.0f KB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1388
        (10, 1<<10, _('%.1f KB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1389
        (1, 1<<10, _('%.2f KB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1390
        (1, 1, _('%.0f bytes')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1391
        )
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1392
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1393
    for multiplier, divisor, format in units:
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1394
        if nbytes >= divisor * multiplier:
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1395
            return format % (nbytes / float(divisor))
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1396
    return units[-1][2] % nbytes
2740
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2655
diff changeset
  1397
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2655
diff changeset
  1398
def drop_scheme(scheme, path):
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2655
diff changeset
  1399
    sc = scheme + ':'
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2655
diff changeset
  1400
    if path.startswith(sc):
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2655
diff changeset
  1401
        path = path[len(sc):]
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2655
diff changeset
  1402
        if path.startswith('//'):
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2655
diff changeset
  1403
            path = path[2:]
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2655
diff changeset
  1404
    return path