mercurial/scmutil.py
author Pierre-Yves David <pierre-yves.david@ens-lyon.org>
Thu, 12 Jul 2012 03:03:19 +0200
changeset 17183 4253cfee08ef
parent 17161 be016e96117a
child 17201 afd75476939e
permissions -rw-r--r--
push: fix bug in detection of remote obsolete support Current code check obsolete availability in local repo.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
13962
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     1
# scmutil.py - Mercurial core utility functions
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     2
#
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     3
#  Copyright Matt Mackall <mpm@selenic.com>
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     4
#
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     7
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
     8
from i18n import _
14980
28e98a8b173d i18n: use UTF-8 string to lower filename for case collision check
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 14861
diff changeset
     9
import util, error, osutil, revset, similar, encoding
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
    10
import match as matchmod
14861
6ed2a449cb5b scmutil: add missing import of re
Steve Borho <steve@borho.org>
parents: 14746
diff changeset
    11
import os, errno, re, stat, sys, glob
13962
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    12
15993
0b05e0bfdc1c scmutil: unify some 'no changes found' messages
Matt Mackall <mpm@selenic.com>
parents: 15797
diff changeset
    13
def nochangesfound(ui, secretlist=None):
0b05e0bfdc1c scmutil: unify some 'no changes found' messages
Matt Mackall <mpm@selenic.com>
parents: 15797
diff changeset
    14
    '''report no changes for push/pull'''
0b05e0bfdc1c scmutil: unify some 'no changes found' messages
Matt Mackall <mpm@selenic.com>
parents: 15797
diff changeset
    15
    if secretlist:
0b05e0bfdc1c scmutil: unify some 'no changes found' messages
Matt Mackall <mpm@selenic.com>
parents: 15797
diff changeset
    16
        ui.status(_("no changes found (ignored %d secret changesets)\n")
0b05e0bfdc1c scmutil: unify some 'no changes found' messages
Matt Mackall <mpm@selenic.com>
parents: 15797
diff changeset
    17
                  % len(secretlist))
0b05e0bfdc1c scmutil: unify some 'no changes found' messages
Matt Mackall <mpm@selenic.com>
parents: 15797
diff changeset
    18
    else:
0b05e0bfdc1c scmutil: unify some 'no changes found' messages
Matt Mackall <mpm@selenic.com>
parents: 15797
diff changeset
    19
        ui.status(_("no changes found\n"))
0b05e0bfdc1c scmutil: unify some 'no changes found' messages
Matt Mackall <mpm@selenic.com>
parents: 15797
diff changeset
    20
13974
23f2736abce3 move checkfilename from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13973
diff changeset
    21
def checkfilename(f):
23f2736abce3 move checkfilename from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13973
diff changeset
    22
    '''Check that the filename f is an acceptable filename for a tracked file'''
23f2736abce3 move checkfilename from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13973
diff changeset
    23
    if '\r' in f or '\n' in f:
23f2736abce3 move checkfilename from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13973
diff changeset
    24
        raise util.Abort(_("'\\n' and '\\r' disallowed in filenames: %r") % f)
23f2736abce3 move checkfilename from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13973
diff changeset
    25
13962
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    26
def checkportable(ui, f):
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    27
    '''Check if filename f is portable and warn or abort depending on config'''
13974
23f2736abce3 move checkfilename from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13973
diff changeset
    28
    checkfilename(f)
14138
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    29
    abort, warn = checkportabilityalert(ui)
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    30
    if abort or warn:
13962
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    31
        msg = util.checkwinfilename(f)
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    32
        if msg:
14138
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    33
            msg = "%s: %r" % (msg, f)
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    34
            if abort:
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    35
                raise util.Abort(msg)
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    36
            ui.warn(_("warning: %s\n") % msg)
14068
04ce8fa1015d add: notify when adding a file that would cause a case-folding collision
Kevin Gessner <kevin@kevingessner.com>
parents: 14067
diff changeset
    37
14067
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    38
def checkportabilityalert(ui):
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    39
    '''check if the user's config requests nothing, a warning, or abort for
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    40
    non-portable filenames'''
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    41
    val = ui.config('ui', 'portablefilenames', 'warn')
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    42
    lval = val.lower()
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    43
    bval = util.parsebool(val)
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    44
    abort = os.name == 'nt' or lval == 'abort'
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    45
    warn = bval or lval == 'warn'
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    46
    if bval is None and not (warn or abort or lval == 'ignore'):
13962
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    47
        raise error.ConfigError(
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    48
            _("ui.portablefilenames value is invalid ('%s')") % val)
14067
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    49
    return abort, warn
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    50
14138
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    51
class casecollisionauditor(object):
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    52
    def __init__(self, ui, abort, existingiter):
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    53
        self._ui = ui
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    54
        self._abort = abort
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    55
        self._map = {}
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    56
        for f in existingiter:
14980
28e98a8b173d i18n: use UTF-8 string to lower filename for case collision check
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 14861
diff changeset
    57
            self._map[encoding.lower(f)] = f
14067
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    58
14138
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    59
    def __call__(self, f):
14980
28e98a8b173d i18n: use UTF-8 string to lower filename for case collision check
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 14861
diff changeset
    60
        fl = encoding.lower(f)
14138
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    61
        map = self._map
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    62
        if fl in map and map[fl] != f:
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    63
            msg = _('possible case-folding collision for %s') % f
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    64
            if self._abort:
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    65
                raise util.Abort(msg)
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    66
            self._ui.warn(_("warning: %s\n") % msg)
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    67
        map[fl] = f
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
    68
14220
21b8ce4d3331 rename path_auditor to pathauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14167
diff changeset
    69
class pathauditor(object):
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    70
    '''ensure that a filesystem path contains no banned components.
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    71
    the following properties of a path are checked:
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    72
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    73
    - ends with a directory separator
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    74
    - under top-level .hg
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    75
    - starts at the root of a windows drive
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    76
    - contains ".."
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    77
    - traverses a symlink (e.g. a/symlink_here/b)
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    78
    - inside a nested repository (a callback can be used to approve
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    79
      some nested repositories, e.g., subrepositories)
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    80
    '''
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    81
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    82
    def __init__(self, root, callback=None):
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    83
        self.audited = set()
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    84
        self.auditeddir = set()
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    85
        self.root = root
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    86
        self.callback = callback
15666
37a6e9765015 pathauditor: switch normcase logic according to case sensitivity of filesystem
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15665
diff changeset
    87
        if os.path.lexists(root) and not util.checkcase(root):
37a6e9765015 pathauditor: switch normcase logic according to case sensitivity of filesystem
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15665
diff changeset
    88
            self.normcase = util.normcase
