mercurial/util.py
author Matt Mackall <mpm@selenic.com>
Fri, 03 Apr 2009 14:51:48 -0500
changeset 7948 de377b1a9a84
parent 7947 a454eeb1b827
child 7953 8c6f823efcc9
permissions -rw-r--r--
move encoding bits from util to encoding In addition to cleaning up util, this gets rid of some circular dependencies.
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>
4635
63b9d2deed48 Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4625
diff changeset
     5
 Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
2859
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 _
7890
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
    16
import cStringIO, errno, re, shutil, sys, tempfile, traceback, error
7948
de377b1a9a84 move encoding bits from util to encoding
Matt Mackall <mpm@selenic.com>
parents: 7947
diff changeset
    17
import os, stat, threading, time, calendar, ConfigParser, glob, osutil
de377b1a9a84 move encoding bits from util to encoding
Matt Mackall <mpm@selenic.com>
parents: 7947
diff changeset
    18
import imp
3769
96095d9ff1f8 Add encoding detection
Matt Mackall <mpm@selenic.com>
parents: 3767
diff changeset
    19
6470
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    20
# Python compatibility
3769
96095d9ff1f8 Add encoding detection
Matt Mackall <mpm@selenic.com>
parents: 3767
diff changeset
    21
4057
3600b84656d3 Fallback to ascii if getpreferredencoding raises an exception
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4055
diff changeset
    22
try:
4647
7c80e3e6f030 Provide a version independent way to use the set datatype.
Eric Hopper <hopper@omnifarious.org>
parents: 4635
diff changeset
    23
    set = set
7c80e3e6f030 Provide a version independent way to use the set datatype.
Eric Hopper <hopper@omnifarious.org>
parents: 4635
diff changeset
    24
    frozenset = frozenset
7c80e3e6f030 Provide a version independent way to use the set datatype.
Eric Hopper <hopper@omnifarious.org>
parents: 4635
diff changeset
    25
except NameError:
7c80e3e6f030 Provide a version independent way to use the set datatype.
Eric Hopper <hopper@omnifarious.org>
parents: 4635
diff changeset
    26
    from sets import Set as set, ImmutableSet as frozenset
7c80e3e6f030 Provide a version independent way to use the set datatype.
Eric Hopper <hopper@omnifarious.org>
parents: 4635
diff changeset
    27
6470
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    28
_md5 = None
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    29
def md5(s):
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    30
    global _md5
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    31
    if _md5 is None:
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    32
        try:
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    33
            import hashlib
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    34
            _md5 = hashlib.md5
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    35
        except ImportError:
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    36
            import md5
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    37
            _md5 = md5.md5
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    38
    return _md5(s)
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    39
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    40
_sha1 = None
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    41
def sha1(s):
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    42
    global _sha1
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    43
    if _sha1 is None:
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    44
        try:
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    45
            import hashlib
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    46
            _sha1 = hashlib.sha1
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    47
        except ImportError:
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    48
            import sha
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    49
            _sha1 = sha.sha
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    50
    return _sha1(s)
ac0bcd951c2c python 2.6 compatibility: compatibility wrappers for hash functions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6339
diff changeset
    51
4647
7c80e3e6f030 Provide a version independent way to use the set datatype.
Eric Hopper <hopper@omnifarious.org>
parents: 4635
diff changeset
    52
try:
7106
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    53
    import subprocess
7163
1be530a3180e Fix util.popen2 for Python 2.3
Thomas Arendsen Hein <thomas@intevation.de>
parents: 7137
diff changeset
    54
    subprocess.Popen  # trigger ImportError early
7123
716277f5867e util: subprocess close_fds option is unix only
Patrick Mezard <pmezard@gmail.com>
parents: 7118
diff changeset
    55
    closefds = os.name == 'posix'
7106
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    56
    def popen2(cmd, mode='t', bufsize=-1):
7123
716277f5867e util: subprocess close_fds option is unix only
Patrick Mezard <pmezard@gmail.com>
parents: 7118
diff changeset
    57
        p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
716277f5867e util: subprocess close_fds option is unix only
Patrick Mezard <pmezard@gmail.com>
parents: 7118
diff changeset
    58
                             close_fds=closefds,
7106
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    59
                             stdin=subprocess.PIPE, stdout=subprocess.PIPE)
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    60
        return p.stdin, p.stdout
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    61
    def popen3(cmd, mode='t', bufsize=-1):
7123
716277f5867e util: subprocess close_fds option is unix only
Patrick Mezard <pmezard@gmail.com>
parents: 7118
diff changeset
    62
        p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
716277f5867e util: subprocess close_fds option is unix only
Patrick Mezard <pmezard@gmail.com>
parents: 7118
diff changeset
    63
                             close_fds=closefds,
7106
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    64
                             stdin=subprocess.PIPE, stdout=subprocess.PIPE,
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    65
                             stderr=subprocess.PIPE)
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    66
        return p.stdin, p.stdout, p.stderr
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    67
    def Popen3(cmd, capturestderr=False, bufsize=-1):
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    68
        stderr = capturestderr and subprocess.PIPE or None
7123
716277f5867e util: subprocess close_fds option is unix only
Patrick Mezard <pmezard@gmail.com>
parents: 7118
diff changeset
    69
        p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
716277f5867e util: subprocess close_fds option is unix only
Patrick Mezard <pmezard@gmail.com>
parents: 7118
diff changeset
    70
                             close_fds=closefds,
7106
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    71
                             stdin=subprocess.PIPE, stdout=subprocess.PIPE,
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    72
                             stderr=stderr)
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    73
        p.fromchild = p.stdout
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    74
        p.tochild = p.stdin
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    75
        p.childerr = p.stderr
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    76
        return p
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    77
except ImportError:
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    78
    subprocess = None
7164
cae820101762 Add util.popen3 fallback, simplify import of Popen3
Thomas Arendsen Hein <thomas@intevation.de>
parents: 7163
diff changeset
    79
    from popen2 import Popen3
7163
1be530a3180e Fix util.popen2 for Python 2.3
Thomas Arendsen Hein <thomas@intevation.de>
parents: 7137
diff changeset
    80
    popen2 = os.popen2
7164
cae820101762 Add util.popen3 fallback, simplify import of Popen3
Thomas Arendsen Hein <thomas@intevation.de>
parents: 7163
diff changeset
    81
    popen3 = os.popen3
7106
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    82
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
    83
7632
9626819b2e3d refactor version code
Matt Mackall <mpm@selenic.com>
parents: 7559
diff changeset
    84
def version():
9626819b2e3d refactor version code
Matt Mackall <mpm@selenic.com>
parents: 7559
diff changeset
    85
    """Return version information if available."""
9626819b2e3d refactor version code
Matt Mackall <mpm@selenic.com>
parents: 7559
diff changeset
    86
    try:
9626819b2e3d refactor version code
Matt Mackall <mpm@selenic.com>
parents: 7559
diff changeset
    87
        import __version__
9626819b2e3d refactor version code
Matt Mackall <mpm@selenic.com>
parents: 7559
diff changeset
    88
        return __version__.version
9626819b2e3d refactor version code
Matt Mackall <mpm@selenic.com>
parents: 7559
diff changeset
    89
    except ImportError:
9626819b2e3d refactor version code
Matt Mackall <mpm@selenic.com>
parents: 7559
diff changeset
    90
        return 'unknown'
9626819b2e3d refactor version code
Matt Mackall <mpm@selenic.com>
parents: 7559
diff changeset
    91
2609
6c5b1b5cc160 util.parsedate should understand dates from hg export
Chris Mason <mason@suse.com>
parents: 2601
diff changeset
    92
# used by parsedate
3808
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    93
defaultdateformats = (
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    94
    '%Y-%m-%d %H:%M:%S',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    95
    '%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
    96
    '%Y-%m-%d %H:%M',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    97
    '%Y-%m-%d %I:%M%p',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    98
    '%Y-%m-%d',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
    99
    '%m-%d',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   100
    '%m/%d',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   101
    '%m/%d/%y',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   102
    '%m/%d/%Y',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   103
    '%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
   104
    '%a %b %d %I:%M:%S%p %Y',
4708
01f9ee4de1ad Add support for RFC2822 to util.parsedate().
Markus F.X.J. Oberhumer <markus@oberhumer.com>
parents: 4686
diff changeset
   105
    '%a, %d %b %Y %H:%M:%S',        #  GNU coreutils "/bin/date --rfc-2822"
3808
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   106
    '%b %d %H:%M:%S %Y',
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
   107
    '%b %d %I:%M:%S%p %Y',
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
   108
    '%b %d %H:%M:%S',
3808
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   109
    '%b %d %I:%M:%S%p',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   110
    '%b %d %H:%M',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   111
    '%b %d %I:%M%p',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   112
    '%b %d %Y',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   113
    '%b %d',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   114
    '%H:%M:%S',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   115
    '%I:%M:%SP',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   116
    '%H:%M',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   117
    '%I:%M%p',
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
   118
)
2609
6c5b1b5cc160 util.parsedate should understand dates from hg export
Chris Mason <mason@suse.com>
parents: 2601
diff changeset
   119
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
   120
extendeddateformats = defaultdateformats + (
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
   121
    "%Y",
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
   122
    "%Y-%m",
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
   123
    "%b",
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
   124
    "%b %Y",
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
   125
    )
2609
6c5b1b5cc160 util.parsedate should understand dates from hg export
Chris Mason <mason@suse.com>
parents: 2601
diff changeset
   126
4069
3fef134832d8 allow values that aren't strings in util.configparser
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4068
diff changeset
   127
# differences from SafeConfigParser:
3fef134832d8 allow values that aren't strings in util.configparser
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4068
diff changeset
   128
# - case-sensitive keys
3fef134832d8 allow values that aren't strings in util.configparser
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4068
diff changeset
   129
# - allows values that are not strings (this means that you may not
3fef134832d8 allow values that aren't strings in util.configparser
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4068
diff changeset
   130
#   be able to save the configuration to a file)
3425
ec6f400cff4d Use a case-sensitive version of SafeConfigParser everywhere
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3257
diff changeset
   131
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
   132
    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
   133
        return optionstr
ec6f400cff4d Use a case-sensitive version of SafeConfigParser everywhere
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3257
diff changeset
   134
4069
3fef134832d8 allow values that aren't strings in util.configparser
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4068
diff changeset
   135
    def set(self, section, option, value):
3fef134832d8 allow values that aren't strings in util.configparser
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4068
diff changeset
   136
        return ConfigParser.ConfigParser.set(self, section, option, value)
3fef134832d8 allow values that aren't strings in util.configparser
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4068
diff changeset
   137
3fef134832d8 allow values that aren't strings in util.configparser
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4068
diff changeset
   138
    def _interpolate(self, section, option, rawval, vars):
3fef134832d8 allow values that aren't strings in util.configparser
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4068
diff changeset
   139
        if not isinstance(rawval, basestring):
3fef134832d8 allow values that aren't strings in util.configparser
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4068
diff changeset
   140
            return rawval
3fef134832d8 allow values that aren't strings in util.configparser
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4068
diff changeset
   141
        return ConfigParser.SafeConfigParser._interpolate(self, section,
3fef134832d8 allow values that aren't strings in util.configparser
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4068
diff changeset
   142
                                                          option, rawval, vars)
3fef134832d8 allow values that aren't strings in util.configparser
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4068
diff changeset
   143
3145
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   144
def cachefunc(func):
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   145
    '''cache the result of function calls'''
3147
97420a49188d add comments in cachefunc
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3145
diff changeset
   146
    # XXX doesn't handle keywords args
3145
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   147
    cache = {}
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   148
    if func.func_code.co_argcount == 1:
3147
97420a49188d add comments in cachefunc
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3145
diff changeset
   149
        # we gain a small amount of time because
97420a49188d add comments in cachefunc
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3145
diff changeset
   150
        # 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
   151
        def f(arg):
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   152
            if arg not in cache:
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   153
                cache[arg] = func(arg)
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   154
            return cache[arg]
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   155
    else:
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   156
        def f(*args):
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   157
            if args not in cache:
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   158
                cache[args] = func(*args)
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   159
            return cache[args]
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   160
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   161
    return f
e4ea47c21480 Add cachefunc to abstract function call cache
Brendan Cully <brendan@kublai.com>
parents: 3131
diff changeset
   162
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   163
def pipefilter(s, cmd):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   164
    '''filter string S through command CMD, returning its output'''
7106
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
   165
    (pin, pout) = popen2(cmd, 'b')
1258
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   166
    def writer():
2096
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
   167
        try:
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
   168
            pin.write(s)
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
   169
            pin.close()
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
   170
        except IOError, inst:
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
   171
            if inst.errno != errno.EPIPE:
f5ebe964c6be Ignore EPIPE in pipefilter
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 2090
diff changeset
   172
                raise
1258
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   173
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   174
    # 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
   175
    # systems, including Windows
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   176
    w = threading.Thread(target=writer)
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   177
    w.start()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   178
    f = pout.read()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   179
    pout.close()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   180
    w.join()
1945754e466b Add file encoding/decoding support
mpm@selenic.com
parents: 1241
diff changeset
   181
    return f
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
   182
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   183
def tempfilter(s, cmd):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   184
    '''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
   185
    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
   186
    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
   187
    the temporary files generated.'''
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   188
    inname, outname = None, None
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   189
    try:
2165
d821918e3bee Use better names (hg-{usage}-{random}.{suffix}) for temporary files.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2153
diff changeset
   190
        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
   191
        fp = os.fdopen(infd, 'wb')
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   192
        fp.write(s)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   193
        fp.close()
