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