37a6e9765015 pathauditor: switch normcase logic according to case sensitivity of filesystem
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15665
diff changeset
    89
        else:
37a6e9765015 pathauditor: switch normcase logic according to case sensitivity of filesystem
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15665
diff changeset
    90
            self.normcase = lambda x: x
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    91
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    92
    def __call__(self, path):
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    93
        '''Check the relative path.
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    94
        path may contain a pattern (e.g. foodir/**.txt)'''
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    95
15721
4751d5133f15 windows: force specified path to be audited in localpath form
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15666
diff changeset
    96
        path = util.localpath(path)
15666
37a6e9765015 pathauditor: switch normcase logic according to case sensitivity of filesystem
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15665
diff changeset
    97
        normpath = self.normcase(path)
15664
ec8730886f36 pathauditor: use normcase()-ed path for audit result cache
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 14984
diff changeset
    98
        if normpath in self.audited:
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
    99
            return
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   100
        # AIX ignores "/" at end of path, others raise EISDIR.
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   101
        if util.endswithsep(path):
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   102
            raise util.Abort(_("path ends in directory separator: %s") % path)
15665
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   103
        parts = util.splitpath(path)
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   104
        if (os.path.splitdrive(path)[0]
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   105
            or parts[0].lower() in ('.hg', '.hg.', '')
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   106
            or os.pardir in parts):
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   107
            raise util.Abort(_("path contains illegal component: %s") % path)
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   108
        if '.hg' in path.lower():
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   109
            lparts = [p.lower() for p in parts]
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   110
            for p in '.hg', '.hg.':
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   111
                if p in lparts[1:]:
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   112
                    pos = lparts.index(p)
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   113
                    base = os.path.join(*parts[:pos])
15436
18f1bb70462e cmdutil: don't use repr on paths in pathauditor - it looks strange on windows
Mads Kiilerich <mads@kiilerich.com>
parents: 14984
diff changeset
   114
                    raise util.Abort(_("path '%s' is inside nested repo %r")
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   115
                                     % (path, base))
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   116
15665
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   117
        normparts = util.splitpath(normpath)
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   118
        assert len(parts) == len(normparts)
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   119
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   120
        parts.pop()
15665
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   121
        normparts.pop()
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   122
        prefixes = []
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   123
        while parts:
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   124
            prefix = os.sep.join(parts)
15665
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   125
            normprefix = os.sep.join(normparts)
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   126
            if normprefix in self.auditeddir:
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   127
                break
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   128
            curpath = os.path.join(self.root, prefix)
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   129
            try:
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   130
                st = os.lstat(curpath)
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   131
            except OSError, err:
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   132
                # EINVAL can be raised as invalid path syntax under win32.
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   133
                # They must be ignored for patterns can be checked too.
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   134
                if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   135
                    raise
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   136
            else:
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   137
                if stat.S_ISLNK(st.st_mode):
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   138
                    raise util.Abort(
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   139
                        _('path %r traverses symbolic link %r')
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   140
                        % (path, prefix))
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   141
                elif (stat.S_ISDIR(st.st_mode) and
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   142
                      os.path.isdir(os.path.join(curpath, '.hg'))):
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   143
                    if not self.callback or not self.callback(curpath):
16683
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   144
                        raise util.Abort(_("path '%s' is inside nested "
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   145
                                           "repo %r")
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   146
                                         % (path, prefix))
15665
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   147
            prefixes.append(normprefix)
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   148
            parts.pop()
15665
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   149
            normparts.pop()
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   150
15664
ec8730886f36 pathauditor: use normcase()-ed path for audit result cache
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 14984
diff changeset
   151
        self.audited.add(normpath)
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   152
        # only add prefixes to the cache after checking everything: we don't
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   153
        # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   154
        self.auditeddir.update(prefixes)
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   155
14089
d3f7e110c3c0 opener: introduce an abstact superclass of it
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14068
diff changeset
   156
class abstractopener(object):
d3f7e110c3c0 opener: introduce an abstact superclass of it
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14068
diff changeset
   157
    """Abstract base class; cannot be instantiated"""
d3f7e110c3c0 opener: introduce an abstact superclass of it
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14068
diff changeset
   158
d3f7e110c3c0 opener: introduce an abstact superclass of it
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14068
diff changeset
   159
    def __init__(self, *args, **kwargs):
d3f7e110c3c0 opener: introduce an abstact superclass of it
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14068
diff changeset
   160
        '''Prevent instantiation; don't call this from subclasses.'''
d3f7e110c3c0 opener: introduce an abstact superclass of it
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14068
diff changeset
   161
        raise NotImplementedError('attempted instantiating ' + str(type(self)))
d3f7e110c3c0 opener: introduce an abstact superclass of it
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14068
diff changeset
   162
16455
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   163
    def tryread(self, path):
16479
fc04698fa778 opener: coding style, use triple quotes for doc string
Thomas Arendsen Hein <thomas@intevation.de>
parents: 16455
diff changeset
   164
        '''gracefully return an empty string for missing files'''
16455
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   165
        try:
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   166
            return self.read(path)
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   167
        except IOError, inst:
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   168
            if inst.errno != errno.ENOENT:
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   169
                raise
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   170
        return ""
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   171
14167
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   172
    def read(self, path):
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   173
        fp = self(path, 'rb')
14097
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   174
        try:
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   175
            return fp.read()
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   176
        finally:
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   177
            fp.close()
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   178
14167
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   179
    def write(self, path, data):
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   180
        fp = self(path, 'wb')
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   181
        try:
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   182
            return fp.write(data)
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   183
        finally:
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   184
            fp.close()
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   185
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   186
    def append(self, path, data):
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   187
        fp = self(path, 'ab')
14097
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   188
        try:
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   189
            return fp.write(data)
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   190
        finally:
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   191
            fp.close()
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   192
17161
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   193
    def mkdir(self, path=None):
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   194
        return os.mkdir(self.join(path))
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   195
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   196
    def exists(self, path=None):
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   197
        return os.path.exists(self.join(path))
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   198
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   199
    def isdir(self, path=None):
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   200
        return os.path.isdir(self.join(path))
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   201
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   202
    def makedir(self, path=None, notindexed=True):
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   203
        return util.makedir(self.join(path), notindexed)
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   204
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   205
    def makedirs(self, path=None, mode=None):
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   206
        return util.makedirs(self.join(path), mode)
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   207
14089
d3f7e110c3c0 opener: introduce an abstact superclass of it
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14068
diff changeset
   208
class opener(abstractopener):
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   209
    '''Open files relative to a base directory
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   210
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   211
    This class is used to hide the details of COW semantics and
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   212
    remote file access from higher level code.
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   213
    '''
17157
87e8440964a0 localrepo: use path expansion API via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17104
diff changeset
   214
    def __init__(self, base, audit=True, expand=False):