2165
d821918e3bee Use better names (hg-{usage}-{random}.{suffix}) for temporary files.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2153
diff changeset
   194
        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
   195
        os.close(outfd)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   196
        cmd = cmd.replace('INFILE', inname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   197
        cmd = cmd.replace('OUTFILE', outname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   198
        code = os.system(cmd)
4720
72fb6f10fac1 OpenVMS patches
Jean-Francois PIERONNE <jf.pieronne@laposte.net>
parents: 4708
diff changeset
   199
        if sys.platform == 'OpenVMS' and code & 1:
72fb6f10fac1 OpenVMS patches
Jean-Francois PIERONNE <jf.pieronne@laposte.net>
parents: 4708
diff changeset
   200
            code = 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
   201
        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
   202
                             (cmd, explain_exit(code)))
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   203
        return open(outname, 'rb').read()
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   204
    finally:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   205
        try:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   206
            if inname: os.unlink(inname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   207
        except: pass
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   208
        try:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   209
            if outname: os.unlink(outname)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   210
        except: pass
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   211
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   212
filtertable = {
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   213
    'tempfile:': tempfilter,
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   214
    'pipe:': pipefilter,
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   215
    }
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   216
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   217
def filter(s, cmd):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   218
    "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
   219
    for name, fn in filtertable.iteritems():
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   220
        if cmd.startswith(name):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   221
            return fn(s, cmd[len(name):].lstrip())
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   222
    return pipefilter(s, cmd)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
   223
1015
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
   224
def binary(s):
6507
9699864de219 Let util.binary check entire data for \0 (issue1066, issue1079)
Christian Ebert <blacktrash@gmx.net>
parents: 6501
diff changeset
   225
    """return true if a string is binary data"""
9699864de219 Let util.binary check entire data for \0 (issue1066, issue1079)
Christian Ebert <blacktrash@gmx.net>
parents: 6501
diff changeset
   226
    if s and '\0' in s:
1015
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
   227
        return True
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
   228
    return False
22571b8d35d3 Add automatic binary file detection to diff and export
mpm@selenic.com
parents: 917
diff changeset
   229
556
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   230
def unique(g):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   231
    """return the uniq elements of iterable g"""
5881
4bb64294e5b4 util: simplify unique
Matt Mackall <mpm@selenic.com>
parents: 5668
diff changeset
   232
    return dict.fromkeys(g).keys()
556
f6c6fa15ff70 Move dirstate.uniq to util.unique
mpm@selenic.com
parents: 521
diff changeset
   233
6762
f67d1468ac50 util: add sort helper
Matt Mackall <mpm@selenic.com>
parents: 6746
diff changeset
   234
def sort(l):
f67d1468ac50 util: add sort helper
Matt Mackall <mpm@selenic.com>
parents: 6746
diff changeset
   235
    if not isinstance(l, list):
f67d1468ac50 util: add sort helper
Matt Mackall <mpm@selenic.com>
parents: 6746
diff changeset
   236
        l = list(l)
f67d1468ac50 util: add sort helper
Matt Mackall <mpm@selenic.com>
parents: 6746
diff changeset
   237
    l.sort()
f67d1468ac50 util: add sort helper
Matt Mackall <mpm@selenic.com>
parents: 6746
diff changeset
   238
    return l
f67d1468ac50 util: add sort helper
Matt Mackall <mpm@selenic.com>
parents: 6746
diff changeset
   239
7396
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   240
def increasingchunks(source, min=1024, max=65536):
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   241
    '''return no less than min bytes per chunk while data remains,
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   242
    doubling min after each chunk until it reaches max'''
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   243
    def log2(x):
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   244
        if not x:
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   245
            return 0
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   246
        i = 0
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   247
        while x:
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   248
            x >>= 1
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   249
            i += 1
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   250
        return i - 1
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   251
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   252
    buf = []
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   253
    blen = 0
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   254
    for chunk in source:
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   255
        buf.append(chunk)
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   256
        blen += len(chunk)
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   257
        if blen >= min:
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   258
            if min < max:
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   259
                min = min << 1
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   260
                nmin = 1 << log2(blen)
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   261
                if nmin > min:
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   262
                    min = nmin
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   263
                if min > max:
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   264
                    min = max
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   265
            yield ''.join(buf)
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   266
            blen = 0
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   267
            buf = []
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   268
    if buf:
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   269
        yield ''.join(buf)
526c40a74bd0 templater: return data in increasing chunk sizes
Brendan Cully <brendan@kublai.com>
parents: 7301
diff changeset
   270
7947
a454eeb1b827 move util.Abort to error.py
Matt Mackall <mpm@selenic.com>
parents: 7913
diff changeset
   271
Abort = error.Abort
508
42a660abaf75 [PATCH] Harden os.system
mpm@selenic.com
parents: 464
diff changeset
   272
724
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   273
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
   274
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
   275
6595
99a92acafdb9 remove default arg from patkind
Matt Mackall <mpm@selenic.com>
parents: 6575
diff changeset
   276
def patkind(name, default):
1563
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   277
    """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
   278
    actual pattern."""
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   279
    for prefix in 're', 'glob', 'path', 'relglob', 'relpath', 'relre':
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   280
        if name.startswith(prefix + ':'): return name.split(':', 1)
6595
99a92acafdb9 remove default arg from patkind
Matt Mackall <mpm@selenic.com>
parents: 6575
diff changeset
   281
    return default, name
1563
cc2a2e12f4ad export patkind() from util
Robin Farine <robin.farine@terminus.org>
parents: 1546
diff changeset
   282
1062
6d5a62a549fa pep-0008 cleanup
benoit.boissinot@ens-lyon.fr
parents: 1031
diff changeset
   283
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
   284
    "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
   285
    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
   286
    res = ''
5949
48d01b1e315f Permit glob patterns to use nested curly braces.
Jesse Glick <jesse.glick@sun.com>
parents: 5921
diff changeset
   287
    group = 0
724
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   288
    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
   289
    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
   290
        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
   291
        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
   292
        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
   293
            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
   294
                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
   295
                res += '.*'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   296
            else:
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 == '?':
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
        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
   301
            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
   302
            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
   303
                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
   304
            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
   305
                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
   306
            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
   307
                res += '\\['
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   308
            else:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   309
                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
   310
                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
   311
                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
   312
                    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
   313
                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
   314
                    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
   315
                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
   316
        elif c == '{':
5949
48d01b1e315f Permit glob patterns to use nested curly braces.
Jesse Glick <jesse.glick@sun.com>
parents: 5921
diff changeset
   317
            group += 1
724
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   318
            res += '(?:'
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   319
        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
   320
            res += ')'
5949
48d01b1e315f Permit glob patterns to use nested curly braces.
Jesse Glick <jesse.glick@sun.com>
parents: 5921
diff changeset
   321
            group -= 1
724
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   322
        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
   323
            res += '|'
1990
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   324
        elif c == '\\':
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   325
            p = peek()
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   326
            if p:
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   327
                i += 1
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   328
                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
   329
            else:
4b0535c678d6 make it possible to escape characters in a glob expression
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1976
diff changeset
   330
                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
   331
        else:
1c0c413cccdd Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 705
diff changeset
   332
            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
   333
    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
   334
812
b65af904d6d7 Reduce the amount of stat traffic generated by a walk.
Bryan O'Sullivan <bos@serpentine.com>
parents: 782
diff changeset
   335
_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
   336
4229
24c22a3f2ef8 pass repo.root to util.pathto() in preparation for the next patch
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4129
diff changeset
   337
def pathto(root, n1, n2):
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   338
    '''return the relative path from one place to another.
4229
24c22a3f2ef8 pass repo.root to util.pathto() in preparation for the next patch
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4129
diff changeset
   339
    root should use os.sep to separate directories
3669
48768b1ab23c fix util.pathto
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3629
diff changeset
   340
    n1 should use os.sep to separate directories
48768b1ab23c fix util.pathto
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3629
diff changeset
   341
    n2 should use "/" to separate directories
48768b1ab23c fix util.pathto
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3629
diff changeset
   342
    returns an os.sep-separated path.
4229
24c22a3f2ef8 pass repo.root to util.pathto() in preparation for the next patch
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4129
diff changeset
   343
24c22a3f2ef8 pass repo.root to util.pathto() in preparation for the next patch
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4129
diff changeset
   344
    If n1 is a relative path, it's assumed it's
24c22a3f2ef8 pass repo.root to util.pathto() in preparation for the next patch
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4129
diff changeset
   345
    relative to root.
24c22a3f2ef8 pass repo.root to util.pathto() in preparation for the next patch
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4129
diff changeset
   346
    n2 should always be relative to root.
3669
48768b1ab23c fix util.pathto
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3629
diff changeset
   347
    '''
886
509de8ab6f31 Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents: 884
diff changeset
   348
    if not n1: return localpath(n2)
4230
c93562fb12cc Fix handling of paths when run outside the repo.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4229
diff changeset
   349
    if os.path.isabs(n1):
c93562fb12cc Fix handling of paths when run outside the repo.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4229
diff changeset
   350
        if os.path.splitdrive(root)[0] != os.path.splitdrive(n1)[0]:
c93562fb12cc Fix handling of paths when run outside the repo.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4229
diff changeset
   351
            return os.path.join(root, localpath(n2))
c93562fb12cc Fix handling of paths when run outside the repo.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4229
diff changeset
   352
        n2 = '/'.join((pconvert(root), n2))
5844
07d8eb78dd68 Add util.splitpath() and use it instead of using os.sep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5843
diff changeset
   353
    a, b = splitpath(n1), n2.split('/')
1541
bf4e7ef08741 fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
twaldmann@thinkmo.de
parents: 1528
diff changeset
   354
    a.reverse()
bf4e7ef08741 fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
twaldmann@thinkmo.de
parents: 1528
diff changeset
   355
    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
   356
    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
   357
        a.pop()
bf4e7ef08741 fixed some stuff pychecker shows, marked unclear/wrong stuff with XXX
twaldmann@thinkmo.de
parents: 1528
diff changeset
   358
        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
   359
    b.reverse()
6111
213ea6eed412 util.pathto: return '.' instead of an empty string
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6091
diff changeset
   360
    return os.sep.join((['..'] * len(a)) + b) or '.'
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
   361
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   362
def canonpath(root, cwd, myname):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   363
    """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
   364
    if root == os.sep:
8befbb4e30b2 Handle hg under /
Arun Sharma <arun@sharma-home.net>
parents: 1563
diff changeset
   365
        rootsep = os.sep
5843
83c354c4d529 Add endswithsep() and use it instead of using os.sep and os.altsep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5802
diff changeset
   366
    elif endswithsep(root):
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
   367
        rootsep = root
1566
8befbb4e30b2 Handle hg under /
Arun Sharma <arun@sharma-home.net>
parents: 1563
diff changeset
   368
    else:
1810
7596611ab3d5 Whitespace, tab and formatting cleanups, mainly in mq.py
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1635
diff changeset
   369
        rootsep = root + os.sep
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   370
    name = myname
2090
eb40db373717 fix util.canonpath on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2085
diff changeset
   371
    if not os.path.isabs(name):
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   372
        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
   373
    name = os.path.normpath(name)
5158
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   374
    audit_path = path_auditor(root)
2278
3711e23ab10a Make hg status work for repositories in root directory on windows (issue 228)
Manpreet Singh <junkblocker@yahoo.com>
parents: 2271
diff changeset
   375
    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
   376
        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
   377
        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
   378
        return pconvert(name)
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   379
    elif name == root:
870
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   380
        return ''
a82eae840447 Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 869
diff changeset
   381
    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
   382
        # 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
   383
        # 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
   384
        # 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
   385
        # `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
   386
        # 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
   387
        # 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
   388
        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
   389
        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
   390
        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
   391
            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
   392
                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
   393
            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
   394
                break
2193
fb28ce04b349 add util.samestat function for windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2177
diff changeset
   395
            if samestat(name_st, root_st):
4086
cc8a52229620 Fix accessing the repo through a symlink.
Jun Inoue <jun.lambda@gmail.com>
parents: 4067
diff changeset
   396
                if not rel:
cc8a52229620 Fix accessing the repo through a symlink.
Jun Inoue <jun.lambda@gmail.com>
parents: 4067
diff changeset
   397
                    # name was actually the same as root (maybe a symlink)
cc8a52229620 Fix accessing the repo through a symlink.
Jun Inoue <jun.lambda@gmail.com>
parents: 4067
diff changeset
   398
                    return ''
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
   399
                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
   400
                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
   401
                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
   402
                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
   403
            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
   404
            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
   405
            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
   406
                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
   407
            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
   408
1081
8b7d63489db3 Change canonpath to not know about repo objects
mpm@selenic.com
parents: 1075
diff changeset
   409
        raise Abort('%s not under root' % myname)
897
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   410
6575
e08e0367ba15 walk: kill util.cmdmatcher and _matcher
Matt Mackall <mpm@selenic.com>
parents: 6548
diff changeset
   411
def matcher(canonroot, cwd='', names=[], inc=[], exc=[], src=None, dflt_pat='glob'):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   412
    """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
   413
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   414
    arguments:
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   415
    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
   416
    cwd - the current working directory, if relevant
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   417
    names - patterns to find
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   418
    inc - patterns to include
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   419
    exc - patterns to exclude
4185
51ee2868a571 util._matcher: update comments
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4183
diff changeset
   420
    dflt_pat - if a pattern in names has no explicit type, assume this one
51ee2868a571 util._matcher: update comments
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4183
diff changeset
   421
    src - where these patterns came from (e.g. .hgignore)
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   422
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   423
    a pattern is one of:
4185
51ee2868a571 util._matcher: update comments
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4183
diff changeset
   424
    'glob:<glob>' - a glob relative to cwd
51ee2868a571 util._matcher: update comments
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4183
diff changeset
   425
    're:<regexp>' - a regular expression
51ee2868a571 util._matcher: update comments
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4183
diff changeset
   426
    'path:<path>' - a path relative to canonroot
51ee2868a571 util._matcher: update comments
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4183
diff changeset
   427
    'relglob:<glob>' - an unrooted glob (*.c matches C files in all dirs)
51ee2868a571 util._matcher: update comments
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4183
diff changeset
   428
    'relpath:<path>' - a path relative to cwd
51ee2868a571 util._matcher: update comments
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4183
diff changeset
   429
    'relre:<regexp>' - a regexp that doesn't have to match the start of a name
51ee2868a571 util._matcher: update comments
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4183
diff changeset
   430
    '<something>' - one of the cases above, selected by the dflt_pat argument
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   431
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   432
    returns:
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   433
    a 3-tuple containing
4185
51ee2868a571 util._matcher: update comments
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4183
diff changeset
   434
    - list of roots (places where one should start a recursive walk of the fs);
51ee2868a571 util._matcher: update comments
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4183
diff changeset
   435
      this often matches the explicit non-pattern names passed in, but also
51ee2868a571 util._matcher: update comments
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4183
diff changeset
   436
      includes the initial part of glob: patterns that has no glob characters
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   437
    - a bool match(filename) function
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   438
    - a bool indicating if any patterns were passed in
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   439
    """
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   440
4198
9e3121017fb2 Optimize return value of util._matcher for common command line case
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4197
diff changeset
   441
    # a common case: no patterns at all
9e3121017fb2 Optimize return value of util._matcher for common command line case
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4197
diff changeset
   442
    if not names and not inc and not exc:
9e3121017fb2 Optimize return value of util._matcher for common command line case
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4197
diff changeset
   443
        return [], always, False
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   444
1413
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   445
    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
   446
        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
   447
            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
   448
        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
   449
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   450
    def regex(kind, name, tail):
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   451
        '''convert a pattern into a regular expression'''
4190
769bc4af561d util.*matcher: change default "names" argument
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4189
diff changeset
   452
        if not name:
769bc4af561d util.*matcher: change default "names" argument
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4189
diff changeset
   453
            return ''
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   454
        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
   455
            return name
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   456
        elif kind == 'path':
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   457
            return '^' + re.escape(name) + '(?:/|$)'
1270
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   458
        elif kind == 'relglob':
4307
702f48570eb3 change relglob: patterns to be consistent with glob: patterns
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4306
diff changeset
   459
            return globre(name, '(?:|.*/)', tail)
888
e7a943e8c52b Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents: 886
diff changeset
   460
        elif kind == 'relpath':
4197
492d0d5b6976 remove unused "head" hack from util._matcher
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4195
diff changeset
   461
            return re.escape(name) + '(?:/|$)'
1270
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   462
        elif kind == 'relre':
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   463
            if name.startswith('^'):
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   464
                return name
fc3b41570082 Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1258
diff changeset
   465
            return '.*' + name
4306
6cecaec07cc9 Revert changeset ef1f1a4b2efb; add another test for glob: patterns
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4255
diff changeset
   466
        return globre(name, '', tail)
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   467
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   468
    def matchfn(pats, tail):
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   469
        """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
   470
        if not pats:
f4250806dbeb further fix traceback on invalid .hgignore patterns
Benoit Boissinot <mercurial-bugs@selenic.com>
parents: 1446
diff changeset
   471
            return
4371
d7ad1e42a368 util._matcher: speed up regexp matching.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4338
diff changeset
   472
        try:
d7ad1e42a368 util._matcher: speed up regexp matching.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4338
diff changeset
   473
            pat = '(?:%s)' % '|'.join([regex(k, p, tail) for (k, p) in pats])
6074
59a9dc9562e2 ignore: split up huge patterns
Matt Mackall <mpm@selenic.com>
parents: 6062
diff changeset
   474
            if len(pat) > 20000:
59a9dc9562e2 ignore: split up huge patterns
Matt Mackall <mpm@selenic.com>
parents: 6062
diff changeset
   475
                raise OverflowError()
4371
d7ad1e42a368 util._matcher: speed up regexp matching.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4338
diff changeset
   476
            return re.compile(pat).match
5201
0f6a1bdf89fb match: handle large regexes
Matt Mackall <mpm@selenic.com>
parents: 5077
diff changeset
   477
        except OverflowError:
0f6a1bdf89fb match: handle large regexes
Matt Mackall <mpm@selenic.com>
parents: 5077
diff changeset
   478
            # We're using a Python with a tiny regex engine and we
0f6a1bdf89fb match: handle large regexes
Matt Mackall <mpm@selenic.com>
parents: 5077
diff changeset
   479
            # made it explode, so we'll divide the pattern list in two
0f6a1bdf89fb match: handle large regexes
Matt Mackall <mpm@selenic.com>
parents: 5077
diff changeset
   480
            # until it works
0f6a1bdf89fb match: handle large regexes
Matt Mackall <mpm@selenic.com>
parents: 5077
diff changeset
   481
            l = len(pats)
0f6a1bdf89fb match: handle large regexes
Matt Mackall <mpm@selenic.com>
parents: 5077
diff changeset
   482
            if l < 2:
0f6a1bdf89fb match: handle large regexes
Matt Mackall <mpm@selenic.com>
parents: 5077
diff changeset
   483
                raise
5454
f2ca8d2c988f explicitely use integer division
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 5450
diff changeset
   484
            a, b = matchfn(pats[:l//2], tail), matchfn(pats[l//2:], tail)
5201
0f6a1bdf89fb match: handle large regexes
Matt Mackall <mpm@selenic.com>
parents: 5077
diff changeset
   485
            return lambda s: a(s) or b(s)
4371
d7ad1e42a368 util._matcher: speed up regexp matching.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4338
diff changeset
   486
        except re.error:
d7ad1e42a368 util._matcher: speed up regexp matching.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4338
diff changeset
   487
            for k, p in pats:
d7ad1e42a368 util._matcher: speed up regexp matching.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4338
diff changeset
   488
                try:
d7ad1e42a368 util._matcher: speed up regexp matching.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4338
diff changeset
   489
                    re.compile('(?:%s)' % regex(k, p, tail))
d7ad1e42a368 util._matcher: speed up regexp matching.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4338
diff changeset
   490
                except re.error:
d7ad1e42a368 util._matcher: speed up regexp matching.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4338
diff changeset
   491
                    if src:
d7ad1e42a368 util._matcher: speed up regexp matching.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4338
diff changeset
   492
                        raise Abort("%s: invalid pattern (%s): %s" %
d7ad1e42a368 util._matcher: speed up regexp matching.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4338
diff changeset
   493
                                    (src, k, p))
d7ad1e42a368 util._matcher: speed up regexp matching.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4338
diff changeset
   494
                    else:
d7ad1e42a368 util._matcher: speed up regexp matching.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4338
diff changeset
   495
                        raise Abort("invalid pattern (%s): %s" % (k, p))
d7ad1e42a368 util._matcher: speed up regexp matching.
Bryan O'Sullivan <bos@serpentine.com>
parents: 4338
diff changeset
   496
            raise Abort("invalid pattern")
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   497
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   498
    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
   499
        '''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
   500
        root = []
4183
6f9474044736 small globprefix fix
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4129
diff changeset
   501
        for p in pat.split('/'):
1413
1c64c628d15f Do not use 'glob' expansion by default on OS != 'nt'
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1402
diff changeset
   502
            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
   503
            root.append(p)
4187
01c4ea5e788c A 'glob:foo?bar' pattern determines a root - the tree root
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4185
diff changeset
   504
        return '/'.join(root) or '.'
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   505
4192
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   506
    def normalizepats(names, default):
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   507
        pats = []
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   508
        roots = []
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   509
        anypats = False
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   510
        for kind, name in [patkind(p, default) for p in names]:
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   511
            if kind in ('glob', 'relpath'):
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   512
                name = canonpath(canonroot, cwd, name)
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   513
            elif kind in ('relglob', 'path'):
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   514
                name = normpath(name)
4236
34c4540c04c5 util._matcher: remove superfluous variable
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4233
diff changeset
   515
34c4540c04c5 util._matcher: remove superfluous variable
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4233
diff changeset
   516
            pats.append((kind, name))
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   517
4192
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   518
            if kind in ('glob', 're', 'relglob', 'relre'):
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   519
                anypats = True
4236
34c4540c04c5 util._matcher: remove superfluous variable
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4233
diff changeset
   520
4192
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   521
            if kind == 'glob':
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   522
                root = globprefix(name)
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   523
                roots.append(root)
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   524
            elif kind in ('relpath', 'path'):
4233
03a665f9f913 util._matcher: use "." as the root of empty {rel,}path patterns
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4199
diff changeset
   525
                roots.append(name or '.')
4192
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   526
            elif kind == 'relglob':
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   527
                roots.append('.')
4236
34c4540c04c5 util._matcher: remove superfluous variable
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4233
diff changeset
   528
        return roots, pats, anypats
4192
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   529
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   530
    roots, pats, anypats = normalizepats(names, dflt_pat)
897
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   531
820
89985a1b3427 Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents: 814
diff changeset
   532
    patmatch = matchfn(pats, '$') or always
897
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   533
    incmatch = always
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   534
    if inc:
4192
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   535
        dummy, inckinds, dummy = normalizepats(inc, 'glob')
2480
519a1011db91 fix -I/-X when relative paths used or in subdir
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2471
diff changeset
   536
        incmatch = matchfn(inckinds, '(?:/|$)')
7430
f0a3e87c810d util: use existing never() instead of custom lambda
Mads Kiilerich <mads@kiilerich.com>
parents: 7414
diff changeset
   537
    excmatch = never
897
fe30f5434b51 Fix bug with empty inc and exc
mpm@selenic.com
parents: 896
diff changeset
   538
    if exc:
4192
9814d600011e util._matcher: unify pattern normalization
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4190
diff changeset
   539
        dummy, exckinds, dummy = normalizepats(exc, 'glob')
2480
519a1011db91 fix -I/-X when relative paths used or in subdir
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2471
diff changeset
   540
        excmatch = matchfn(exckinds, '(?:/|$)')
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   541
4199
ec932167c3a7 Optimize return value of util._matcher for hgignore case
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4198
diff changeset
   542
    if not names and inc and not exc:
ec932167c3a7 Optimize return value of util._matcher for hgignore case
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4198
diff changeset
   543
        # common case: hgignore patterns
ec932167c3a7 Optimize return value of util._matcher for hgignore case
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4198
diff changeset
   544
        match = incmatch
ec932167c3a7 Optimize return value of util._matcher for hgignore case
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4198
diff changeset
   545
    else:
ec932167c3a7 Optimize return value of util._matcher for hgignore case
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4198
diff changeset
   546
        match = lambda fn: incmatch(fn) and not excmatch(fn) and patmatch(fn)
ec932167c3a7 Optimize return value of util._matcher for hgignore case
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4198
diff changeset
   547
ec932167c3a7 Optimize return value of util._matcher for hgignore case
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4198
diff changeset
   548
    return (roots, match, (inc or exc or anypats) and True)
742
092937de2ad7 Refactor matchpats and walk
mpm@selenic.com
parents: 740
diff changeset
   549
5062
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
   550
_hgexecutable = None
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
   551
6499
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
   552
def main_is_frozen():
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
   553
    """return True if we are a frozen executable.
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
   554
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
   555
    The code supports py2exe (most common, Windows only) and tools/freeze
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
   556
    (portable, not much used).
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
   557
    """
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
   558
    return (hasattr(sys, "frozen") or # new py2exe
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
   559
            hasattr(sys, "importers") or # old py2exe
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
   560
            imp.is_frozen("__main__")) # tools/freeze
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
   561
5062
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
   562
def hgexecutable():
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
   563
    """return location of the 'hg' executable.
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
   564
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
   565
    Defaults to $HG or 'hg' in the search path.
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
   566
    """
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
   567
    if _hgexecutable is None:
6500
a3175cd7dbec Tidy code, fix typo
Bryan O'Sullivan <bos@serpentine.com>
parents: 6499
diff changeset
   568
        hg = os.environ.get('HG')
a3175cd7dbec Tidy code, fix typo
Bryan O'Sullivan <bos@serpentine.com>
parents: 6499
diff changeset
   569
        if hg:
a3175cd7dbec Tidy code, fix typo
Bryan O'Sullivan <bos@serpentine.com>
parents: 6499
diff changeset
   570
            set_hgexecutable(hg)
6499
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
   571
        elif main_is_frozen():
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
   572
            set_hgexecutable(sys.executable)
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
   573
        else:
7732
3793802ea41b Make util.find_exe alway returns existing file, fixing issue1459
Mads Kiilerich <mads@kiilerich.com>
parents: 7696
diff changeset
   574
            set_hgexecutable(find_exe('hg') or 'hg')
5062
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
   575
    return _hgexecutable
4686
849f011dbf79 Remember path to 'hg' executable and pass to external tools and hooks as $HG.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4673
diff changeset
   576
849f011dbf79 Remember path to 'hg' executable and pass to external tools and hooks as $HG.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4673
diff changeset
   577
def set_hgexecutable(path):
5062
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
   578
    """set location of the 'hg' executable"""
4686
849f011dbf79 Remember path to 'hg' executable and pass to external tools and hooks as $HG.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4673
diff changeset
   579
    global _hgexecutable
5062
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
   580
    _hgexecutable = path
4686
849f011dbf79 Remember path to 'hg' executable and pass to external tools and hooks as $HG.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4673
diff changeset
   581
1882
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   582
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
   583
    '''enhanced shell command execution.
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   584
    run with environment maybe modified, maybe in different dir.
508
42a660abaf75 [PATCH] Harden os.system
mpm@selenic.com
parents: 464
diff changeset
   585
1882
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   586
    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
   587
    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
   588
    exception.'''
2601
00fc88b0b256 move most of tag code to localrepository class.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
   589
    def py2shell(val):
00fc88b0b256 move most of tag code to localrepository class.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
   590
        '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
   591
        if val in (None, False):
00fc88b0b256 move most of tag code to localrepository class.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
   592
            return '0'
00fc88b0b256 move most of tag code to localrepository class.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
   593
        if val == True:
00fc88b0b256 move most of tag code to localrepository class.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
   594
            return '1'
00fc88b0b256 move most of tag code to localrepository class.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
   595
        return str(val)
1880
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   596
    oldenv = {}
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   597
    for k in environ:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   598
        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
   599
    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
   600
        oldcwd = os.getcwd()
3905
a8c0365b2ace util.system: fix quoting on windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3860
diff changeset
   601
    origcmd = cmd
a8c0365b2ace util.system: fix quoting on windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3860
diff changeset
   602
    if os.name == 'nt':
a8c0365b2ace util.system: fix quoting on windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3860
diff changeset
   603
        cmd = '"%s"' % cmd
1880
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   604
    try:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   605
        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
   606
            os.environ[k] = py2shell(v)
5062
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
   607
        os.environ['HG'] = hgexecutable()
1880
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   608
        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
   609
            os.chdir(cwd)
1882
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   610
        rc = os.system(cmd)
4720
72fb6f10fac1 OpenVMS patches
Jean-Francois PIERONNE <jf.pieronne@laposte.net>
parents: 4708
diff changeset
   611
        if sys.platform == 'OpenVMS' and rc & 1:
72fb6f10fac1 OpenVMS patches
Jean-Francois PIERONNE <jf.pieronne@laposte.net>
parents: 4708
diff changeset
   612
            rc = 0
1882
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   613
        if rc and onerr:
3905
a8c0365b2ace util.system: fix quoting on windows
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3860
diff changeset
   614
            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
   615
                                explain_exit(rc)[0])
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   616
            if errprefix:
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   617
                errmsg = '%s: %s' % (errprefix, errmsg)
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   618
            try:
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   619
                onerr.warn(errmsg + '\n')
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   620
            except AttributeError:
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   621
                raise onerr(errmsg)
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
   622
        return rc
1880
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   623
    finally:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   624
        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
   625
            if v is None:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   626
                del os.environ[k]
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   627
            else:
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   628
                os.environ[k] = v
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   629
        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
   630
            os.chdir(oldcwd)
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
   631
7388
5751631246de dispatch: generalize signature checking for extension command wrapping
Matt Mackall <mpm@selenic.com>
parents: 7301
diff changeset
   632
def checksignature(func):
5751631246de dispatch: generalize signature checking for extension command wrapping
Matt Mackall <mpm@selenic.com>
parents: 7301
diff changeset
   633
    '''wrap a function with code to check for calling errors'''
5751631246de dispatch: generalize signature checking for extension command wrapping
Matt Mackall <mpm@selenic.com>
parents: 7301
diff changeset
   634
    def check(*args, **kwargs):
5751631246de dispatch: generalize signature checking for extension command wrapping
Matt Mackall <mpm@selenic.com>
parents: 7301
diff changeset
   635
        try:
5751631246de dispatch: generalize signature checking for extension command wrapping
Matt Mackall <mpm@selenic.com>
parents: 7301
diff changeset
   636
            return func(*args, **kwargs)
5751631246de dispatch: generalize signature checking for extension command wrapping
Matt Mackall <mpm@selenic.com>
parents: 7301
diff changeset
   637
        except TypeError:
5751631246de dispatch: generalize signature checking for extension command wrapping
Matt Mackall <mpm@selenic.com>
parents: 7301
diff changeset
   638
            if len(traceback.extract_tb(sys.exc_info()[2])) == 1:
7646
e62a456b8dc5 error: move SignatureError
Matt Mackall <mpm@selenic.com>
parents: 7644
diff changeset
   639
                raise error.SignatureError
7388
5751631246de dispatch: generalize signature checking for extension command wrapping
Matt Mackall <mpm@selenic.com>
parents: 7301
diff changeset
   640
            raise
5751631246de dispatch: generalize signature checking for extension command wrapping
Matt Mackall <mpm@selenic.com>
parents: 7301
diff changeset
   641
5751631246de dispatch: generalize signature checking for extension command wrapping
Matt Mackall <mpm@selenic.com>
parents: 7301
diff changeset
   642
    return check
5751631246de dispatch: generalize signature checking for extension command wrapping
Matt Mackall <mpm@selenic.com>
parents: 7301
diff changeset
   643
4281
384672d8080f add util.lexists
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4275
diff changeset
   644
# os.path.lexists is not available on python2.3
384672d8080f add util.lexists
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4275
diff changeset
   645
def lexists(filename):
384672d8080f add util.lexists
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4275
diff changeset
   646
    "test whether a file with this name exists. does not follow symlinks"
384672d8080f add util.lexists
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4275
diff changeset
   647
    try:
384672d8080f add util.lexists
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4275
diff changeset
   648
        os.lstat(filename)
384672d8080f add util.lexists
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4275
diff changeset
   649
    except:
384672d8080f add util.lexists
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4275
diff changeset
   650
        return False
384672d8080f add util.lexists
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4275
diff changeset
   651
    return True
384672d8080f add util.lexists
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4275
diff changeset
   652
421
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   653
def rename(src, dst):
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
   654
    """forcibly rename a file"""
421
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   655
    try:
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   656
        os.rename(src, dst)
4956
02b127749dc0 fix unused variables reported by pychecker
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 4948
diff changeset
   657
    except OSError, err: # FIXME: check err (EEXIST ?)
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   658
        # 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
   659
        # 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
   660
        # schedules it for delete but does not delete it. rename
7780
9892c4d94fb7 rename: simplify forced renaming
Matt Mackall <mpm@selenic.com>
parents: 7767
diff changeset
   661
        # happens immediately even for open files, so we rename
9892c4d94fb7 rename: simplify forced renaming
Matt Mackall <mpm@selenic.com>
parents: 7767
diff changeset
   662
        # destination to a temporary name, then delete that. then
9892c4d94fb7 rename: simplify forced renaming
Matt Mackall <mpm@selenic.com>
parents: 7767
diff changeset
   663
        # rename is safe to do.
9892c4d94fb7 rename: simplify forced renaming
Matt Mackall <mpm@selenic.com>
parents: 7767
diff changeset
   664
        temp = dst + "-force-rename"
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   665
        os.rename(dst, temp)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   666
        os.unlink(temp)
421
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   667
        os.rename(src, dst)
43b8da7420a9 [PATCH] rename under the other OS
mpm@selenic.com
parents: 419
diff changeset
   668
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
   669
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
   670
    """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
   671
    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
   672
    # 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
   673
    try:
547ede0123a2 util.unlink should only catch OSError.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2054
diff changeset
   674
        os.removedirs(os.path.dirname(f))
547ede0123a2 util.unlink should only catch OSError.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2054
diff changeset
   675
    except OSError:
547ede0123a2 util.unlink should only catch OSError.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2054
diff changeset
   676
        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
   677
3629
4cfb72bcb978 util: add copyfile function
Matt Mackall <mpm@selenic.com>
parents: 3568
diff changeset
   678
def copyfile(src, dest):
7767
b2410ed2cbe9 Use shutil.copystat in copyfile().
Will Maier <willmaier@ml1.net>
parents: 7732
diff changeset
   679
    "copy a file, preserving mode and atime/mtime"
4271
1eaa8d90c689 fix util.copyfile to deal with symlinks
Eric St-Jean <esj@wwd.ca>
parents: 4256
diff changeset
   680
    if os.path.islink(src):
1eaa8d90c689 fix util.copyfile to deal with symlinks
Eric St-Jean <esj@wwd.ca>
parents: 4256
diff changeset
   681
        try:
1eaa8d90c689 fix util.copyfile to deal with symlinks
Eric St-Jean <esj@wwd.ca>
parents: 4256
diff changeset
   682
            os.unlink(dest)
1eaa8d90c689 fix util.copyfile to deal with symlinks
Eric St-Jean <esj@wwd.ca>
parents: 4256
diff changeset
   683
        except:
1eaa8d90c689 fix util.copyfile to deal with symlinks
Eric St-Jean <esj@wwd.ca>
parents: 4256
diff changeset
   684
            pass
1eaa8d90c689 fix util.copyfile to deal with symlinks
Eric St-Jean <esj@wwd.ca>
parents: 4256
diff changeset
   685
        os.symlink(os.readlink(src), dest)
1eaa8d90c689 fix util.copyfile to deal with symlinks
Eric St-Jean <esj@wwd.ca>
parents: 4256
diff changeset
   686
    else:
1eaa8d90c689 fix util.copyfile to deal with symlinks
Eric St-Jean <esj@wwd.ca>
parents: 4256
diff changeset
   687
        try:
1eaa8d90c689 fix util.copyfile to deal with symlinks
Eric St-Jean <esj@wwd.ca>
parents: 4256
diff changeset
   688
            shutil.copyfile(src, dest)
7767
b2410ed2cbe9 Use shutil.copystat in copyfile().
Will Maier <willmaier@ml1.net>
parents: 7732
diff changeset
   689
            shutil.copystat(src, dest)
4271
1eaa8d90c689 fix util.copyfile to deal with symlinks
Eric St-Jean <esj@wwd.ca>
parents: 4256
diff changeset
   690
        except shutil.Error, inst:
1eaa8d90c689 fix util.copyfile to deal with symlinks
Eric St-Jean <esj@wwd.ca>
parents: 4256
diff changeset
   691
            raise Abort(str(inst))
3629
4cfb72bcb978 util: add copyfile function
Matt Mackall <mpm@selenic.com>
parents: 3568
diff changeset
   692
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   693
def copyfiles(src, dst, hardlink=None):
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   694
    """Copy a directory tree using hardlinks if possible"""
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   695
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   696
    if hardlink is None:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   697
        hardlink = (os.stat(src).st_dev ==
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   698
                    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
   699
1207
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   700
    if os.path.isdir(src):
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   701
        os.mkdir(dst)
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5360
diff changeset
   702
        for name, kind in osutil.listdir(src):
1207
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   703
            srcname = os.path.join(src, name)
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   704
            dstname = os.path.join(dst, name)
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   705
            copyfiles(srcname, dstname, hardlink)
1207
a7b8812973d9 Rewrite copytree as copyfiles
mpm@selenic.com
parents: 1200
diff changeset
   706
    else:
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   707
        if hardlink:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   708
            try:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   709
                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
   710
            except (IOError, OSError):
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   711
                hardlink = False
1591
5a3229cf1492 do not copy atime and mtime in util.copyfiles
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1585
diff changeset
   712
                shutil.copy(src, dst)
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   713
        else:
1591
5a3229cf1492 do not copy atime and mtime in util.copyfiles
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1585
diff changeset
   714
            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
   715
5158
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   716
class path_auditor(object):
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   717
    '''ensure that a filesystem path contains no banned components.
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   718
    the following properties of a path are checked:
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   719
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   720
    - under top-level .hg
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   721
    - starts at the root of a windows drive
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   722
    - contains ".."
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   723
    - traverses a symlink (e.g. a/symlink_here/b)
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   724
    - inside a nested repository'''
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   725
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   726
    def __init__(self, root):
5200
c7e8fe11f34a path_auditor: cache names of audited directories
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5162
diff changeset
   727
        self.audited = set()
c7e8fe11f34a path_auditor: cache names of audited directories
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5162
diff changeset
   728
        self.auditeddir = set()
5158
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   729
        self.root = root
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   730
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   731
    def __call__(self, path):
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   732
        if path in self.audited:
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   733
            return
5159
d84329a11fdd Make a few portability improvements to path auditing code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5158
diff changeset
   734
        normpath = os.path.normcase(path)
5844
07d8eb78dd68 Add util.splitpath() and use it instead of using os.sep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5843
diff changeset
   735
        parts = splitpath(normpath)
7784
8a217626bb0c audit: check for casefolding of .hg (issue1450)
Matt Mackall <mpm@selenic.com>
parents: 7780
diff changeset
   736
        if (os.path.splitdrive(path)[0]
8a217626bb0c audit: check for casefolding of .hg (issue1450)
Matt Mackall <mpm@selenic.com>
parents: 7780
diff changeset
   737
            or parts[0].lower() in ('.hg', '.hg.', '')
5158
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   738
            or os.pardir in parts):
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   739
            raise Abort(_("path contains illegal component: %s") % path)
7784
8a217626bb0c audit: check for casefolding of .hg (issue1450)
Matt Mackall <mpm@selenic.com>
parents: 7780
diff changeset
   740
        if '.hg' in path.lower():
8a217626bb0c audit: check for casefolding of .hg (issue1450)
Matt Mackall <mpm@selenic.com>
parents: 7780
diff changeset
   741
            lparts = [p.lower() for p in parts]
7553
71be8688f2db audit: reject paths with .hg (issue 1450)
Matt Mackall <mpm@selenic.com>
parents: 7525
diff changeset
   742
            for p in '.hg', '.hg.':
7820
346fafc144fc audit: be even pickier (issue1450)
Matt Mackall <mpm@selenic.com>
parents: 7784
diff changeset
   743
                if p in lparts[1:]:
7784
8a217626bb0c audit: check for casefolding of .hg (issue1450)
Matt Mackall <mpm@selenic.com>
parents: 7780
diff changeset
   744
                    pos = lparts.index(p)
7553
71be8688f2db audit: reject paths with .hg (issue 1450)
Matt Mackall <mpm@selenic.com>
parents: 7525
diff changeset
   745
                    base = os.path.join(*parts[:pos])
71be8688f2db audit: reject paths with .hg (issue 1450)
Matt Mackall <mpm@selenic.com>
parents: 7525
diff changeset
   746
                    raise Abort(_('path %r is inside repo %r') % (path, base))
5158
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   747
        def check(prefix):
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   748
            curpath = os.path.join(self.root, prefix)
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   749
            try:
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   750
                st = os.lstat(curpath)
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   751
            except OSError, err:
5162
9374373fb727 util: ignore invalid path errors in path_auditor.
Patrick Mezard <pmezard@gmail.com>
parents: 5159
diff changeset
   752
                # EINVAL can be raised as invalid path syntax under win32.
9374373fb727 util: ignore invalid path errors in path_auditor.
Patrick Mezard <pmezard@gmail.com>
parents: 5159
diff changeset
   753
                # They must be ignored for patterns can be checked too.
5487
7a64931e2d76 Fix file-changed-to-dir and dir-to-file commits (issue660).
Maxim Dounin <mdounin@mdounin.ru>
parents: 5481
diff changeset
   754
                if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
5158
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   755
                    raise
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   756
            else:
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   757
                if stat.S_ISLNK(st.st_mode):
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   758
                    raise Abort(_('path %r traverses symbolic link %r') %
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   759
                                (path, prefix))
5159
d84329a11fdd Make a few portability improvements to path auditing code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5158
diff changeset
   760
                elif (stat.S_ISDIR(st.st_mode) and
d84329a11fdd Make a few portability improvements to path auditing code.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5158
diff changeset
   761
                      os.path.isdir(os.path.join(curpath, '.hg'))):
5158
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   762
                    raise Abort(_('path %r is inside repo %r') %
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
   763
                                (path, prefix))
5845
5924a11aa419 Fix not to use os.sep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5844
diff changeset
   764
        parts.pop()
5200
c7e8fe11f34a path_auditor: cache names of audited directories
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5162
diff changeset
   765
        prefixes = []
5845
5924a11aa419 Fix not to use os.sep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5844
diff changeset
   766
        for n in range(len(parts)):
5924a11aa419 Fix not to use os.sep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5844
diff changeset
   767
            prefix = os.sep.join(parts)
5200
c7e8fe11f34a path_auditor: cache names of audited directories
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5162
diff changeset
   768
            if prefix in self.auditeddir:
c7e8fe11f34a path_auditor: cache names of audited directories
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5162
diff changeset
   769
                break
c7e8fe11f34a path_auditor: cache names of audited directories
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5162
diff changeset
   770
            check(prefix)
c7e8fe11f34a path_auditor: cache names of audited directories
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5162
diff changeset
   771
            prefixes.append(prefix)
5845
5924a11aa419 Fix not to use os.sep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5844
diff changeset
   772
            parts.pop()
5200
c7e8fe11f34a path_auditor: cache names of audited directories
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5162
diff changeset
   773
c7e8fe11f34a path_auditor: cache names of audited directories
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5162
diff changeset
   774
        self.audited.add(path)
c7e8fe11f34a path_auditor: cache names of audited directories
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5162
diff changeset
   775
        # only add prefixes to the cache after checking everything: we don't
c7e8fe11f34a path_auditor: cache names of audited directories
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5162
diff changeset
   776
        # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
c7e8fe11f34a path_auditor: cache names of audited directories
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5162
diff changeset
   777
        self.auditeddir.update(prefixes)
1835
bdfb524d728a Validate paths before reading or writing files in repository or working dir.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1830
diff changeset
   778
7890
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   779
if os.name == 'nt':
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   780
    from windows import *
7913
1b1b3dd630a5 windows: hoist expand_glob() back into util.py
Steve Borho <steve@borho.org>
parents: 7890
diff changeset
   781
    def expand_glob(pats):
1b1b3dd630a5 windows: hoist expand_glob() back into util.py
Steve Borho <steve@borho.org>
parents: 7890
diff changeset
   782
        '''On Windows, expand the implicit globs in a list of patterns'''
1b1b3dd630a5 windows: hoist expand_glob() back into util.py
Steve Borho <steve@borho.org>
parents: 7890
diff changeset
   783
        ret = []
1b1b3dd630a5 windows: hoist expand_glob() back into util.py
Steve Borho <steve@borho.org>
parents: 7890
diff changeset
   784
        for p in pats:
1b1b3dd630a5 windows: hoist expand_glob() back into util.py
Steve Borho <steve@borho.org>
parents: 7890
diff changeset
   785
            kind, name = patkind(p, None)
1b1b3dd630a5 windows: hoist expand_glob() back into util.py
Steve Borho <steve@borho.org>
parents: 7890
diff changeset
   786
            if kind is None:
1b1b3dd630a5 windows: hoist expand_glob() back into util.py
Steve Borho <steve@borho.org>
parents: 7890
diff changeset
   787
                globbed = glob.glob(name)
1b1b3dd630a5 windows: hoist expand_glob() back into util.py
Steve Borho <steve@borho.org>
parents: 7890
diff changeset
   788
                if globbed:
1b1b3dd630a5 windows: hoist expand_glob() back into util.py
Steve Borho <steve@borho.org>
parents: 7890
diff changeset
   789
                    ret.extend(globbed)
1b1b3dd630a5 windows: hoist expand_glob() back into util.py
Steve Borho <steve@borho.org>
parents: 7890
diff changeset
   790
                    continue
1b1b3dd630a5 windows: hoist expand_glob() back into util.py
Steve Borho <steve@borho.org>
parents: 7890
diff changeset
   791
                # if we couldn't expand the glob, just keep it around
1b1b3dd630a5 windows: hoist expand_glob() back into util.py
Steve Borho <steve@borho.org>
parents: 7890
diff changeset
   792
            ret.append(p)
1b1b3dd630a5 windows: hoist expand_glob() back into util.py
Steve Borho <steve@borho.org>
parents: 7890
diff changeset
   793
        return ret
7890
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   794
else:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   795
    from posix import *
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   796
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   797
def makelock(info, pathname):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   798
    try:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   799
        return os.symlink(info, pathname)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   800
    except OSError, why:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   801
        if why.errno == errno.EEXIST:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   802
            raise
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   803
    except AttributeError: # no symlink in os
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   804
        pass
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   805
704
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   806
    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
   807
    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
   808
    os.close(ld)
5ca319a641e1 Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 698
diff changeset
   809
7890
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   810
def readlock(pathname):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   811
    try:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   812
        return os.readlink(pathname)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   813
    except OSError, why:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   814
        if why.errno not in (errno.EINVAL, errno.ENOSYS):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   815
            raise
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   816
    except AttributeError: # no symlink in os
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   817
        pass
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   818
    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
   819
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   820
def nlinks(pathname):
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   821
    """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
   822
    return os.lstat(pathname).st_nlink
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   823
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   824
if hasattr(os, 'link'):
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   825
    os_link = os.link
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   826
else:
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   827
    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
   828
        raise OSError(0, _("Hardlinks not supported"))
1241
3b4f05ff3130 Add support for cloning with hardlinks on windows.
Stephen Darnell
parents: 1207
diff changeset
   829
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   830
def fstat(fp):
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   831
    '''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
   832
    try:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   833
        return os.fstat(fp.fileno())
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   834
    except AttributeError:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   835
        return os.stat(fp.name)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   836
3784
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   837
# File system features
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   838
6746
1dca460e7d1e rename checkfolding to checkcase
Matt Mackall <mpm@selenic.com>
parents: 6743
diff changeset
   839
def checkcase(path):
3784
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   840
    """
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   841
    Check whether the given path is on a case-sensitive filesystem
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   842
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   843
    Requires a path (like /foo/.hg) ending with a foldable final
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   844
    directory component.
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   845
    """
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   846
    s1 = os.stat(path)
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   847
    d, b = os.path.split(path)
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   848
    p2 = os.path.join(d, b.upper())
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   849
    if path == p2:
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   850
        p2 = os.path.join(d, b.lower())
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   851
    try:
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   852
        s2 = os.stat(p2)
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   853
        if s2 == s1:
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   854
            return False
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   855
        return True
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   856
    except:
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   857
        return True
1427949b8f80 imported patch folding
Matt Mackall <mpm@selenic.com>
parents: 3770
diff changeset
   858
6676
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   859
_fspathcache = {}
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   860
def fspath(name, root):
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   861
    '''Get name in the case stored in the filesystem
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   862
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   863
    The name is either relative to root, or it is an absolute path starting
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   864
    with root. Note that this function is unnecessary, and should not be
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   865
    called, for case-sensitive filesystems (simply because it's expensive).
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   866
    '''
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   867
    # If name is absolute, make it relative
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   868
    if name.lower().startswith(root.lower()):
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   869
        l = len(root)
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   870
        if name[l] == os.sep or name[l] == os.altsep:
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   871
            l = l + 1
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   872
        name = name[l:]
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   873
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   874
    if not os.path.exists(os.path.join(root, name)):
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   875
        return None
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   876
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   877
    seps = os.sep
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   878
    if os.altsep:
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   879
        seps = seps + os.altsep
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   880
    # Protect backslashes. This gets silly very quickly.
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   881
    seps.replace('\\','\\\\')
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   882
    pattern = re.compile(r'([^%s]+)|([%s]+)' % (seps, seps))
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   883
    dir = os.path.normcase(os.path.normpath(root))
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   884
    result = []
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   885
    for part, sep in pattern.findall(name):
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   886
        if sep:
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   887
            result.append(sep)
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   888
            continue
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   889
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   890
        if dir not in _fspathcache:
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   891
            _fspathcache[dir] = os.listdir(dir)
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   892
        contents = _fspathcache[dir]
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   893
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   894
        lpart = part.lower()
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   895
        for n in contents:
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   896
            if n.lower() == lpart:
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   897
                result.append(n)
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   898
                break
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   899
        else:
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   900
            # Cannot happen, as the file exists!
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   901
            result.append(part)
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   902
        dir = os.path.join(dir, lpart)
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   903
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   904
    return ''.join(result)
33045179d079 Add a new function, fspath
Paul Moore <p.f.moore@gmail.com>
parents: 6595
diff changeset
   905
3994
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   906
def checkexec(path):
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   907
    """
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   908
    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
   909
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   910
    Requires a directory (like /foo/.hg)
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   911
    """
5739
45fa7b1c5d4c checkexec: fix VFAT tempfile droppings with more modern Linux kernels
Matt Mackall <mpm@selenic.com>
parents: 5707
diff changeset
   912
45fa7b1c5d4c checkexec: fix VFAT tempfile droppings with more modern Linux kernels
Matt Mackall <mpm@selenic.com>
parents: 5707
diff changeset
   913
    # VFAT on some Linux versions can flip mode but it doesn't persist
45fa7b1c5d4c checkexec: fix VFAT tempfile droppings with more modern Linux kernels
Matt Mackall <mpm@selenic.com>
parents: 5707
diff changeset
   914
    # a FS remount. Frequently we can detect it if files are created
45fa7b1c5d4c checkexec: fix VFAT tempfile droppings with more modern Linux kernels
Matt Mackall <mpm@selenic.com>
parents: 5707
diff changeset
   915
    # with exec bit on.
45fa7b1c5d4c checkexec: fix VFAT tempfile droppings with more modern Linux kernels
Matt Mackall <mpm@selenic.com>
parents: 5707
diff changeset
   916
5212
316ce5e85b3e check exec: return fallback in case of error during the check
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 5077
diff changeset
   917
    try:
5420
6d1bd20ae14d Execution bit detection fixes for VFAT on Linux
Rafael Villar Burke <pachi@rvburke.com>
parents: 5396
diff changeset
   918
        EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
5212
316ce5e85b3e check exec: return fallback in case of error during the check
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 5077
diff changeset
   919
        fh, fn = tempfile.mkstemp("", "", path)
5739
45fa7b1c5d4c checkexec: fix VFAT tempfile droppings with more modern Linux kernels
Matt Mackall <mpm@selenic.com>
parents: 5707
diff changeset
   920
        try:
45fa7b1c5d4c checkexec: fix VFAT tempfile droppings with more modern Linux kernels
Matt Mackall <mpm@selenic.com>
parents: 5707
diff changeset
   921
            os.close(fh)
45fa7b1c5d4c checkexec: fix VFAT tempfile droppings with more modern Linux kernels
Matt Mackall <mpm@selenic.com>
parents: 5707
diff changeset
   922
            m = os.stat(fn).st_mode & 0777
45fa7b1c5d4c checkexec: fix VFAT tempfile droppings with more modern Linux kernels
Matt Mackall <mpm@selenic.com>
parents: 5707
diff changeset
   923
            new_file_has_exec = m & EXECFLAGS
45fa7b1c5d4c checkexec: fix VFAT tempfile droppings with more modern Linux kernels
Matt Mackall <mpm@selenic.com>
parents: 5707
diff changeset
   924
            os.chmod(fn, m ^ EXECFLAGS)
5759
027264e720aa util: filter all st_mode with 0777 in checkexec
Patrick Mezard <pmezard@gmail.com>
parents: 5743
diff changeset
   925
            exec_flags_cannot_flip = ((os.stat(fn).st_mode & 0777) == m)
5739
45fa7b1c5d4c checkexec: fix VFAT tempfile droppings with more modern Linux kernels
Matt Mackall <mpm@selenic.com>
parents: 5707
diff changeset
   926
        finally:
45fa7b1c5d4c checkexec: fix VFAT tempfile droppings with more modern Linux kernels
Matt Mackall <mpm@selenic.com>
parents: 5707
diff changeset
   927
            os.unlink(fn)
45fa7b1c5d4c checkexec: fix VFAT tempfile droppings with more modern Linux kernels
Matt Mackall <mpm@selenic.com>
parents: 5707
diff changeset
   928
    except (IOError, OSError):
5212
316ce5e85b3e check exec: return fallback in case of error during the check
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 5077
diff changeset
   929
        # we don't care, the user probably won't be able to commit anyway
316ce5e85b3e check exec: return fallback in case of error during the check
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 5077
diff changeset
   930
        return False
5420
6d1bd20ae14d Execution bit detection fixes for VFAT on Linux
Rafael Villar Burke <pachi@rvburke.com>
parents: 5396
diff changeset
   931
    return not (new_file_has_exec or exec_flags_cannot_flip)
3994
1cc60eebc71f exec: checkexec checks whether filesystem supports exec flags
Matt Mackall <mpm@selenic.com>
parents: 3906
diff changeset
   932
4002
d7b9ec589546 symlinks: use is_link wherever is_exec is used
Matt Mackall <mpm@selenic.com>
parents: 4000
diff changeset
   933
def checklink(path):
3998
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   934
    """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
   935
    # 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
   936
    # file already exists
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   937
    name = tempfile.mktemp(dir=path)
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   938
    try:
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   939
        os.symlink(".", name)
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   940
        os.unlink(name)
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   941
        return True
4017
ea6174c96ae1 catch AttributeError in util.checklink
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4002
diff changeset
   942
    except (OSError, AttributeError):
3998
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   943
        return False
315d47991fd4 symlinks: check whether a filesystem supports symlinks
Matt Mackall <mpm@selenic.com>
parents: 3997
diff changeset
   944
4434
439b1c35348a Fix issue483 - mq does not work under windows with gnu-win32 patch.
Patrick Mezard <pmezard@gmail.com>
parents: 4407
diff changeset
   945
def needbinarypatch():
439b1c35348a Fix issue483 - mq does not work under windows with gnu-win32 patch.
Patrick Mezard <pmezard@gmail.com>
parents: 4407
diff changeset
   946
    """return True if patches should be applied in binary mode by default."""
439b1c35348a Fix issue483 - mq does not work under windows with gnu-win32 patch.
Patrick Mezard <pmezard@gmail.com>
parents: 4407
diff changeset
   947
    return os.name == 'nt'
439b1c35348a Fix issue483 - mq does not work under windows with gnu-win32 patch.
Patrick Mezard <pmezard@gmail.com>
parents: 4407
diff changeset
   948
5843
83c354c4d529 Add endswithsep() and use it instead of using os.sep and os.altsep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5802
diff changeset
   949
def endswithsep(path):
83c354c4d529 Add endswithsep() and use it instead of using os.sep and os.altsep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5802
diff changeset
   950
    '''Check path ends with os.sep or os.altsep.'''
83c354c4d529 Add endswithsep() and use it instead of using os.sep and os.altsep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5802
diff changeset
   951
    return path.endswith(os.sep) or os.altsep and path.endswith(os.altsep)
83c354c4d529 Add endswithsep() and use it instead of using os.sep and os.altsep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5802
diff changeset
   952
5844
07d8eb78dd68 Add util.splitpath() and use it instead of using os.sep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5843
diff changeset
   953
def splitpath(path):
07d8eb78dd68 Add util.splitpath() and use it instead of using os.sep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5843
diff changeset
   954
    '''Split path by os.sep.
07d8eb78dd68 Add util.splitpath() and use it instead of using os.sep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5843
diff changeset
   955
    Note that this function does not use os.altsep because this is
07d8eb78dd68 Add util.splitpath() and use it instead of using os.sep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5843
diff changeset
   956
    an alternative of simple "xxx.split(os.sep)".
07d8eb78dd68 Add util.splitpath() and use it instead of using os.sep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5843
diff changeset
   957
    It is recommended to use os.path.normpath() before using this
07d8eb78dd68 Add util.splitpath() and use it instead of using os.sep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5843
diff changeset
   958
    function if need.'''
07d8eb78dd68 Add util.splitpath() and use it instead of using os.sep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5843
diff changeset
   959
    return path.split(os.sep)
07d8eb78dd68 Add util.splitpath() and use it instead of using os.sep directly.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 5843
diff changeset
   960
6007
090b1a665901 filemerge: add config item for GUI tools
Matt Mackall <mpm@selenic.com>
parents: 6006
diff changeset
   961
def gui():
090b1a665901 filemerge: add config item for GUI tools
Matt Mackall <mpm@selenic.com>
parents: 6006
diff changeset
   962
    '''Are we running in a GUI?'''
090b1a665901 filemerge: add config item for GUI tools
Matt Mackall <mpm@selenic.com>
parents: 6006
diff changeset
   963
    return os.name == "nt" or os.name == "mac" or os.environ.get("DISPLAY")
090b1a665901 filemerge: add config item for GUI tools
Matt Mackall <mpm@selenic.com>
parents: 6006
diff changeset
   964
6132
1ee95f7df611 util: always define a dummy lookup_reg()
Patrick Mezard <pmezard@gmail.com>
parents: 6111
diff changeset
   965
def lookup_reg(key, name=None, scope=None):
1ee95f7df611 util: always define a dummy lookup_reg()
Patrick Mezard <pmezard@gmail.com>
parents: 6111
diff changeset
   966
    return None
1ee95f7df611 util: always define a dummy lookup_reg()
Patrick Mezard <pmezard@gmail.com>
parents: 6111
diff changeset
   967
6062
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
   968
def mktempcopy(name, emptyok=False, createmode=None):
4827
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   969
    """Create a temporary file with the same contents from name
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   970
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   971
    The permission bits are copied from the original file.
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   972
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   973
    If the temporary file is going to be truncated immediately, you
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   974
    can use emptyok=True as an optimization.
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   975
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   976
    Returns the name of the temporary file.
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
   977
    """
4827
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   978
    d, fn = os.path.split(name)
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   979
    fd, temp = tempfile.mkstemp(prefix='.%s-' % fn, dir=d)
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   980
    os.close(fd)
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   981
    # Temporary files are created with mode 0600, which is usually not
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   982
    # what we want.  If the original file already exists, just copy
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   983
    # its mode.  Otherwise, manually obey umask.
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   984
    try:
5740
9046a4f6a07c atomictempfile: avoid chmod weirdness on Linux vfat
Matt Mackall <mpm@selenic.com>
parents: 5739
diff changeset
   985
        st_mode = os.lstat(name).st_mode & 0777
4827
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   986
    except OSError, inst:
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   987
        if inst.errno != errno.ENOENT:
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   988
            raise
6062
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
   989
        st_mode = createmode
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
   990
        if st_mode is None:
7890
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents: 7879
diff changeset
   991
            st_mode = ~umask
6062
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
   992
        st_mode &= 0666
4827
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   993
    os.chmod(temp, st_mode)
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   994
    if emptyok:
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   995
        return temp
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   996
    try:
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   997
        try:
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   998
            ifp = posixfile(name, "rb")
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
   999
        except IOError, inst:
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1000
            if inst.errno == errno.ENOENT:
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1001
                return temp
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1002
            if not getattr(inst, 'filename', None):
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1003
                inst.filename = name
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1004
            raise
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1005
        ofp = posixfile(temp, "wb")
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1006
        for chunk in filechunkiter(ifp):
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1007
            ofp.write(chunk)
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1008
        ifp.close()
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1009
        ofp.close()
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1010
    except:
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1011
        try: os.unlink(temp)
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1012
        except: pass
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1013
        raise
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1014
    return temp
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1015
4827
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1016
class atomictempfile(posixfile):
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1017
    """file-like object that atomically updates a file
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1018
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1019
    All writes will be redirected to a temporary copy of the original
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1020
    file.  When rename is called, the copy is renamed to the original
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1021
    name, making the changes visible.
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1022
    """
6062
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1023
    def __init__(self, name, mode, createmode):
4827
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1024
        self.__name = name
6062
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1025
        self.temp = mktempcopy(name, emptyok=('w' in mode),
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1026
                               createmode=createmode)
4827
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1027
        posixfile.__init__(self, self.temp, mode)
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1028
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1029
    def rename(self):
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1030
        if not self.closed:
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1031
            posixfile.close(self)
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1032
            rename(self.temp, localpath(self.__name))
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1033
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1034
    def __del__(self):
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1035
        if not self.closed:
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1036
            try:
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1037
                os.unlink(self.temp)
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1038
            except: pass
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1039
            posixfile.close(self)
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1040
6062
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1041
def makedirs(name, mode=None):
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1042
    """recursive directory creation with parent mode inheritance"""
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1043
    try:
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1044
        os.mkdir(name)
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1045
        if mode is not None:
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1046
            os.chmod(name, mode)
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1047
        return
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1048
    except OSError, err:
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1049
        if err.errno == errno.EEXIST:
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1050
            return
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1051
        if err.errno != errno.ENOENT:
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1052
            raise
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1053
    parent = os.path.abspath(os.path.dirname(name))
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1054
    makedirs(parent, mode)
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1055
    makedirs(name, mode)
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1056
4827
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1057
class opener(object):
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1058
    """Open files relative to a base directory
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1059
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1060
    This class is used to hide the details of COW semantics and
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1061
    remote file access from higher level code.
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1062
    """
4827
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1063
    def __init__(self, base, audit=True):
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1064
        self.base = base
5158
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
  1065
        if audit:
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
  1066
            self.audit_path = path_auditor(base)
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
  1067
        else:
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
  1068
            self.audit_path = always
6062
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1069
        self.createmode = None
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1070
4828
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1071
    def __getattr__(self, name):
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1072
        if name == '_can_symlink':
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1073
            self._can_symlink = checklink(self.base)
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1074
            return self._can_symlink
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1075
        raise AttributeError(name)
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1076
6062
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1077
    def _fixfilemode(self, name):
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1078
        if self.createmode is None:
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1079
            return
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1080
        os.chmod(name, self.createmode & 0666)
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1081
4827
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1082
    def __call__(self, path, mode="r", text=False, atomictemp=False):
5158
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
  1083
        self.audit_path(path)
4827
89defeae88f3 turn util.opener into a class
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4803
diff changeset
  1084
        f = os.path.join(self.base, path)
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1085
4720
72fb6f10fac1 OpenVMS patches
Jean-Francois PIERONNE <jf.pieronne@laposte.net>
parents: 4708
diff changeset
  1086
        if not text and "b" not in mode:
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1087
            mode += "b" # for that other OS
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1088
6062
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1089
        nlink = -1
6835
08d9e0f974d9 make mq and tags hardlink safe
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6339
diff changeset
  1090
        if mode not in ("r", "rb"):
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1091
            try:
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1092
                nlink = nlinks(f)
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1093
            except OSError:
4328
1083ae4b5f0e util.opener: if requested, use atomicfile even if the file doesn't exist
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4327
diff changeset
  1094
                nlink = 0
2176
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):
6062
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1097
                    makedirs(d, self.createmode)
4508
0026ccc2bf23 Remove atomicfile class.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4488
diff changeset
  1098
            if atomictemp:
6062
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1099
                return atomictempfile(f, mode, self.createmode)
4328
1083ae4b5f0e util.opener: if requested, use atomicfile even if the file doesn't exist
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4327
diff changeset
  1100
            if nlink > 1:
1083ae4b5f0e util.opener: if requested, use atomicfile even if the file doesn't exist
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4327
diff changeset
  1101
                rename(mktempcopy(f), f)
6062
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1102
        fp = posixfile(f, mode)
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1103
        if nlink == 0:
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1104
            self._fixfilemode(f)
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1105
        return fp
2176
9b42304d9896 fix file handling bugs on windows.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2117
diff changeset
  1106
4828
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1107
    def symlink(self, src, dst):
5158
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5124
diff changeset
  1108
        self.audit_path(dst)
4828
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1109
        linkname = os.path.join(self.base, dst)
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1110
        try:
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1111
            os.unlink(linkname)
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1112
        except OSError:
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1113
            pass
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1114
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1115
        dirname = os.path.dirname(linkname)
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1116
        if not os.path.exists(dirname):
6062
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1117
            makedirs(dirname, self.createmode)
4828
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1118
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1119
        if self._can_symlink:
4948
c8d1aa1822d5 Print meaningful error message if os.symlink fails
Bryan O'Sullivan <bos@serpentine.com>
parents: 4876
diff changeset
  1120
            try:
c8d1aa1822d5 Print meaningful error message if os.symlink fails
Bryan O'Sullivan <bos@serpentine.com>
parents: 4876
diff changeset
  1121
                os.symlink(src, linkname)
c8d1aa1822d5 Print meaningful error message if os.symlink fails
Bryan O'Sullivan <bos@serpentine.com>
parents: 4876
diff changeset
  1122
            except OSError, err:
c8d1aa1822d5 Print meaningful error message if os.symlink fails
Bryan O'Sullivan <bos@serpentine.com>
parents: 4876
diff changeset
  1123
                raise OSError(err.errno, _('could not symlink to %r: %s') %
c8d1aa1822d5 Print meaningful error message if os.symlink fails
Bryan O'Sullivan <bos@serpentine.com>
parents: 4876
diff changeset
  1124
                              (src, err.strerror), linkname)
4828
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1125
        else:
5077
84b10dc3dccc Fix issue 653: symlinks checkout failure on non-supporting platforms
Patrick Mezard <pmezard@gmail.com>
parents: 5062
diff changeset
  1126
            f = self(dst, "w")
4828
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1127
            f.write(src)
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1128
            f.close()
6062
3c3b126e5619 Make files in .hg inherit the permissions from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 6007
diff changeset
  1129
            self._fixfilemode(dst)
4828
41ad4105dde9 Add symlink method to util.opener.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4827
diff changeset
  1130
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1131
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
  1132
    """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
  1133
    iterator over chunks of arbitrary size."""
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
  1134
5446
fa836e050c50 chunkbuffer: removed unused method and arg
Matt Mackall <mpm@selenic.com>
parents: 5420
diff changeset
  1135
    def __init__(self, in_iter):
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1136
        """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
  1137
        targetsize is how big a buffer to try to maintain."""
5447
56591846f819 chunkiter: simplify iter logic
Matt Mackall <mpm@selenic.com>
parents: 5446
diff changeset
  1138
        self.iter = iter(in_iter)
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1139
        self.buf = ''
5446
fa836e050c50 chunkbuffer: removed unused method and arg
Matt Mackall <mpm@selenic.com>
parents: 5420
diff changeset
  1140
        self.targetsize = 2**16
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
  1141
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1142
    def read(self, l):
1200
333de1d53846 Minor cleanups.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1199
diff changeset
  1143
        """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
  1144
        Returns less than L bytes if the iterator runs dry."""
5447
56591846f819 chunkiter: simplify iter logic
Matt Mackall <mpm@selenic.com>
parents: 5446
diff changeset
  1145
        if l > len(self.buf) and self.iter:
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1146
            # Clamp to a multiple of self.targetsize
5449
17a4b20eda7b chunkiter: handle large reads more efficiently
Matt Mackall <mpm@selenic.com>
parents: 5447
diff changeset
  1147
            targetsize = max(l, self.targetsize)
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1148
            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
  1149
            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
  1150
            collected = len(self.buf)
5447
56591846f819 chunkiter: simplify iter logic
Matt Mackall <mpm@selenic.com>
parents: 5446
diff changeset
  1151
            for chunk in self.iter:
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1152
                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
  1153
                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
  1154
                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
  1155
                    break
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1156
            if collected < targetsize:
5447
56591846f819 chunkiter: simplify iter logic
Matt Mackall <mpm@selenic.com>
parents: 5446
diff changeset
  1157
                self.iter = False
1199
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1158
            self.buf = collector.getvalue()
5449
17a4b20eda7b chunkiter: handle large reads more efficiently
Matt Mackall <mpm@selenic.com>
parents: 5447
diff changeset
  1159
        if len(self.buf) == l:
5450
c728424d44c6 revlog: fix caching of buffer objects
Matt Mackall <mpm@selenic.com>
parents: 5449
diff changeset
  1160
            s, self.buf = str(self.buf), ''
5449
17a4b20eda7b chunkiter: handle large reads more efficiently
Matt Mackall <mpm@selenic.com>
parents: 5447
diff changeset
  1161
        else:
17a4b20eda7b chunkiter: handle large reads more efficiently
Matt Mackall <mpm@selenic.com>
parents: 5447
diff changeset
  1162
            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
  1163
        return s
78ceaf83f28f Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents: 1169
diff changeset
  1164
2462
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1165
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
  1166
    """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
  1167
    (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
  1168
    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
  1169
    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
  1170
    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
  1171
    requested."""
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1172
    assert size >= 0
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1173
    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
  1174
    while True:
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1175
        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
  1176
        else: nbytes = min(limit, size)
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1177
        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
  1178
        if not s: break
d610bcfd66a8 util: add limit to amount filechunkiter will read
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2448
diff changeset
  1179
        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
  1180
        yield s
1320
5f277e73778f Fix up representation of dates in hgweb.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1312
diff changeset
  1181
1321
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
  1182
def makedate():
1482
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
  1183
    lt = time.localtime()
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
  1184
    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
  1185
        tz = time.altzone
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
  1186
    else:
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
  1187
        tz = time.timezone
4d38b85e60aa fix handling of daylight saving time
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1479
diff changeset
  1188
    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
  1189
6229
c3182eeb70ea dates: improve timezone handling
Matt Mackall <mpm@selenic.com>
parents: 6224
diff changeset
  1190
def datestr(date=None, format='%a %b %d %H:%M:%S %Y %1%2'):
1321
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
  1191
    """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
  1192
    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
  1193
    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
  1194
    append time zone to string."""
1321
b47f96a178a3 Clean up date and timezone handling.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1320
diff changeset
  1195
    t, tz = date or makedate()
6229
c3182eeb70ea dates: improve timezone handling
Matt Mackall <mpm@selenic.com>
parents: 6224
diff changeset
  1196
    if "%1" in format or "%2" in format:
c3182eeb70ea dates: improve timezone handling
Matt Mackall <mpm@selenic.com>
parents: 6224
diff changeset
  1197
        sign = (tz > 0) and "-" or "+"
c3182eeb70ea dates: improve timezone handling
Matt Mackall <mpm@selenic.com>
parents: 6224
diff changeset
  1198
        minutes = abs(tz) / 60
c3182eeb70ea dates: improve timezone handling
Matt Mackall <mpm@selenic.com>
parents: 6224
diff changeset
  1199
        format = format.replace("%1", "%c%02d" % (sign, minutes / 60))
c3182eeb70ea dates: improve timezone handling
Matt Mackall <mpm@selenic.com>
parents: 6224
diff changeset
  1200
        format = format.replace("%2", "%02d" % (minutes % 60))
1987
04c17fc39c84 add changelog style to command line template.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1976
diff changeset
  1201
    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
  1202
    return s
1829
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1203
6134
7b937b26adf7 Make annotae/grep print short dates with -q/--quiet.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6111
diff changeset
  1204
def shortdate(date=None):
7b937b26adf7 Make annotae/grep print short dates with -q/--quiet.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6111
diff changeset
  1205
    """turn (timestamp, tzoff) tuple into iso 8631 date."""
6229
c3182eeb70ea dates: improve timezone handling
Matt Mackall <mpm@selenic.com>
parents: 6224
diff changeset
  1206
    return datestr(date, format='%Y-%m-%d')
6134
7b937b26adf7 Make annotae/grep print short dates with -q/--quiet.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6111
diff changeset
  1207
5357
c6adf2be6069 util: add default argument to strdate
Bryan O'Sullivan <bos@serpentine.com>
parents: 5293
diff changeset
  1208
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
  1209
    """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
  1210
    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
  1211
    def timezone(string):
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1212
        tz = string.split()[-1]
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1213
        if tz[0] in "+-" and len(tz) == 5 and tz[1:].isdigit():
6229
c3182eeb70ea dates: improve timezone handling
Matt Mackall <mpm@selenic.com>
parents: 6224
diff changeset
  1214
            sign = (tz[0] == "+") and 1 or -1
c3182eeb70ea dates: improve timezone handling
Matt Mackall <mpm@selenic.com>
parents: 6224
diff changeset
  1215
            hours = int(tz[1:3])
c3182eeb70ea dates: improve timezone handling
Matt Mackall <mpm@selenic.com>
parents: 6224
diff changeset
  1216
            minutes = int(tz[3:5])
c3182eeb70ea dates: improve timezone handling
Matt Mackall <mpm@selenic.com>
parents: 6224
diff changeset
  1217
            return -sign * (hours * 60 + minutes) * 60
3809
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1218
        if tz == "GMT" or tz == "UTC":
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1219
            return 0
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1220
        return None
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1221
3255
e96d2956eb4a util.strdate: compute timestamp using UTC, not local timezone
Jose M. Prieto <jmprieto@gmx.net>
parents: 3176
diff changeset
  1222
    # NOTE: unixtime = localunixtime + offset
3809
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1223
    offset, date = timezone(string), string
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1224
    if offset != None:
4d93b37b5963 parsedate: add UTC and GMT timezones
Matt Mackall <mpm@selenic.com>
parents: 3808
diff changeset
  1225
        date = " ".join(string.split()[:-1])
3808
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
  1226
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1227
    # add missing elements from defaults
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1228
    for part in defaults:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1229
        found = [True for p in part if ("%"+p) in format]
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1230
        if not found:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1231
            date += "@" + defaults[part]
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1232
            format += "@%" + part[0]
3808
d6529582942a improve date parsing for numerous new date formats
Matt Mackall <mpm@selenic.com>
parents: 3807
diff changeset
  1233
3256
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
  1234
    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
  1235
    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
  1236
    if offset is None:
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
  1237
        # local timezone
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
  1238
        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
  1239
        offset = unixtime - localunixtime
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
  1240
    else:
e5c9a084ffe3 util.strdate: assume local time when no timezone specified
Jose M. Prieto <jmprieto@gmx.net>
parents: 3255
diff changeset
  1241
        unixtime = localunixtime + offset
3255
e96d2956eb4a util.strdate: compute timestamp using UTC, not local timezone
Jose M. Prieto <jmprieto@gmx.net>
parents: 3176
diff changeset
  1242
    return unixtime, offset
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1243
6139
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
  1244
def parsedate(date, formats=None, defaults=None):
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
  1245
    """parse a localized date/time string and return a (unixtime, offset) tuple.
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
  1246
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1247
    The date may be a "unixtime offset" string or in one of the specified
6139
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
  1248
    formats. If the date already is a (unixtime, offset) tuple, it is returned.
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
  1249
    """
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
  1250
    if not date:
3807
e43b48f0f718 parsedate: allow '' for epoch
Matt Mackall <mpm@selenic.com>
parents: 3806
diff changeset
  1251
        return 0, 0
6230
c7253d1a774e dates: Fix bare times to be relative to "today"
Matt Mackall <mpm@selenic.com>
parents: 6229
diff changeset
  1252
    if isinstance(date, tuple) and len(date) == 2:
6139
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
  1253
        return date
2609
6c5b1b5cc160 util.parsedate should understand dates from hg export
Chris Mason <mason@suse.com>
parents: 2601
diff changeset
  1254
    if not formats:
6c5b1b5cc160 util.parsedate should understand dates from hg export
Chris Mason <mason@suse.com>
parents: 2601
diff changeset
  1255
        formats = defaultdateformats
6139
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
  1256
    date = date.strip()
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1257
    try:
6139
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
  1258
        when, offset = map(int, date.split(' '))
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1259
    except ValueError:
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1260
        # fill out defaults
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1261
        if not defaults:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1262
            defaults = {}
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1263
        now = makedate()
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1264
        for part in "d mb yY HI M S".split():
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1265
            if part not in defaults:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1266
                if part[0] in "HMS":
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1267
                    defaults[part] = "00"
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1268
                else:
6229
c3182eeb70ea dates: improve timezone handling
Matt Mackall <mpm@selenic.com>
parents: 6224
diff changeset
  1269
                    defaults[part] = datestr(now, "%" + part[0])
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1270
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1271
        for format in formats:
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1272
            try:
6139
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
  1273
                when, offset = strdate(date, format, defaults)
6087
12856a1742dc better handle errors with date parsing (issue983)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5917
diff changeset
  1274
            except (ValueError, OverflowError):
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1275
                pass
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1276
            else:
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1277
                break
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1278
        else:
6139
989467e8e3a9 Fix bad behaviour when specifying an invalid date (issue700)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6135
diff changeset
  1279
            raise Abort(_('invalid date: %r ') % date)
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1280
    # 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
  1281
    # 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
  1282
    # 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
  1283
    # to UTC+14
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
  1284
    if abs(when) > 0x7fffffff:
3806
92a3532a01d9 parsedate: use Abort rather than ValueError
Matt Mackall <mpm@selenic.com>
parents: 3784
diff changeset
  1285
        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
  1286
    if offset < -50400 or offset > 43200:
3806
92a3532a01d9 parsedate: use Abort rather than ValueError
Matt Mackall <mpm@selenic.com>
parents: 3784
diff changeset
  1287
        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
  1288
    return when, offset
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2480
diff changeset
  1289
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1290
def matchdate(date):
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1291
    """Return a function that matches a given date match specifier
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1292
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1293
    Formats include:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1294
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1295
    '{date}' match a given date to the accuracy provided
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1296
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1297
    '<{date}' on or before a given date
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1298
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1299
    '>{date}' on or after a given date
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1300
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1301
    """
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1302
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1303
    def lower(date):
6230
c7253d1a774e dates: Fix bare times to be relative to "today"
Matt Mackall <mpm@selenic.com>
parents: 6229
diff changeset
  1304
        d = dict(mb="1", d="1")
c7253d1a774e dates: Fix bare times to be relative to "today"
Matt Mackall <mpm@selenic.com>
parents: 6229
diff changeset
  1305
        return parsedate(date, extendeddateformats, d)[0]
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1306
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1307
    def upper(date):
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1308
        d = dict(mb="12", HI="23", M="59", S="59")
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1309
        for days in "31 30 29".split():
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1310
            try:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1311
                d["d"] = days
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1312
                return parsedate(date, extendeddateformats, d)[0]
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1313
            except:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1314
                pass
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1315
        d["d"] = "28"
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1316
        return parsedate(date, extendeddateformats, d)[0]
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1317
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1318
    if date[0] == "<":
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1319
        when = upper(date[1:])
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1320
        return lambda x: x <= when
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1321
    elif date[0] == ">":
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1322
        when = lower(date[1:])
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1323
        return lambda x: x >= when
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1324
    elif date[0] == "-":
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1325
        try:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1326
            days = int(date[1:])
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1327
        except ValueError:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1328
            raise Abort(_("invalid day spec: %s") % date[1:])
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1329
        when = makedate()[0] - days * 3600 * 24
3813
fc5ba0ab7f45 Add --date support to log
Matt Mackall <mpm@selenic.com>
parents: 3812
diff changeset
  1330
        return lambda x: x >= when
3812
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1331
    elif " to " in date:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1332
        a, b = date.split(" to ")
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1333
        start, stop = lower(a), upper(b)
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1334
        return lambda x: x >= start and x <= stop
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1335
    else:
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1336
        start, stop = lower(date), upper(date)
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1337
        return lambda x: x >= start and x <= stop
bf6ab30559e6 Add date matching support
Matt Mackall <mpm@selenic.com>
parents: 3809
diff changeset
  1338
1903
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1339
def shortuser(user):
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1340
    """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
  1341
    f = user.find('@')
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1342
    if f >= 0:
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1343
        user = user[:f]
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1344
    f = user.find('<')
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1345
    if f >= 0:
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1346
        user = user[f+1:]
3176
7492b33bdd9f shortuser should stop before the first space character.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3147
diff changeset
  1347
    f = user.find(' ')
7492b33bdd9f shortuser should stop before the first space character.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3147
diff changeset
  1348
    if f >= 0:
7492b33bdd9f shortuser should stop before the first space character.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3147
diff changeset
  1349
        user = user[:f]
3533
bb44489b901f shortname: truncate at '.' too
Matt Mackall <mpm@selenic.com>
parents: 3466
diff changeset
  1350
    f = user.find('.')
bb44489b901f shortname: truncate at '.' too
Matt Mackall <mpm@selenic.com>
parents: 3466
diff changeset
  1351
    if f >= 0:
bb44489b901f shortname: truncate at '.' too
Matt Mackall <mpm@selenic.com>
parents: 3466
diff changeset
  1352
        user = user[:f]
1903
e4abeafd6eb1 move shortuser into util module.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1353
    return user
1920
b7cc0f323a4c merge with crew.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1903 1882
diff changeset
  1354
5975
75d9fe70c654 templater: move email function to util
Matt Mackall <mpm@selenic.com>
parents: 5949
diff changeset
  1355
def email(author):
75d9fe70c654 templater: move email function to util
Matt Mackall <mpm@selenic.com>
parents: 5949
diff changeset
  1356
    '''get email of author.'''
75d9fe70c654 templater: move email function to util
Matt Mackall <mpm@selenic.com>
parents: 5949
diff changeset
  1357
    r = author.find('>')
75d9fe70c654 templater: move email function to util
Matt Mackall <mpm@selenic.com>
parents: 5949
diff changeset
  1358
    if r == -1: r = None
75d9fe70c654 templater: move email function to util
Matt Mackall <mpm@selenic.com>
parents: 5949
diff changeset
  1359
    return author[author.find('<')+1:r]
75d9fe70c654 templater: move email function to util
Matt Mackall <mpm@selenic.com>
parents: 5949
diff changeset
  1360
3767
1861fa38a6a7 Move ellipsis code to util.ellipsis() and improve maxlength handling.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3721
diff changeset
  1361
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
  1362
    """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
  1363
    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
  1364
        return text
1861fa38a6a7 Move ellipsis code to util.ellipsis() and improve maxlength handling.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3721
diff changeset
  1365
    else:
1861fa38a6a7 Move ellipsis code to util.ellipsis() and improve maxlength handling.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3721
diff changeset
  1366
        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
  1367
7523
e60aaae83323 hgweb: recurse down collections only if ** in [paths]
Benoit Allard <benoit@aeteurope.nl>
parents: 7494
diff changeset
  1368
def walkrepos(path, followsym=False, seen_dirs=None, recurse=False):
1829
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1369
    '''yield every hg repository under path, recursively.'''
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1370
    def errhandler(err):
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1371
        if err.filename == path:
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1372
            raise err
6284
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1373
    if followsym and hasattr(os.path, 'samestat'):
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1374
        def _add_dir_if_not_there(dirlst, dirname):
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1375
            match = False
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1376
            samestat = os.path.samestat
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1377
            dirstat = os.stat(dirname)
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1378
            for lstdirstat in dirlst:
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1379
                if samestat(dirstat, lstdirstat):
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1380
                    match = True
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1381
                    break
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1382
            if not match:
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1383
                dirlst.append(dirstat)
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1384
            return not match
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1385
    else:
6317
b0d937869417 hgwebdir: Tiny fix for webdir on non-symlink capable platforms.
Eric Hopper <hopper@omnifarious.org>
parents: 6284
diff changeset
  1386
        followsym = False
1829
b0f6af327fd4 hgwebdir: export collections of repos
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1635
diff changeset
  1387
6284
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1388
    if (seen_dirs is None) and followsym:
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1389
        seen_dirs = []
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1390
        _add_dir_if_not_there(seen_dirs, path)
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1391
    for root, dirs, files in os.walk(path, topdown=True, onerror=errhandler):
6140
47e6d5d5913a Simplify utils.walkrepos().
Walter Doerwald <walter@livinglogic.de>
parents: 6139
diff changeset
  1392
        if '.hg' in dirs:
47e6d5d5913a Simplify utils.walkrepos().
Walter Doerwald <walter@livinglogic.de>
parents: 6139
diff changeset
  1393
            yield root # found a repository
7525
6a49fa7674c1 hgweb: mq repos should be in non-recursive collections, too
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7523
diff changeset
  1394
            qroot = os.path.join(root, '.hg', 'patches')
6a49fa7674c1 hgweb: mq repos should be in non-recursive collections, too
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7523
diff changeset
  1395
            if os.path.isdir(os.path.join(qroot, '.hg')):
6a49fa7674c1 hgweb: mq repos should be in non-recursive collections, too
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 7523
diff changeset
  1396
                yield qroot # we have a patch queue repo here
7523
e60aaae83323 hgweb: recurse down collections only if ** in [paths]
Benoit Allard <benoit@aeteurope.nl>
parents: 7494
diff changeset
  1397
            if recurse:
e60aaae83323 hgweb: recurse down collections only if ** in [paths]
Benoit Allard <benoit@aeteurope.nl>
parents: 7494
diff changeset
  1398
                # avoid recursing inside the .hg directory
e60aaae83323 hgweb: recurse down collections only if ** in [paths]
Benoit Allard <benoit@aeteurope.nl>
parents: 7494
diff changeset
  1399
                dirs.remove('.hg')
e60aaae83323 hgweb: recurse down collections only if ** in [paths]
Benoit Allard <benoit@aeteurope.nl>
parents: 7494
diff changeset
  1400
            else:
e60aaae83323 hgweb: recurse down collections only if ** in [paths]
Benoit Allard <benoit@aeteurope.nl>
parents: 7494
diff changeset
  1401
                dirs[:] = [] # don't descend further
6284
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1402
        elif followsym:
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1403
            newdirs = []
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1404
            for d in dirs:
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1405
                fname = os.path.join(root, d)
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1406
                if _add_dir_if_not_there(seen_dirs, fname):
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1407
                    if os.path.islink(fname):
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1408
                        for hgname in walkrepos(fname, True, seen_dirs):
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1409
                            yield hgname
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1410
                    else:
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1411
                        newdirs.append(d)
c93b6c0e6e84 Allow hgwebdir collections to follow symlinks.
Eric Hopper <hopper@omnifarious.org>
parents: 6267
diff changeset
  1412
            dirs[:] = newdirs
1951
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
  1413
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
  1414
_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
  1415
4097
403c4ddd74bb Combined the two os_rcpath methods into a single one near rcpath in mercurial/util.py
Shane Holloway <shane.holloway@ieee.org>
parents: 4096
diff changeset
  1416
def os_rcpath():
403c4ddd74bb Combined the two os_rcpath methods into a single one near rcpath in mercurial/util.py
Shane Holloway <shane.holloway@ieee.org>
parents: 4096
diff changeset
  1417
    '''return default os-specific hgrc search path'''
403c4ddd74bb Combined the two os_rcpath methods into a single one near rcpath in mercurial/util.py
Shane Holloway <shane.holloway@ieee.org>
parents: 4096
diff changeset
  1418
    path = system_rcpath()
403c4ddd74bb Combined the two os_rcpath methods into a single one near rcpath in mercurial/util.py
Shane Holloway <shane.holloway@ieee.org>
parents: 4096
diff changeset
  1419
    path.extend(user_rcpath())
403c4ddd74bb Combined the two os_rcpath methods into a single one near rcpath in mercurial/util.py
Shane Holloway <shane.holloway@ieee.org>
parents: 4096
diff changeset
  1420
    path = [os.path.normpath(f) for f in path]
403c4ddd74bb Combined the two os_rcpath methods into a single one near rcpath in mercurial/util.py
Shane Holloway <shane.holloway@ieee.org>
parents: 4096
diff changeset
  1421
    return path
403c4ddd74bb Combined the two os_rcpath methods into a single one near rcpath in mercurial/util.py
Shane Holloway <shane.holloway@ieee.org>
parents: 4096
diff changeset
  1422
1951
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
  1423
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
  1424
    '''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
  1425
    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
  1426
    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
  1427
    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
  1428
    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
  1429
    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
  1430
    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
  1431
        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
  1432
            _rcpath = []
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
  1433
            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
  1434
                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
  1435
                if os.path.isdir(p):
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5360
diff changeset
  1436
                    for f, kind in osutil.listdir(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
  1437
                        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
  1438
                            _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
  1439
                else:
16750010813d use a proper test instead of catching every exception
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1951
diff changeset
  1440
                    _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
  1441
        else:
696230e52e4d add HGRCPATH env var, list of places to look for hgrc files.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1920
diff changeset
  1442
            _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
  1443
    return _rcpath
2612
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1444
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1445
def bytecount(nbytes):
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1446
    '''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
  1447
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1448
    units = (
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1449
        (100, 1<<30, _('%.0f GB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1450
        (10, 1<<30, _('%.1f GB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1451
        (1, 1<<30, _('%.2f GB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1452
        (100, 1<<20, _('%.0f MB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1453
        (10, 1<<20, _('%.1f MB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1454
        (1, 1<<20, _('%.2f MB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1455
        (100, 1<<10, _('%.0f KB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1456
        (10, 1<<10, _('%.1f KB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1457
        (1, 1<<10, _('%.2f KB')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1458
        (1, 1, _('%.0f bytes')),
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1459
        )
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1460
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1461
    for multiplier, divisor, format in units:
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1462
        if nbytes >= divisor * multiplier:
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1463
            return format % (nbytes / float(divisor))
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2609
diff changeset
  1464
    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
  1465
386f04d6ecb3 clean up hg.py: move repo constructor code into each repo module
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2655
diff changeset
  1466
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
  1467
    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
  1468
    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
  1469
        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
  1470
        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
  1471
            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
  1472
    return path
5291
23651848d638 extdiff: avoid repr() doubling paths backslashes under Windows
Patrick Mezard <pmezard@gmail.com>
parents: 5213
diff changeset
  1473
23651848d638 extdiff: avoid repr() doubling paths backslashes under Windows
Patrick Mezard <pmezard@gmail.com>
parents: 5213
diff changeset
  1474
def uirepr(s):
23651848d638 extdiff: avoid repr() doubling paths backslashes under Windows
Patrick Mezard <pmezard@gmail.com>
parents: 5213
diff changeset
  1475
    # Avoid double backslash in Windows path repr()
23651848d638 extdiff: avoid repr() doubling paths backslashes under Windows
Patrick Mezard <pmezard@gmail.com>
parents: 5213
diff changeset
  1476
    return repr(s).replace('\\\\', '\\')
7547
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1477
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1478
def termwidth():
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1479
    if 'COLUMNS' in os.environ:
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1480
        try:
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1481
            return int(os.environ['COLUMNS'])
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1482
        except ValueError:
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1483
            pass
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1484
    try:
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1485
        import termios, array, fcntl
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1486
        for dev in (sys.stdout, sys.stdin):
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1487
            try:
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1488
                fd = dev.fileno()
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1489
                if not os.isatty(fd):
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1490
                    continue
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1491
                arri = fcntl.ioctl(fd, termios.TIOCGWINSZ, '\0' * 8)
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1492
                return array.array('h', arri)[1]
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1493
            except ValueError:
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1494
                pass
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1495
    except ImportError:
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1496
        pass
4949729ee9ee python implementation of diffstat
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7537
diff changeset
  1497
    return 80
7879
5c4026a289a4 templater: ability to display diffstat for log-like commands
Alexander Solovyov <piranha at piranha.org.ua>
parents: 7875
diff changeset
  1498
5c4026a289a4 templater: ability to display diffstat for log-like commands
Alexander Solovyov <piranha at piranha.org.ua>
parents: 7875
diff changeset
  1499
def iterlines(iterator):
5c4026a289a4 templater: ability to display diffstat for log-like commands
Alexander Solovyov <piranha at piranha.org.ua>
parents: 7875
diff changeset
  1500
    for chunk in iterator:
5c4026a289a4 templater: ability to display diffstat for log-like commands
Alexander Solovyov <piranha at piranha.org.ua>
parents: 7875
diff changeset
  1501
        for line in chunk.splitlines():
5c4026a289a4 templater: ability to display diffstat for log-like commands
Alexander Solovyov <piranha at piranha.org.ua>
parents: 7875
diff changeset
  1502
            yield line