87e8440964a0 localrepo: use path expansion API via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17104
diff changeset
   215
        if expand:
87e8440964a0 localrepo: use path expansion API via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17104
diff changeset
   216
            base = os.path.realpath(util.expandpath(base))
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   217
        self.base = base
14720
36283a7b6856 opener: add self._audit (issue2862)
Adrian Buehlmann <adrian@cadifra.com>
parents: 14672
diff changeset
   218
        self._audit = audit
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   219
        if audit:
14220
21b8ce4d3331 rename path_auditor to pathauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14167
diff changeset
   220
            self.auditor = pathauditor(base)
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   221
        else:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   222
            self.auditor = util.always
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   223
        self.createmode = None
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   224
        self._trustnlink = None
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   225
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   226
    @util.propertycache
14261
e3649bcca3f6 opener: rename _can_symlink to _cansymlink
Adrian Buehlmann <adrian@cadifra.com>
parents: 14236
diff changeset
   227
    def _cansymlink(self):
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   228
        return util.checklink(self.base)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   229
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   230
    def _fixfilemode(self, name):
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   231
        if self.createmode is None:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   232
            return
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   233
        os.chmod(name, self.createmode & 0666)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   234
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   235
    def __call__(self, path, mode="r", text=False, atomictemp=False):
14720
36283a7b6856 opener: add self._audit (issue2862)
Adrian Buehlmann <adrian@cadifra.com>
parents: 14672
diff changeset
   236
        if self._audit:
36283a7b6856 opener: add self._audit (issue2862)
Adrian Buehlmann <adrian@cadifra.com>
parents: 14672
diff changeset
   237
            r = util.checkosfilename(path)
36283a7b6856 opener: add self._audit (issue2862)
Adrian Buehlmann <adrian@cadifra.com>
parents: 14672
diff changeset
   238
            if r:
36283a7b6856 opener: add self._audit (issue2862)
Adrian Buehlmann <adrian@cadifra.com>
parents: 14672
diff changeset
   239
                raise util.Abort("%s: %r" % (r, path))
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   240
        self.auditor(path)
16199
8181bd808dc5 scmutil: add join method to opener to construct path relative to base
Idan Kamara <idankk86@gmail.com>
parents: 16198
diff changeset
   241
        f = self.join(path)
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   242
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   243
        if not text and "b" not in mode:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   244
            mode += "b" # for that other OS
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   245
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   246
        nlink = -1
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   247
        dirname, basename = os.path.split(f)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   248
        # If basename is empty, then the path is malformed because it points
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   249
        # to a directory. Let the posixfile() call below raise IOError.
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   250
        if basename and mode not in ('r', 'rb'):
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   251
            if atomictemp:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   252
                if not os.path.isdir(dirname):
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   253
                    util.makedirs(dirname, self.createmode)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   254
                return util.atomictempfile(f, mode, self.createmode)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   255
            try:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   256
                if 'w' in mode:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   257
                    util.unlink(f)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   258
                    nlink = 0
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   259
                else:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   260
                    # nlinks() may behave differently for files on Windows
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   261
                    # shares if the file is open.
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   262
                    fd = util.posixfile(f)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   263
                    nlink = util.nlinks(f)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   264
                    if nlink < 1:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   265
                        nlink = 2 # force mktempcopy (issue1922)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   266
                    fd.close()
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   267
            except (OSError, IOError), e:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   268
                if e.errno != errno.ENOENT:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   269
                    raise
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   270
                nlink = 0
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   271
                if not os.path.isdir(dirname):
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   272
                    util.makedirs(dirname, self.createmode)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   273
            if nlink > 0:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   274
                if self._trustnlink is None:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   275
                    self._trustnlink = nlink > 1 or util.checknlink(f)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   276
                if nlink > 1 or not self._trustnlink:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   277
                    util.rename(util.mktempcopy(f), f)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   278
        fp = util.posixfile(f, mode)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   279
        if nlink == 0:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   280
            self._fixfilemode(f)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   281
        return fp
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   282
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   283
    def symlink(self, src, dst):
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   284
        self.auditor(dst)
16199
8181bd808dc5 scmutil: add join method to opener to construct path relative to base
Idan Kamara <idankk86@gmail.com>
parents: 16198
diff changeset
   285
        linkname = self.join(dst)
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   286
        try:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   287
            os.unlink(linkname)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   288
        except OSError:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   289
            pass
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   290
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   291
        dirname = os.path.dirname(linkname)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   292
        if not os.path.exists(dirname):
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   293
            util.makedirs(dirname, self.createmode)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   294
14261
e3649bcca3f6 opener: rename _can_symlink to _cansymlink
Adrian Buehlmann <adrian@cadifra.com>
parents: 14236
diff changeset
   295
        if self._cansymlink:
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   296
            try:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   297
                os.symlink(src, linkname)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   298
            except OSError, err:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   299
                raise OSError(err.errno, _('could not symlink to %r: %s') %
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   300
                              (src, err.strerror), linkname)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   301
        else:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   302
            f = self(dst, "w")
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   303
            f.write(src)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   304
            f.close()
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   305
            self._fixfilemode(dst)
13971
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   306
14404
69b60edfd76c opener: add audit function
Adrian Buehlmann <adrian@cadifra.com>
parents: 14320
diff changeset
   307
    def audit(self, path):
69b60edfd76c opener: add audit function
Adrian Buehlmann <adrian@cadifra.com>
parents: 14320
diff changeset
   308
        self.auditor(path)
69b60edfd76c opener: add audit function
Adrian Buehlmann <adrian@cadifra.com>
parents: 14320
diff changeset
   309
16199
8181bd808dc5 scmutil: add join method to opener to construct path relative to base
Idan Kamara <idankk86@gmail.com>
parents: 16198
diff changeset
   310
    def join(self, path):
17161
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   311
        if path:
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   312
            return os.path.join(self.base, path)
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   313
        else:
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   314
            return self.base
16199
8181bd808dc5 scmutil: add join method to opener to construct path relative to base
Idan Kamara <idankk86@gmail.com>
parents: 16198
diff changeset
   315
14090
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   316
class filteropener(abstractopener):
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   317
    '''Wrapper opener for filtering filenames with a function.'''
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   318
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   319
    def __init__(self, opener, filter):
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   320
        self._filter = filter
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   321
        self._orig = opener
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   322
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   323
    def __call__(self, path, *args, **kwargs):
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   324
        return self._orig(self._filter(path), *args, **kwargs)
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   325
13971
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   326
def canonpath(root, cwd, myname, auditor=None):
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   327
    '''return the canonical path of myname, given cwd and root'''
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   328
    if util.endswithsep(root):
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   329
        rootsep = root
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   330
    else:
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   331
        rootsep = root + os.sep
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   332
    name = myname
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   333
    if not os.path.isabs(name):
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   334
        name = os.path.join(root, cwd, name)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   335
    name = os.path.normpath(name)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   336
    if auditor is None:
14220
21b8ce4d3331 rename path_auditor to pathauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14167
diff changeset
   337
        auditor = pathauditor(root)
13971
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   338
    if name != rootsep and name.startswith(rootsep):
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   339
        name = name[len(rootsep):]
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   340
        auditor(name)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   341
        return util.pconvert(name)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   342
    elif name == root:
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   343
        return ''
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   344
    else:
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   345
        # Determine whether `name' is in the hierarchy at or beneath `root',
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   346
        # by iterating name=dirname(name) until that causes no change (can't
17007
21e18c608b68 scmutil: change canonpath to use util.samefile (issue2167)
Adrian Buehlmann <adrian@cadifra.com>
parents: 16828
diff changeset
   347
        # check name == '/', because that doesn't work on windows). The list
21e18c608b68 scmutil: change canonpath to use util.samefile (issue2167)
Adrian Buehlmann <adrian@cadifra.com>
parents: 16828
diff changeset
   348
        # `rel' holds the reversed list of components making up the relative
21e18c608b68 scmutil: change canonpath to use util.samefile (issue2167)
Adrian Buehlmann <adrian@cadifra.com>
parents: 16828
diff changeset
   349
        # file name we want.
13971
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   350
        rel = []
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   351
        while True:
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   352
            try:
17007
21e18c608b68 scmutil: change canonpath to use util.samefile (issue2167)
Adrian Buehlmann <adrian@cadifra.com>
parents: 16828
diff changeset
   353
                s = util.samefile(name, root)
13971
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   354
            except OSError:
17007
21e18c608b68 scmutil: change canonpath to use util.samefile (issue2167)
Adrian Buehlmann <adrian@cadifra.com>
parents: 16828
diff changeset
   355
                s = False
21e18c608b68 scmutil: change canonpath to use util.samefile (issue2167)
Adrian Buehlmann <adrian@cadifra.com>
parents: 16828
diff changeset
   356
            if s:
13971
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   357
                if not rel:
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   358
                    # name was actually the same as root (maybe a symlink)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   359
                    return ''
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   360
                rel.reverse()
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   361
                name = os.path.join(*rel)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   362
                auditor(name)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   363
                return util.pconvert(name)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   364
            dirname, basename = os.path.split(name)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   365
            rel.append(basename)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   366
            if dirname == name:
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   367
                break
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   368
            name = dirname
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   369
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   370
        raise util.Abort('%s not under root' % myname)
13975
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   371
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   372
def walkrepos(path, followsym=False, seen_dirs=None, recurse=False):
17104
5a9acb0b2086 help: improve hgweb help
Mads Kiilerich <mads@kiilerich.com>
parents: 17037
diff changeset
   373
    '''yield every hg repository under path, always recursively.
5a9acb0b2086 help: improve hgweb help
Mads Kiilerich <mads@kiilerich.com>
parents: 17037
diff changeset
   374
    The recurse flag will only control recursion into repo working dirs'''
13975
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   375
    def errhandler(err):
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   376
        if err.filename == path:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   377
            raise err
14961
5523529bd1af walkrepos: use getattr instead of hasattr for samestat
Augie Fackler <durin42@gmail.com>
parents: 14928
diff changeset
   378
    samestat = getattr(os.path, 'samestat', None)
5523529bd1af walkrepos: use getattr instead of hasattr for samestat
Augie Fackler <durin42@gmail.com>
parents: 14928
diff changeset
   379
    if followsym and samestat is not None:
14227
94985b5a8278 scmutil: rename local function _add_dir_if_not_there
Adrian Buehlmann <adrian@cadifra.com>
parents: 14226
diff changeset
   380
        def adddir(dirlst, dirname):
13975
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   381
            match = False
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   382
            dirstat = os.stat(dirname)
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   383
            for lstdirstat in dirlst:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   384
                if samestat(dirstat, lstdirstat):
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   385
                    match = True
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   386
                    break
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   387
            if not match:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   388
                dirlst.append(dirstat)
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   389
            return not match
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   390
    else:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   391
        followsym = False
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   392
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   393
    if (seen_dirs is None) and followsym:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   394
        seen_dirs = []
14227
94985b5a8278 scmutil: rename local function _add_dir_if_not_there
Adrian Buehlmann <adrian@cadifra.com>
parents: 14226
diff changeset
   395
        adddir(seen_dirs, path)
13975
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   396
    for root, dirs, files in os.walk(path, topdown=True, onerror=errhandler):
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   397
        dirs.sort()
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   398
        if '.hg' in dirs:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   399
            yield root # found a repository
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   400
            qroot = os.path.join(root, '.hg', 'patches')
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   401
            if os.path.isdir(os.path.join(qroot, '.hg')):
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   402
                yield qroot # we have a patch queue repo here
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   403
            if recurse:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   404
                # avoid recursing inside the .hg directory
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   405
                dirs.remove('.hg')
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   406
            else:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   407
                dirs[:] = [] # don't descend further
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   408
        elif followsym:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   409
            newdirs = []
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   410
            for d in dirs:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   411
                fname = os.path.join(root, d)
14227
94985b5a8278 scmutil: rename local function _add_dir_if_not_there
Adrian Buehlmann <adrian@cadifra.com>
parents: 14226
diff changeset
   412
                if adddir(seen_dirs, fname):
13975
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   413
                    if os.path.islink(fname):
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   414
                        for hgname in walkrepos(fname, True, seen_dirs):
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   415
                            yield hgname
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   416
                    else:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   417
                        newdirs.append(d)
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   418
            dirs[:] = newdirs
13984
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   419
14224
f4189866c76c rename scmutil.os_rcpath to osrcpath
Adrian Buehlmann <adrian@cadifra.com>
parents: 14220
diff changeset
   420
def osrcpath():
13985
26335a817dd0 move os_rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13984
diff changeset
   421
    '''return default os-specific hgrc search path'''
14225
f0ca440b5722 rename scmutil.system_rcpath to systemrcpath
Adrian Buehlmann <adrian@cadifra.com>
parents: 14224
diff changeset
   422
    path = systemrcpath()
14226
73cca883370d rename scmutil.user_rcpath to userrcpath
Adrian Buehlmann <adrian@cadifra.com>
parents: 14225
diff changeset
   423
    path.extend(userrcpath())
13985
26335a817dd0 move os_rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13984
diff changeset
   424
    path = [os.path.normpath(f) for f in path]
26335a817dd0 move os_rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13984
diff changeset
   425
    return path
26335a817dd0 move os_rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13984
diff changeset
   426
13984
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   427
_rcpath = None
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   428
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   429
def rcpath():
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   430
    '''return hgrc search path. if env var HGRCPATH is set, use it.
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   431
    for each item in path, if directory, use files ending in .rc,
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   432
    else use item.
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   433
    make HGRCPATH empty to only look in .hg/hgrc of current repo.
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   434
    if no HGRCPATH, use default os-specific path.'''
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   435
    global _rcpath
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   436
    if _rcpath is None:
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   437
        if 'HGRCPATH' in os.environ:
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   438
            _rcpath = []
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   439
            for p in os.environ['HGRCPATH'].split(os.pathsep):
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   440
                if not p:
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   441
                    continue
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   442
                p = util.expandpath(p)
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   443
                if os.path.isdir(p):
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   444
                    for f, kind in osutil.listdir(p):
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   445
                        if f.endswith('.rc'):
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   446
                            _rcpath.append(os.path.join(p, f))
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   447
                else:
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   448
                    _rcpath.append(p)
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   449
        else:
14224
f4189866c76c rename scmutil.os_rcpath to osrcpath
Adrian Buehlmann <adrian@cadifra.com>
parents: 14220
diff changeset
   450
            _rcpath = osrcpath()
13984
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   451
    return _rcpath
13986
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   452
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   453
if os.name != 'nt':
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   454
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   455
    def rcfiles(path):
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   456
        rcs = [os.path.join(path, 'hgrc')]
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   457
        rcdir = os.path.join(path, 'hgrc.d')
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   458
        try:
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   459
            rcs.extend([os.path.join(rcdir, f)
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   460
                        for f, kind in osutil.listdir(rcdir)
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   461
                        if f.endswith(".rc")])
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   462
        except OSError:
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   463
            pass
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   464
        return rcs
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   465
14225
f0ca440b5722 rename scmutil.system_rcpath to systemrcpath
Adrian Buehlmann <adrian@cadifra.com>
parents: 14224
diff changeset
   466
    def systemrcpath():
13986
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   467
        path = []
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents: 16379
diff changeset
   468
        if sys.platform == 'plan9':
16436
e98460f6089d scmutil: fix systemrcpath regression introduced in f5dd179bfa4a
Wolfgang Treutterer <Wolfgang.Treutterer@ipp.mpg.de>
parents: 16390
diff changeset
   469
            root = 'lib/mercurial'
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents: 16379
diff changeset
   470
        else:
16436
e98460f6089d scmutil: fix systemrcpath regression introduced in f5dd179bfa4a
Wolfgang Treutterer <Wolfgang.Treutterer@ipp.mpg.de>
parents: 16390
diff changeset
   471
            root = 'etc/mercurial'
13986
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   472
        # old mod_python does not set sys.argv
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   473
        if len(getattr(sys, 'argv', [])) > 0:
14527
5867bd6e7cf5 scmutil: improve path calculation for install-relative RC files (issue2841)
Matt Mackall <mpm@selenic.com>
parents: 14484
diff changeset
   474
            p = os.path.dirname(os.path.dirname(sys.argv[0]))
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents: 16379
diff changeset
   475
            path.extend(rcfiles(os.path.join(p, root)))
16436
e98460f6089d scmutil: fix systemrcpath regression introduced in f5dd179bfa4a
Wolfgang Treutterer <Wolfgang.Treutterer@ipp.mpg.de>
parents: 16390
diff changeset
   476
        path.extend(rcfiles('/' + root))
13986
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   477
        return path
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   478
14226
73cca883370d rename scmutil.user_rcpath to userrcpath
Adrian Buehlmann <adrian@cadifra.com>
parents: 14225
diff changeset
   479
    def userrcpath():
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents: 16379
diff changeset
   480
        if sys.platform == 'plan9':
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents: 16379
diff changeset
   481
            return [os.environ['home'] + '/lib/hgrc']
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents: 16379
diff changeset
   482
        else:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents: 16379
diff changeset
   483
            return [os.path.expanduser('~/.hgrc')]
13986
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   484
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   485
else:
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   486
16808
572d5e254f20 scmutil: use _winreg.HKEY_LOCAL_MACHINE
Adrian Buehlmann <adrian@cadifra.com>
parents: 16791
diff changeset
   487
    import _winreg
13986
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   488
14225
f0ca440b5722 rename scmutil.system_rcpath to systemrcpath
Adrian Buehlmann <adrian@cadifra.com>
parents: 14224
diff changeset
   489
    def systemrcpath():
13986
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   490
        '''return default os-specific hgrc search path'''
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   491
        rcpath = []
14236
e949a008999d rename util.executable_path to executablepath
Adrian Buehlmann <adrian@cadifra.com>
parents: 14230
diff changeset
   492
        filename = util.executablepath()
13986
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   493
        # Use mercurial.ini found in directory with hg.exe
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   494
        progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   495
        if os.path.isfile(progrc):
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   496
            rcpath.append(progrc)
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   497
            return rcpath
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   498
        # Use hgrc.d found in directory with hg.exe
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   499
        progrcd = os.path.join(os.path.dirname(filename), 'hgrc.d')
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   500
        if os.path.isdir(progrcd):
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   501
            for f, kind in osutil.listdir(progrcd):
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   502
                if f.endswith('.rc'):
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   503
                    rcpath.append(os.path.join(progrcd, f))
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   504
            return rcpath
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   505
        # else look for a system rcpath in the registry
14230
d51630301241 rename util.lookup_reg to lookupreg
Adrian Buehlmann <adrian@cadifra.com>
parents: 14227
diff changeset
   506
        value = util.lookupreg('SOFTWARE\\Mercurial', None,
16808
572d5e254f20 scmutil: use _winreg.HKEY_LOCAL_MACHINE
Adrian Buehlmann <adrian@cadifra.com>
parents: 16791
diff changeset
   507
                               _winreg.HKEY_LOCAL_MACHINE)
13986
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   508
        if not isinstance(value, str) or not value:
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   509
            return rcpath
16068
73aaff46175b use util.localpath() instead of 'str.replace()' to unify path conversion
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15993
diff changeset
   510
        value = util.localpath(value)
13986
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   511
        for p in value.split(os.pathsep):
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   512
            if p.lower().endswith('mercurial.ini'):
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   513
                rcpath.append(p)
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   514
            elif os.path.isdir(p):
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   515
                for f, kind in osutil.listdir(p):
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   516
                    if f.endswith('.rc'):
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   517
                        rcpath.append(os.path.join(p, f))
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   518
        return rcpath
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   519
14226
73cca883370d rename scmutil.user_rcpath to userrcpath
Adrian Buehlmann <adrian@cadifra.com>
parents: 14225
diff changeset
   520
    def userrcpath():
13986
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   521
        '''return os-specific hgrc search path to the user dir'''
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   522
        home = os.path.expanduser('~')
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   523
        path = [os.path.join(home, 'mercurial.ini'),
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   524
                os.path.join(home, '.hgrc')]
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   525
        userprofile = os.environ.get('USERPROFILE')
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   526
        if userprofile:
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   527
            path.append(os.path.join(userprofile, 'mercurial.ini'))
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   528
            path.append(os.path.join(userprofile, '.hgrc'))
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   529
        return path
14319
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   530
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   531
def revsingle(repo, revspec, default='.'):
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   532
    if not revspec:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   533
        return repo[default]
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   534
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   535
    l = revrange(repo, [revspec])
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   536
    if len(l) < 1:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   537
        raise util.Abort(_('empty revision set'))
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   538
    return repo[l[-1]]
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   539
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   540
def revpair(repo, revs):
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   541
    if not revs:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   542
        return repo.dirstate.p1(), None
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   543
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   544
    l = revrange(repo, revs)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   545
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   546
    if len(l) == 0:
16790
2a0efa1112ac revpair: handle odd ranges (issue3474)
Matt Mackall <mpm@selenic.com>
parents: 16479
diff changeset
   547
        if revs:
2a0efa1112ac revpair: handle odd ranges (issue3474)
Matt Mackall <mpm@selenic.com>
parents: 16479
diff changeset
   548
            raise util.Abort(_('empty revision range'))
14319
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   549
        return repo.dirstate.p1(), None
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   550
16790
2a0efa1112ac revpair: handle odd ranges (issue3474)
Matt Mackall <mpm@selenic.com>
parents: 16479
diff changeset
   551
    if len(l) == 1 and len(revs) == 1 and _revrangesep not in revs[0]:
14319
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   552
        return repo.lookup(l[0]), None
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   553
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   554
    return repo.lookup(l[0]), repo.lookup(l[-1])
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   555
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   556
_revrangesep = ':'
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   557
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   558
def revrange(repo, revs):
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   559
    """Yield revision as strings from a list of revision specifications."""
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   560
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   561
    def revfix(repo, val, defval):
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   562
        if not val and val != 0 and defval is not None:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   563
            return defval
16379
5cbfbb838198 scmutil: use context instead of lookup
Matt Mackall <mpm@selenic.com>
parents: 16208
diff changeset
   564
        return repo[val].rev()
14319
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   565
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   566
    seen, l = set(), []
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   567
    for spec in revs:
16390
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   568
        if l and not seen:
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   569
            seen = set(l)
14319
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   570
        # attempt to parse old-style ranges first to deal with
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   571
        # things like old-tag which contain query metacharacters
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   572
        try:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   573
            if isinstance(spec, int):
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   574
                seen.add(spec)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   575
                l.append(spec)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   576
                continue
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   577
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   578
            if _revrangesep in spec:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   579
                start, end = spec.split(_revrangesep, 1)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   580
                start = revfix(repo, start, 0)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   581
                end = revfix(repo, end, len(repo) - 1)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   582
                step = start > end and -1 or 1
16390
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   583
                if not seen and not l:
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   584
                    # by far the most common case: revs = ["-1:0"]
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   585
                    l = range(start, end + step, step)
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   586
                    # defer syncing seen until next iteration
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   587
                    continue
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   588
                newrevs = set(xrange(start, end + step, step))
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   589
                if seen:
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   590
                    newrevs.difference_update(seen)
16814
9da5a2864f3f scmutil: seen.union should be seen.update (issue3476)
Bryan O'Sullivan <bryano@fb.com>
parents: 16790
diff changeset
   591
                    seen.update(newrevs)
16390
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   592
                else:
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   593
                    seen = newrevs
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   594
                l.extend(sorted(newrevs, reverse=start > end))
14319
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   595
                continue
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   596
            elif spec and spec in repo: # single unquoted rev
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   597
                rev = revfix(repo, spec, None)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   598
                if rev in seen:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   599
                    continue
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   600
                seen.add(rev)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   601
                l.append(rev)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   602
                continue
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   603
        except error.RepoLookupError:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   604
            pass
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   605
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   606
        # fall through to new-style queries if old-style fails
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   607
        m = revset.match(repo.ui, spec)
17037
419966126a05 scmutil: speed up new-style range extension
Bryan O'Sullivan <bryano@fb.com>
parents: 17007
diff changeset
   608
        dl = [r for r in m(repo, xrange(len(repo))) if r not in seen]
419966126a05 scmutil: speed up new-style range extension
Bryan O'Sullivan <bryano@fb.com>
parents: 17007
diff changeset
   609
        l.extend(dl)
419966126a05 scmutil: speed up new-style range extension
Bryan O'Sullivan <bryano@fb.com>
parents: 17007
diff changeset
   610
        seen.update(dl)
14319
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   611
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   612
    return l
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   613
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   614
def expandpats(pats):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   615
    if not util.expandglobs:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   616
        return list(pats)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   617
    ret = []
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   618
    for p in pats:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   619
        kind, name = matchmod._patsplit(p, None)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   620
        if kind is None:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   621
            try:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   622
                globbed = glob.glob(name)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   623
            except re.error:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   624
                globbed = [name]
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   625
            if globbed:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   626
                ret.extend(globbed)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   627
                continue
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   628
        ret.append(p)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   629
    return ret
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   630
16171
336e61875335 graphlog: restore FILE glob expansion on Windows
Patrick Mezard <patrick@mezard.eu>
parents: 16167
diff changeset
   631
def matchandpats(ctx, pats=[], opts={}, globbed=False, default='relpath'):
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   632
    if pats == ("",):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   633
        pats = []
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   634
    if not globbed and default == 'relpath':
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   635
        pats = expandpats(pats or [])
14670
19197fa4c41c scmutil: match now accepts a context or a repo
Matt Mackall <mpm@selenic.com>
parents: 14669
diff changeset
   636
19197fa4c41c scmutil: match now accepts a context or a repo
Matt Mackall <mpm@selenic.com>
parents: 14669
diff changeset
   637
    m = ctx.match(pats, opts.get('include'), opts.get('exclude'),
14669
2d2604adfdd6 context: add a match builder method
Matt Mackall <mpm@selenic.com>
parents: 14527
diff changeset
   638
                         default)
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   639
    def badfn(f, msg):
14671
35c2cc322ba8 scmutil: switch match users to supplying contexts
Matt Mackall <mpm@selenic.com>
parents: 14670
diff changeset
   640
        ctx._repo.ui.warn("%s: %s\n" % (m.rel(f), msg))
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   641
    m.bad = badfn
16171
336e61875335 graphlog: restore FILE glob expansion on Windows
Patrick Mezard <patrick@mezard.eu>
parents: 16167
diff changeset
   642
    return m, pats
336e61875335 graphlog: restore FILE glob expansion on Windows
Patrick Mezard <patrick@mezard.eu>
parents: 16167
diff changeset
   643
336e61875335 graphlog: restore FILE glob expansion on Windows
Patrick Mezard <patrick@mezard.eu>
parents: 16167
diff changeset
   644
def match(ctx, pats=[], opts={}, globbed=False, default='relpath'):
336e61875335 graphlog: restore FILE glob expansion on Windows
Patrick Mezard <patrick@mezard.eu>
parents: 16167
diff changeset
   645
    return matchandpats(ctx, pats, opts, globbed, default)[0]
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   646
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   647
def matchall(repo):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   648
    return matchmod.always(repo.root, repo.getcwd())
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   649
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   650
def matchfiles(repo, files):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   651
    return matchmod.exact(repo.root, repo.getcwd(), files)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   652
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   653
def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   654
    if dry_run is None:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   655
        dry_run = opts.get('dry_run')
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   656
    if similarity is None:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   657
        similarity = float(opts.get('similarity') or 0)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   658
    # we'd use status here, except handling of symlinks and ignore is tricky
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   659
    added, unknown, deleted, removed = [], [], [], []
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   660
    audit_path = pathauditor(repo.root)
14671
35c2cc322ba8 scmutil: switch match users to supplying contexts
Matt Mackall <mpm@selenic.com>
parents: 14670
diff changeset
   661
    m = match(repo[None], pats, opts)
16167
94a8396c9305 addremove: return 1 if we failed to handle any explicit files
Matt Mackall <mpm@selenic.com>
parents: 16115
diff changeset
   662
    rejected = []
94a8396c9305 addremove: return 1 if we failed to handle any explicit files
Matt Mackall <mpm@selenic.com>
parents: 16115
diff changeset
   663
    m.bad = lambda x, y: rejected.append(x)
94a8396c9305 addremove: return 1 if we failed to handle any explicit files
Matt Mackall <mpm@selenic.com>
parents: 16115
diff changeset
   664
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   665
    for abs in repo.walk(m):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   666
        target = repo.wjoin(abs)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   667
        good = True
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   668
        try:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   669
            audit_path(abs)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   670
        except (OSError, util.Abort):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   671
            good = False
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   672
        rel = m.rel(abs)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   673
        exact = m.exact(abs)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   674
        if good and abs not in repo.dirstate:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   675
            unknown.append(abs)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   676
            if repo.ui.verbose or not exact:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   677
                repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
16683
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   678
        elif (repo.dirstate[abs] != 'r' and
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   679
              (not good or not os.path.lexists(target) or
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   680
               (os.path.isdir(target) and not os.path.islink(target)))):
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   681
            deleted.append(abs)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   682
            if repo.ui.verbose or not exact:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   683
                repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   684
        # for finding renames
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   685
        elif repo.dirstate[abs] == 'r':
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   686
            removed.append(abs)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   687
        elif repo.dirstate[abs] == 'a':
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   688
            added.append(abs)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   689
    copies = {}
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   690
    if similarity > 0:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   691
        for old, new, score in similar.findrenames(repo,
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   692
                added + unknown, removed + deleted, similarity):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   693
            if repo.ui.verbose or not m.exact(old) or not m.exact(new):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   694
                repo.ui.status(_('recording removal of %s as rename to %s '
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   695
                                 '(%d%% similar)\n') %
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   696
                               (m.rel(old), m.rel(new), score * 100))
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   697
            copies[new] = old
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   698
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   699
    if not dry_run:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   700
        wctx = repo[None]
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   701
        wlock = repo.wlock()
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   702
        try:
14435
5f6090e559fa context: make forget work like commands.forget
Matt Mackall <mpm@selenic.com>
parents: 14404
diff changeset
   703
            wctx.forget(deleted)
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   704
            wctx.add(unknown)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   705
            for new, old in copies.iteritems():
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   706
                wctx.copy(old, new)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   707
        finally:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   708
            wlock.release()
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   709
16167
94a8396c9305 addremove: return 1 if we failed to handle any explicit files
Matt Mackall <mpm@selenic.com>
parents: 16115
diff changeset
   710
    for f in rejected:
94a8396c9305 addremove: return 1 if we failed to handle any explicit files
Matt Mackall <mpm@selenic.com>
parents: 16115
diff changeset
   711
        if f in m.files():
94a8396c9305 addremove: return 1 if we failed to handle any explicit files
Matt Mackall <mpm@selenic.com>
parents: 16115
diff changeset
   712
            return 1
94a8396c9305 addremove: return 1 if we failed to handle any explicit files
Matt Mackall <mpm@selenic.com>
parents: 16115
diff changeset
   713
    return 0
94a8396c9305 addremove: return 1 if we failed to handle any explicit files
Matt Mackall <mpm@selenic.com>
parents: 16115
diff changeset
   714
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   715
def updatedir(ui, repo, patches, similarity=0):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   716
    '''Update dirstate after patch application according to metadata'''
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   717
    if not patches:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   718
        return []
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   719
    copies = []
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   720
    removes = set()
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   721
    cfiles = patches.keys()
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   722
    cwd = repo.getcwd()
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   723
    if cwd:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   724
        cfiles = [util.pathto(repo.root, cwd, f) for f in patches.keys()]
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   725
    for f in patches:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   726
        gp = patches[f]
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   727
        if not gp:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   728
            continue
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   729
        if gp.op == 'RENAME':
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   730
            copies.append((gp.oldpath, gp.path))
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   731
            removes.add(gp.oldpath)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   732
        elif gp.op == 'COPY':
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   733
            copies.append((gp.oldpath, gp.path))
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   734
        elif gp.op == 'DELETE':
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   735
            removes.add(gp.path)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   736
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   737
    wctx = repo[None]
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   738
    for src, dst in copies:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   739
        dirstatecopy(ui, repo, wctx, src, dst, cwd=cwd)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   740
    if (not similarity) and removes:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   741
        wctx.remove(sorted(removes), True)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   742
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   743
    for f in patches:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   744
        gp = patches[f]
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   745
        if gp and gp.mode:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   746
            islink, isexec = gp.mode
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   747
            dst = repo.wjoin(gp.path)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   748
            # patch won't create empty files
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   749
            if gp.op == 'ADD' and not os.path.lexists(dst):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   750
                flags = (isexec and 'x' or '') + (islink and 'l' or '')
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   751
                repo.wwrite(gp.path, '', flags)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   752
            util.setflags(dst, islink, isexec)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   753
    addremove(repo, cfiles, similarity=similarity)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   754
    files = patches.keys()
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   755
    files.extend([r for r in removes if r not in files])
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   756
    return sorted(files)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   757
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   758
def dirstatecopy(ui, repo, wctx, src, dst, dryrun=False, cwd=None):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   759
    """Update the dirstate to reflect the intent of copying src to dst. For
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   760
    different reasons it might not end with dst being marked as copied from src.
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   761
    """
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   762
    origsrc = repo.dirstate.copied(src) or src
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   763
    if dst == origsrc: # copying back a copy?
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   764
        if repo.dirstate[dst] not in 'mn' and not dryrun:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   765
            repo.dirstate.normallookup(dst)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   766
    else:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   767
        if repo.dirstate[origsrc] == 'a' and origsrc == src:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   768
            if not ui.quiet:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   769
                ui.warn(_("%s has not been committed yet, so no copy "
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   770
                          "data will be stored for %s.\n")
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   771
                        % (repo.pathto(origsrc, cwd), repo.pathto(dst, cwd)))
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   772
            if repo.dirstate[dst] in '?r' and not dryrun:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   773
                wctx.add([dst])
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   774
        elif not dryrun:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   775
            wctx.copy(origsrc, dst)
14482
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   776
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   777
def readrequires(opener, supported):
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   778
    '''Reads and parses .hg/requires and checks if all entries found
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   779
    are in the list of supported features.'''
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   780
    requirements = set(opener.read("requires").splitlines())
14746
72e4fcb43227 requirements: show all missing features in the error message.
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 14720
diff changeset
   781
    missings = []
14482
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   782
    for r in requirements:
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   783
        if r not in supported:
14484
4582a4dd1817 requires: note apparent corruption
Matt Mackall <mpm@selenic.com>
parents: 14483
diff changeset
   784
            if not r or not r[0].isalnum():
4582a4dd1817 requires: note apparent corruption
Matt Mackall <mpm@selenic.com>
parents: 14483
diff changeset
   785
                raise error.RequirementError(_(".hg/requires file is corrupt"))
14746
72e4fcb43227 requirements: show all missing features in the error message.
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 14720
diff changeset
   786
            missings.append(r)
72e4fcb43227 requirements: show all missing features in the error message.
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 14720
diff changeset
   787
    missings.sort()
72e4fcb43227 requirements: show all missing features in the error message.
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 14720
diff changeset
   788
    if missings:
16683
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   789
        raise error.RequirementError(
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   790
            _("unknown repository format: requires features '%s' (upgrade "
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   791
              "Mercurial)") % "', '".join(missings))
14482
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   792
    return requirements
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   793
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   794
class filecacheentry(object):
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   795
    def __init__(self, path):
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   796
        self.path = path
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   797
        self.cachestat = filecacheentry.stat(self.path)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   798
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   799
        if self.cachestat:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   800
            self._cacheable = self.cachestat.cacheable()
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   801
        else:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   802
            # None means we don't know yet
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   803
            self._cacheable = None
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   804
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   805
    def refresh(self):
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   806
        if self.cacheable():
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   807
            self.cachestat = filecacheentry.stat(self.path)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   808
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   809
    def cacheable(self):
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   810
        if self._cacheable is not None:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   811
            return self._cacheable
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   812
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   813
        # we don't know yet, assume it is for now
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   814
        return True
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   815
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   816
    def changed(self):
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   817
        # no point in going further if we can't cache it
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   818
        if not self.cacheable():
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   819
            return True
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   820
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   821
        newstat = filecacheentry.stat(self.path)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   822
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   823
        # we may not know if it's cacheable yet, check again now
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   824
        if newstat and self._cacheable is None:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   825
            self._cacheable = newstat.cacheable()
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   826
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   827
            # check again
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   828
            if not self._cacheable:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   829
                return True
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   830
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   831
        if self.cachestat != newstat:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   832
            self.cachestat = newstat
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   833
            return True
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   834
        else:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   835
            return False
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   836
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   837
    @staticmethod
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   838
    def stat(path):
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   839
        try:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   840
            return util.cachestat(path)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   841
        except OSError, e:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   842
            if e.errno != errno.ENOENT:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   843
                raise
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   844
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   845
class filecache(object):
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   846
    '''A property like decorator that tracks a file under .hg/ for updates.
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   847
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   848
    Records stat info when called in _filecache.
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   849
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   850
    On subsequent calls, compares old stat info with new info, and recreates
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   851
    the object when needed, updating the new stat info in _filecache.
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   852
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   853
    Mercurial either atomic renames or appends for files under .hg,
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   854
    so to ensure the cache is reliable we need the filesystem to be able
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   855
    to tell us if a file has been replaced. If it can't, we fallback to
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   856
    recreating the object on every call (essentially the same behaviour as
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   857
    propertycache).'''
16198
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   858
    def __init__(self, path):
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   859
        self.path = path
16198
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   860
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   861
    def join(self, obj, fname):
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   862
        """Used to compute the runtime path of the cached file.
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   863
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   864
        Users should subclass filecache and provide their own version of this
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   865
        function to call the appropriate join function on 'obj' (an instance
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   866
        of the class that its member function was decorated).
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   867
        """
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   868
        return obj.join(fname)
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   869
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   870
    def __call__(self, func):
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   871
        self.func = func
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   872
        self.name = func.__name__
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   873
        return self
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   874
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   875
    def __get__(self, obj, type=None):
16115
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   876
        # do we need to check if the file changed?
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   877
        if self.name in obj.__dict__:
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   878
            return obj.__dict__[self.name]
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   879
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   880
        entry = obj._filecache.get(self.name)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   881
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   882
        if entry:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   883
            if entry.changed():
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   884
                entry.obj = self.func(obj)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   885
        else:
16198
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   886
            path = self.join(obj, self.path)
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   887
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   888
            # We stat -before- creating the object so our cache doesn't lie if
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   889
            # a writer modified between the time we read and stat
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   890
            entry = filecacheentry(path)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   891
            entry.obj = self.func(obj)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   892
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   893
            obj._filecache[self.name] = entry
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   894
16115
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   895
        obj.__dict__[self.name] = entry.obj
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   896
        return entry.obj
16115
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   897
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   898
    def __set__(self, obj, value):
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   899
        if self.name in obj._filecache:
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   900
            obj._filecache[self.name].obj = value # update cached copy
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   901
        obj.__dict__[self.name] = value # update copy returned by obj.x
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   902
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   903
    def __delete__(self, obj):
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   904
        try:
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   905
            del obj.__dict__[self.name]
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   906
        except KeyError:
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   907
            raise AttributeError, self.name