mercurial/scmutil.py
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
Mon, 15 Apr 2013 01:22:15 +0900
changeset 18948 2f05fa162316
parent 18945 e75b72fffdfe
child 18949 138978f20180
permissions -rw-r--r--
localrepo: use "vfs.rename()" instead of "util.rename()"
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 _
18466
ac0c12123743 log: remove any ancestors of nullrev (issue3772)
Sean Farley <sean.michael.farley@gmail.com>
parents: 18450
diff changeset
     9
from mercurial.node import nullrev
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents: 18898
diff changeset
    10
import util, error, osutil, revset, similar, encoding, phases, parsers
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
    11
import match as matchmod
18690
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents: 18678
diff changeset
    12
import os, errno, re, stat, glob
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents: 18678
diff changeset
    13
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents: 18678
diff changeset
    14
if os.name == 'nt':
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents: 18678
diff changeset
    15
    import scmwindows as scmplatform
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents: 18678
diff changeset
    16
else:
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents: 18678
diff changeset
    17
    import scmposix as scmplatform
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents: 18678
diff changeset
    18
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents: 18678
diff changeset
    19
systemrcpath = scmplatform.systemrcpath
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents: 18678
diff changeset
    20
userrcpath = scmplatform.userrcpath
13962
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    21
17248
6ffb35b2284c discovery: add extinct changesets to outgoing.excluded
Patrick Mezard <patrick@mezard.eu>
parents: 17201
diff changeset
    22
def nochangesfound(ui, repo, excluded=None):
6ffb35b2284c discovery: add extinct changesets to outgoing.excluded
Patrick Mezard <patrick@mezard.eu>
parents: 17201
diff changeset
    23
    '''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
    24
    nodes excluded from the push/pull.
6ffb35b2284c discovery: add extinct changesets to outgoing.excluded
Patrick Mezard <patrick@mezard.eu>
parents: 17201
diff changeset
    25
    '''
6ffb35b2284c discovery: add extinct changesets to outgoing.excluded
Patrick Mezard <patrick@mezard.eu>
parents: 17201
diff changeset
    26
    secretlist = []
6ffb35b2284c discovery: add extinct changesets to outgoing.excluded
Patrick Mezard <patrick@mezard.eu>
parents: 17201
diff changeset
    27
    if excluded:
6ffb35b2284c discovery: add extinct changesets to outgoing.excluded
Patrick Mezard <patrick@mezard.eu>
parents: 17201
diff changeset
    28
        for n in excluded:
18617
227479f61db9 outgoing: fix possible filtering crash in outgoing (issue3814)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18466
diff changeset
    29
            if n not in repo:
227479f61db9 outgoing: fix possible filtering crash in outgoing (issue3814)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18466
diff changeset
    30
                # discovery should not have included the filtered revision,
227479f61db9 outgoing: fix possible filtering crash in outgoing (issue3814)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18466
diff changeset
    31
                # we have to explicitly exclude it until discovery is cleanup.
227479f61db9 outgoing: fix possible filtering crash in outgoing (issue3814)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18466
diff changeset
    32
                continue
17248
6ffb35b2284c discovery: add extinct changesets to outgoing.excluded
Patrick Mezard <patrick@mezard.eu>
parents: 17201
diff changeset
    33
            ctx = repo[n]
6ffb35b2284c discovery: add extinct changesets to outgoing.excluded
Patrick Mezard <patrick@mezard.eu>
parents: 17201
diff changeset
    34
            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
    35
                secretlist.append(n)
6ffb35b2284c discovery: add extinct changesets to outgoing.excluded
Patrick Mezard <patrick@mezard.eu>
parents: 17201
diff changeset
    36
15993
0b05e0bfdc1c scmutil: unify some 'no changes found' messages
Matt Mackall <mpm@selenic.com>
parents: 15797
diff changeset
    37
    if secretlist:
0b05e0bfdc1c scmutil: unify some 'no changes found' messages
Matt Mackall <mpm@selenic.com>
parents: 15797
diff changeset
    38
        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
    39
                  % len(secretlist))
0b05e0bfdc1c scmutil: unify some 'no changes found' messages
Matt Mackall <mpm@selenic.com>
parents: 15797
diff changeset
    40
    else:
0b05e0bfdc1c scmutil: unify some 'no changes found' messages
Matt Mackall <mpm@selenic.com>
parents: 15797
diff changeset
    41
        ui.status(_("no changes found\n"))
0b05e0bfdc1c scmutil: unify some 'no changes found' messages
Matt Mackall <mpm@selenic.com>
parents: 15797
diff changeset
    42
17821
361ab1e2086f scmutil: add bad character checking to checknewlabel
Kevin Bullock <kbullock@ringworld.org>
parents: 17817
diff changeset
    43
def checknewlabel(repo, lbl, kind):
17817
b17be267b59c scmutil: add function to validate new branch, tag, and bookmark names
Kevin Bullock <kbullock@ringworld.org>
parents: 17768
diff changeset
    44
    if lbl in ['tip', '.', 'null']:
b17be267b59c scmutil: add function to validate new branch, tag, and bookmark names
Kevin Bullock <kbullock@ringworld.org>
parents: 17768
diff changeset
    45
        raise util.Abort(_("the name '%s' is reserved") % lbl)
17821
361ab1e2086f scmutil: add bad character checking to checknewlabel
Kevin Bullock <kbullock@ringworld.org>
parents: 17817
diff changeset
    46
    for c in (':', '\0', '\n', '\r'):
361ab1e2086f scmutil: add bad character checking to checknewlabel
Kevin Bullock <kbullock@ringworld.org>
parents: 17817
diff changeset
    47
        if c in lbl:
17850
71c1513fd560 scmutil: generalize message to make it more i18n-friendly
Wagner Bruna <wbruna@yahoo.com>
parents: 17846
diff changeset
    48
            raise util.Abort(_("%r cannot be used in a name") % c)
18566
341868ef0cf6 bookmark: don't allow integers as bookmark/branch/tag names
Durham Goode <durham@fb.com>
parents: 18560
diff changeset
    49
    try:
341868ef0cf6 bookmark: don't allow integers as bookmark/branch/tag names
Durham Goode <durham@fb.com>
parents: 18560
diff changeset
    50
        int(lbl)
341868ef0cf6 bookmark: don't allow integers as bookmark/branch/tag names
Durham Goode <durham@fb.com>
parents: 18560
diff changeset
    51
        raise util.Abort(_("a %s cannot have an integer as its name") % kind)
341868ef0cf6 bookmark: don't allow integers as bookmark/branch/tag names
Durham Goode <durham@fb.com>
parents: 18560
diff changeset
    52
    except ValueError:
341868ef0cf6 bookmark: don't allow integers as bookmark/branch/tag names
Durham Goode <durham@fb.com>
parents: 18560
diff changeset
    53
        pass
17817
b17be267b59c scmutil: add function to validate new branch, tag, and bookmark names
Kevin Bullock <kbullock@ringworld.org>
parents: 17768
diff changeset
    54
13974
23f2736abce3 move checkfilename from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13973
diff changeset
    55
def checkfilename(f):
23f2736abce3 move checkfilename from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13973
diff changeset
    56
    '''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
    57
    if '\r' in f or '\n' in f:
23f2736abce3 move checkfilename from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13973
diff changeset
    58
        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
    59
13962
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    60
def checkportable(ui, f):
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    61
    '''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
    62
    checkfilename(f)
14138
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    63
    abort, warn = checkportabilityalert(ui)
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    64
    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
    65
        msg = util.checkwinfilename(f)
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    66
        if msg:
14138
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    67
            msg = "%s: %r" % (msg, f)
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    68
            if abort:
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    69
                raise util.Abort(msg)
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    70
            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
    71
14067
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    72
def checkportabilityalert(ui):
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    73
    '''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
    74
    non-portable filenames'''
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    75
    val = ui.config('ui', 'portablefilenames', 'warn')
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    76
    lval = val.lower()
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    77
    bval = util.parsebool(val)
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    78
    abort = os.name == 'nt' or lval == 'abort'
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    79
    warn = bval or lval == 'warn'
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    80
    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
    81
        raise error.ConfigError(
8b252e826c68 add: introduce a warning message for non-portable filenames (issue2756) (BC)
Adrian Buehlmann <adrian@cadifra.com>
parents:
diff changeset
    82
            _("ui.portablefilenames value is invalid ('%s')") % val)
14067
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    83
    return abort, warn
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    84
14138
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    85
class casecollisionauditor(object):
17201
afd75476939e scmutil: 25% speedup in casecollisionauditor
Joshua Redstone <joshua.redstone@fb.com>
parents: 17161
diff changeset
    86
    def __init__(self, ui, abort, dirstate):
14138
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    87
        self._ui = ui
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    88
        self._abort = abort
17201
afd75476939e scmutil: 25% speedup in casecollisionauditor
Joshua Redstone <joshua.redstone@fb.com>
parents: 17161
diff changeset
    89
        allfiles = '\0'.join(dirstate._map)
afd75476939e scmutil: 25% speedup in casecollisionauditor
Joshua Redstone <joshua.redstone@fb.com>
parents: 17161
diff changeset
    90
        self._loweredfiles = set(encoding.lower(allfiles).split('\0'))
afd75476939e scmutil: 25% speedup in casecollisionauditor
Joshua Redstone <joshua.redstone@fb.com>
parents: 17161
diff changeset
    91
        self._dirstate = dirstate
afd75476939e scmutil: 25% speedup in casecollisionauditor
Joshua Redstone <joshua.redstone@fb.com>
parents: 17161
diff changeset
    92
        # 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
    93
        # 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
    94
        # same filename twice.
afd75476939e scmutil: 25% speedup in casecollisionauditor
Joshua Redstone <joshua.redstone@fb.com>
parents: 17161
diff changeset
    95
        self._newfiles = set()
14067
e88a4958a6b7 scmutil: refactor ui.portablefilenames processing
Kevin Gessner <kevin@kevingessner.com>
parents: 13986
diff changeset
    96
14138
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
    97
    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
    98
        fl = encoding.lower(f)
17201
afd75476939e scmutil: 25% speedup in casecollisionauditor
Joshua Redstone <joshua.redstone@fb.com>
parents: 17161
diff changeset
    99
        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
   100
            f not in self._newfiles):
14138
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
   101
            msg = _('possible case-folding collision for %s') % f
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
   102
            if self._abort:
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
   103
                raise util.Abort(msg)
c18204fd35b0 scmutil: introduce casecollisionauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14097
diff changeset
   104
            self._ui.warn(_("warning: %s\n") % msg)
17201
afd75476939e scmutil: 25% speedup in casecollisionauditor
Joshua Redstone <joshua.redstone@fb.com>
parents: 17161
diff changeset
   105
        self._loweredfiles.add(fl)
afd75476939e scmutil: 25% speedup in casecollisionauditor
Joshua Redstone <joshua.redstone@fb.com>
parents: 17161
diff changeset
   106
        self._newfiles.add(f)
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   107
14220
21b8ce4d3331 rename path_auditor to pathauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14167
diff changeset
   108
class pathauditor(object):
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   109
    '''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
   110
    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
   111
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   112
    - ends with a directory separator
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   113
    - under top-level .hg
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   114
    - 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
   115
    - contains ".."
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   116
    - 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
   117
    - 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
   118
      some nested repositories, e.g., subrepositories)
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   119
    '''
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   120
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   121
    def __init__(self, root, callback=None):
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   122
        self.audited = set()
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   123
        self.auditeddir = set()
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   124
        self.root = root
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   125
        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
   126
        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
   127
            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
   128
        else:
37a6e9765015 pathauditor: switch normcase logic according to case sensitivity of filesystem
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15665
diff changeset
   129
            self.normcase = lambda x: x
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   130
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   131
    def __call__(self, path):
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   132
        '''Check the relative path.
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   133
        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
   134
15721
4751d5133f15 windows: force specified path to be audited in localpath form
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15666
diff changeset
   135
        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
   136
        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
   137
        if normpath in self.audited:
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   138
            return
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   139
        # 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
   140
        if util.endswithsep(path):
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   141
            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
   142
        parts = util.splitpath(path)
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   143
        if (os.path.splitdrive(path)[0]
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   144
            or parts[0].lower() in ('.hg', '.hg.', '')
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   145
            or os.pardir in parts):
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   146
            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
   147
        if '.hg' in path.lower():
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   148
            lparts = [p.lower() for p in parts]
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   149
            for p in '.hg', '.hg.':
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   150
                if p in lparts[1:]:
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   151
                    pos = lparts.index(p)
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   152
                    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
   153
                    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
   154
                                     % (path, base))
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   155
15665
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   156
        normparts = util.splitpath(normpath)
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   157
        assert len(parts) == len(normparts)
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   158
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   159
        parts.pop()
15665
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   160
        normparts.pop()
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   161
        prefixes = []
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   162
        while parts:
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   163
            prefix = os.sep.join(parts)
15665
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   164
            normprefix = os.sep.join(normparts)
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   165
            if normprefix in self.auditeddir:
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   166
                break
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   167
            curpath = os.path.join(self.root, prefix)
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   168
            try:
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   169
                st = os.lstat(curpath)
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   170
            except OSError, err:
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   171
                # 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
   172
                # 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
   173
                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
   174
                    raise
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   175
            else:
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   176
                if stat.S_ISLNK(st.st_mode):
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   177
                    raise util.Abort(
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   178
                        _('path %r traverses symbolic link %r')
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   179
                        % (path, prefix))
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   180
                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
   181
                      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
   182
                    if not self.callback or not self.callback(curpath):
16683
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   183
                        raise util.Abort(_("path '%s' is inside nested "
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   184
                                           "repo %r")
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   185
                                         % (path, prefix))
15665
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   186
            prefixes.append(normprefix)
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   187
            parts.pop()
15665
081e795c60e0 pathauditor: preserve case in abort messages
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15664
diff changeset
   188
            normparts.pop()
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   189
15664
ec8730886f36 pathauditor: use normcase()-ed path for audit result cache
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 14984
diff changeset
   190
        self.audited.add(normpath)
13972
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   191
        # 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
   192
        # 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
   193
        self.auditeddir.update(prefixes)
d1f4e7fd970a move path_auditor from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13971
diff changeset
   194
18624
4db216b1c154 pathauditor: add check() method
Durham Goode <durham@fb.com>
parents: 18618
diff changeset
   195
    def check(self, path):
4db216b1c154 pathauditor: add check() method
Durham Goode <durham@fb.com>
parents: 18618
diff changeset
   196
        try:
4db216b1c154 pathauditor: add check() method
Durham Goode <durham@fb.com>
parents: 18618
diff changeset
   197
            self(path)
4db216b1c154 pathauditor: add check() method
Durham Goode <durham@fb.com>
parents: 18618
diff changeset
   198
            return True
4db216b1c154 pathauditor: add check() method
Durham Goode <durham@fb.com>
parents: 18618
diff changeset
   199
        except (OSError, util.Abort):
4db216b1c154 pathauditor: add check() method
Durham Goode <durham@fb.com>
parents: 18618
diff changeset
   200
            return False
4db216b1c154 pathauditor: add check() method
Durham Goode <durham@fb.com>
parents: 18618
diff changeset
   201
17649
f65c6a5f256c scmutil: rename classes from "opener" to "vfs"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17561
diff changeset
   202
class abstractvfs(object):
14089
d3f7e110c3c0 opener: introduce an abstact superclass of it
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14068
diff changeset
   203
    """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
   204
d3f7e110c3c0 opener: introduce an abstact superclass of it
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14068
diff changeset
   205
    def __init__(self, *args, **kwargs):
d3f7e110c3c0 opener: introduce an abstact superclass of it
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14068
diff changeset
   206
        '''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
   207
        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
   208
16455
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   209
    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
   210
        '''gracefully return an empty string for missing files'''
16455
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   211
        try:
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   212
            return self.read(path)
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   213
        except IOError, inst:
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   214
            if inst.errno != errno.ENOENT:
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   215
                raise
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   216
        return ""
154219f3a6a4 opener: introduce tryread helper
Matt Mackall <mpm@selenic.com>
parents: 16436
diff changeset
   217
14167
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   218
    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
   219
        fp = self(path, 'rb')
14097
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   220
        try:
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   221
            return fp.read()
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   222
        finally:
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   223
            fp.close()
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   224
14167
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   225
    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
   226
        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
   227
        try:
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   228
            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
   229
        finally:
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   230
            fp.close()
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   231
0e4753807c93 util & scmutil: adapt read/write helpers as request by mpm
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14138
diff changeset
   232
    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
   233
        fp = self(path, 'ab')
14097
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   234
        try:
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   235
            return fp.write(data)
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   236
        finally:
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   237
            fp.close()
ca3376f044f8 opener: add read & write utility methods
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14090
diff changeset
   238
17161
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   239
    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
   240
        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
   241
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   242
    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
   243
        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
   244
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   245
    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
   246
        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
   247
be016e96117a localrepo: use file API via vfs while ensuring repository directory
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17157
diff changeset
   248
    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
   249
        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
   250
17723
ab23768746fd scmutil: reorder newly added functions for vfs support in dictionary order
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17681
diff changeset
   251
    def mkdir(self, path=None):
ab23768746fd scmutil: reorder newly added functions for vfs support in dictionary order
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17681
diff changeset
   252
        return os.mkdir(self.join(path))
ab23768746fd scmutil: reorder newly added functions for vfs support in dictionary order
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17681
diff changeset
   253
17747
aad3bce98f76 store: invoke "osutil.listdir()" via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17726
diff changeset
   254
    def readdir(self, path=None, stat=None, skip=None):
aad3bce98f76 store: invoke "osutil.listdir()" via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17726
diff changeset
   255
        return osutil.listdir(self.join(path), stat, skip)
aad3bce98f76 store: invoke "osutil.listdir()" via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17726
diff changeset
   256
18948
2f05fa162316 localrepo: use "vfs.rename()" instead of "util.rename()"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18945
diff changeset
   257
    def rename(self, src, dst):
2f05fa162316 localrepo: use "vfs.rename()" instead of "util.rename()"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18945
diff changeset
   258
        return util.rename(self.join(src), self.join(dst))
2f05fa162316 localrepo: use "vfs.rename()" instead of "util.rename()"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18945
diff changeset
   259
17726
7cb7e17c23b2 store: invoke "os.stat()" for "createmode" initialization via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17725
diff changeset
   260
    def stat(self, path=None):
7cb7e17c23b2 store: invoke "os.stat()" for "createmode" initialization via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17725
diff changeset
   261
        return os.stat(self.join(path))
7cb7e17c23b2 store: invoke "os.stat()" for "createmode" initialization via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17725
diff changeset
   262
17649
f65c6a5f256c scmutil: rename classes from "opener" to "vfs"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17561
diff changeset
   263
class vfs(abstractvfs):
f65c6a5f256c scmutil: rename classes from "opener" to "vfs"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17561
diff changeset
   264
    '''Operate files relative to a base directory
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   265
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   266
    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
   267
    remote file access from higher level code.
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   268
    '''
18945
e75b72fffdfe vfs: split "expand" into "realpath"/"expandpath" to apply each separately
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18900
diff changeset
   269
    def __init__(self, base, audit=True, expandpath=False, realpath=False):
e75b72fffdfe vfs: split "expand" into "realpath"/"expandpath" to apply each separately
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18900
diff changeset
   270
        if expandpath:
e75b72fffdfe vfs: split "expand" into "realpath"/"expandpath" to apply each separately
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18900
diff changeset
   271
            base = util.expandpath(base)
e75b72fffdfe vfs: split "expand" into "realpath"/"expandpath" to apply each separately
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18900
diff changeset
   272
        if realpath:
e75b72fffdfe vfs: split "expand" into "realpath"/"expandpath" to apply each separately
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18900
diff changeset
   273
            base = os.path.realpath(base)
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   274
        self.base = base
17554
5450c8ad9d98 scmutil: turn opener._audit into a property, mustaudit
Bryan O'Sullivan <bryano@fb.com>
parents: 17248
diff changeset
   275
        self._setmustaudit(audit)
5450c8ad9d98 scmutil: turn opener._audit into a property, mustaudit
Bryan O'Sullivan <bryano@fb.com>
parents: 17248
diff changeset
   276
        self.createmode = None
5450c8ad9d98 scmutil: turn opener._audit into a property, mustaudit
Bryan O'Sullivan <bryano@fb.com>
parents: 17248
diff changeset
   277
        self._trustnlink = None
5450c8ad9d98 scmutil: turn opener._audit into a property, mustaudit
Bryan O'Sullivan <bryano@fb.com>
parents: 17248
diff changeset
   278
5450c8ad9d98 scmutil: turn opener._audit into a property, mustaudit
Bryan O'Sullivan <bryano@fb.com>
parents: 17248
diff changeset
   279
    def _getmustaudit(self):
5450c8ad9d98 scmutil: turn opener._audit into a property, mustaudit
Bryan O'Sullivan <bryano@fb.com>
parents: 17248
diff changeset
   280
        return self._audit
5450c8ad9d98 scmutil: turn opener._audit into a property, mustaudit
Bryan O'Sullivan <bryano@fb.com>
parents: 17248
diff changeset
   281
5450c8ad9d98 scmutil: turn opener._audit into a property, mustaudit
Bryan O'Sullivan <bryano@fb.com>
parents: 17248
diff changeset
   282
    def _setmustaudit(self, onoff):
5450c8ad9d98 scmutil: turn opener._audit into a property, mustaudit
Bryan O'Sullivan <bryano@fb.com>
parents: 17248
diff changeset
   283
        self._audit = onoff
5450c8ad9d98 scmutil: turn opener._audit into a property, mustaudit
Bryan O'Sullivan <bryano@fb.com>
parents: 17248
diff changeset
   284
        if onoff:
18327
4aecdb91443c scmutil: simplify vfs.audit - drop wrapped vfs.auditor
Mads Kiilerich <mads@kiilerich.com>
parents: 18316
diff changeset
   285
            self.audit = pathauditor(self.base)
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   286
        else:
18327
4aecdb91443c scmutil: simplify vfs.audit - drop wrapped vfs.auditor
Mads Kiilerich <mads@kiilerich.com>
parents: 18316
diff changeset
   287
            self.audit = util.always
17554
5450c8ad9d98 scmutil: turn opener._audit into a property, mustaudit
Bryan O'Sullivan <bryano@fb.com>
parents: 17248
diff changeset
   288
5450c8ad9d98 scmutil: turn opener._audit into a property, mustaudit
Bryan O'Sullivan <bryano@fb.com>
parents: 17248
diff changeset
   289
    mustaudit = property(_getmustaudit, _setmustaudit)
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   290
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   291
    @util.propertycache
14261
e3649bcca3f6 opener: rename _can_symlink to _cansymlink
Adrian Buehlmann <adrian@cadifra.com>
parents: 14236
diff changeset
   292
    def _cansymlink(self):
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   293
        return util.checklink(self.base)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   294
18192
f9a89bdd64a6 scmutil: don't try to match modes on filesystems without modes (issue3740)
Matt Mackall <mpm@selenic.com>
parents: 17850
diff changeset
   295
    @util.propertycache
f9a89bdd64a6 scmutil: don't try to match modes on filesystems without modes (issue3740)
Matt Mackall <mpm@selenic.com>
parents: 17850
diff changeset
   296
    def _chmod(self):
f9a89bdd64a6 scmutil: don't try to match modes on filesystems without modes (issue3740)
Matt Mackall <mpm@selenic.com>
parents: 17850
diff changeset
   297
        return util.checkexec(self.base)
f9a89bdd64a6 scmutil: don't try to match modes on filesystems without modes (issue3740)
Matt Mackall <mpm@selenic.com>
parents: 17850
diff changeset
   298
17763
13070de77c86 vfs: backout fchmod change from 76b73ce0ffac
Matt Mackall <mpm@selenic.com>
parents: 17752
diff changeset
   299
    def _fixfilemode(self, name):
18192
f9a89bdd64a6 scmutil: don't try to match modes on filesystems without modes (issue3740)
Matt Mackall <mpm@selenic.com>
parents: 17850
diff changeset
   300
        if self.createmode is None or not self._chmod:
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   301
            return
17763
13070de77c86 vfs: backout fchmod change from 76b73ce0ffac
Matt Mackall <mpm@selenic.com>
parents: 17752
diff changeset
   302
        os.chmod(name, self.createmode & 0666)
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   303
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   304
    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
   305
        if self._audit:
36283a7b6856 opener: add self._audit (issue2862)
Adrian Buehlmann <adrian@cadifra.com>
parents: 14672
diff changeset
   306
            r = util.checkosfilename(path)
36283a7b6856 opener: add self._audit (issue2862)
Adrian Buehlmann <adrian@cadifra.com>
parents: 14672
diff changeset
   307
            if r:
36283a7b6856 opener: add self._audit (issue2862)
Adrian Buehlmann <adrian@cadifra.com>
parents: 14672
diff changeset
   308
                raise util.Abort("%s: %r" % (r, path))
18327
4aecdb91443c scmutil: simplify vfs.audit - drop wrapped vfs.auditor
Mads Kiilerich <mads@kiilerich.com>
parents: 18316
diff changeset
   309
        self.audit(path)
16199
8181bd808dc5 scmutil: add join method to opener to construct path relative to base
Idan Kamara <idankk86@gmail.com>
parents: 16198
diff changeset
   310
        f = self.join(path)
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   311
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   312
        if not text and "b" not in mode:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   313
            mode += "b" # for that other OS
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   314
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   315
        nlink = -1
17937
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   316
        if mode not in ('r', 'rb'):
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   317
            dirname, basename = util.split(f)
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   318
            # If basename is empty, then the path is malformed because it points
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   319
            # to a directory. Let the posixfile() call below raise IOError.
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   320
            if basename:
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   321
                if atomictemp:
18678
423eee0b0b14 util: make ensuredirs safer against races
Bryan O'Sullivan <bryano@fb.com>
parents: 18668
diff changeset
   322
                    util.ensuredirs(dirname, self.createmode)
17937
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   323
                    return util.atomictempfile(f, mode, self.createmode)
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   324
                try:
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   325
                    if 'w' in mode:
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   326
                        util.unlink(f)
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   327
                        nlink = 0
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   328
                    else:
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   329
                        # nlinks() may behave differently for files on Windows
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   330
                        # shares if the file is open.
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   331
                        fd = util.posixfile(f)
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   332
                        nlink = util.nlinks(f)
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   333
                        if nlink < 1:
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   334
                            nlink = 2 # force mktempcopy (issue1922)
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   335
                        fd.close()
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   336
                except (OSError, IOError), e:
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   337
                    if e.errno != errno.ENOENT:
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   338
                        raise
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   339
                    nlink = 0
18678
423eee0b0b14 util: make ensuredirs safer against races
Bryan O'Sullivan <bryano@fb.com>
parents: 18668
diff changeset
   340
                    util.ensuredirs(dirname, self.createmode)
17937
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   341
                if nlink > 0:
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   342
                    if self._trustnlink is None:
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   343
                        self._trustnlink = nlink > 1 or util.checknlink(f)
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   344
                    if nlink > 1 or not self._trustnlink:
3cb032d50447 vfs: optimize __call__ by not calling util.split for reads
Adrian Buehlmann <adrian@cadifra.com>
parents: 17850
diff changeset
   345
                        util.rename(util.mktempcopy(f), f)
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   346
        fp = util.posixfile(f, mode)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   347
        if nlink == 0:
17763
13070de77c86 vfs: backout fchmod change from 76b73ce0ffac
Matt Mackall <mpm@selenic.com>
parents: 17752
diff changeset
   348
            self._fixfilemode(f)
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   349
        return fp
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   350
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   351
    def symlink(self, src, dst):
18327
4aecdb91443c scmutil: simplify vfs.audit - drop wrapped vfs.auditor
Mads Kiilerich <mads@kiilerich.com>
parents: 18316
diff changeset
   352
        self.audit(dst)
16199
8181bd808dc5 scmutil: add join method to opener to construct path relative to base
Idan Kamara <idankk86@gmail.com>
parents: 16198
diff changeset
   353
        linkname = self.join(dst)
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   354
        try:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   355
            os.unlink(linkname)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   356
        except OSError:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   357
            pass
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   358
18678
423eee0b0b14 util: make ensuredirs safer against races
Bryan O'Sullivan <bryano@fb.com>
parents: 18668
diff changeset
   359
        util.ensuredirs(os.path.dirname(linkname), self.createmode)
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   360
14261
e3649bcca3f6 opener: rename _can_symlink to _cansymlink
Adrian Buehlmann <adrian@cadifra.com>
parents: 14236
diff changeset
   361
        if self._cansymlink:
13970
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   362
            try:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   363
                os.symlink(src, linkname)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   364
            except OSError, err:
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   365
                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
   366
                              (src, err.strerror), linkname)
d13913355390 move opener from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13962
diff changeset
   367
        else:
17768
9837cafc25b1 vfs: use self.write to write symlink placeholders
Matt Mackall <mpm@selenic.com>
parents: 17763
diff changeset
   368
            self.write(dst, src)
13971
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   369
16199
8181bd808dc5 scmutil: add join method to opener to construct path relative to base
Idan Kamara <idankk86@gmail.com>
parents: 16198
diff changeset
   370
    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
   371
        if path:
17681
a41fd730f230 scmutil: backout 83785bb56062 (issue3643)
Matt Mackall <mpm@selenic.com>
parents: 17675
diff changeset
   372
            return os.path.join(self.base, path)
a41fd730f230 scmutil: backout 83785bb56062 (issue3643)
Matt Mackall <mpm@selenic.com>
parents: 17675
diff changeset
   373
        else:
a41fd730f230 scmutil: backout 83785bb56062 (issue3643)
Matt Mackall <mpm@selenic.com>
parents: 17675
diff changeset
   374
            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
   375
17649
f65c6a5f256c scmutil: rename classes from "opener" to "vfs"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17561
diff changeset
   376
opener = vfs
f65c6a5f256c scmutil: rename classes from "opener" to "vfs"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17561
diff changeset
   377
17845
408ded42c5ec scmutil: abstract out mustaudit delegation
Bryan O'Sullivan <bryano@fb.com>
parents: 17821
diff changeset
   378
class auditvfs(object):
408ded42c5ec scmutil: abstract out mustaudit delegation
Bryan O'Sullivan <bryano@fb.com>
parents: 17821
diff changeset
   379
    def __init__(self, vfs):
408ded42c5ec scmutil: abstract out mustaudit delegation
Bryan O'Sullivan <bryano@fb.com>
parents: 17821
diff changeset
   380
        self.vfs = vfs
408ded42c5ec scmutil: abstract out mustaudit delegation
Bryan O'Sullivan <bryano@fb.com>
parents: 17821
diff changeset
   381
408ded42c5ec scmutil: abstract out mustaudit delegation
Bryan O'Sullivan <bryano@fb.com>
parents: 17821
diff changeset
   382
    def _getmustaudit(self):
408ded42c5ec scmutil: abstract out mustaudit delegation
Bryan O'Sullivan <bryano@fb.com>
parents: 17821
diff changeset
   383
        return self.vfs.mustaudit
408ded42c5ec scmutil: abstract out mustaudit delegation
Bryan O'Sullivan <bryano@fb.com>
parents: 17821
diff changeset
   384
408ded42c5ec scmutil: abstract out mustaudit delegation
Bryan O'Sullivan <bryano@fb.com>
parents: 17821
diff changeset
   385
    def _setmustaudit(self, onoff):
408ded42c5ec scmutil: abstract out mustaudit delegation
Bryan O'Sullivan <bryano@fb.com>
parents: 17821
diff changeset
   386
        self.vfs.mustaudit = onoff
408ded42c5ec scmutil: abstract out mustaudit delegation
Bryan O'Sullivan <bryano@fb.com>
parents: 17821
diff changeset
   387
408ded42c5ec scmutil: abstract out mustaudit delegation
Bryan O'Sullivan <bryano@fb.com>
parents: 17821
diff changeset
   388
    mustaudit = property(_getmustaudit, _setmustaudit)
408ded42c5ec scmutil: abstract out mustaudit delegation
Bryan O'Sullivan <bryano@fb.com>
parents: 17821
diff changeset
   389
17846
f42cf30873dc scmutil: add mustaudit delegation to filtervfs (issue3673)
Bryan O'Sullivan <bryano@fb.com>
parents: 17845
diff changeset
   390
class filtervfs(abstractvfs, auditvfs):
17649
f65c6a5f256c scmutil: rename classes from "opener" to "vfs"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17561
diff changeset
   391
    '''Wrapper vfs for filtering filenames with a function.'''
14090
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   392
17846
f42cf30873dc scmutil: add mustaudit delegation to filtervfs (issue3673)
Bryan O'Sullivan <bryano@fb.com>
parents: 17845
diff changeset
   393
    def __init__(self, vfs, filter):
f42cf30873dc scmutil: add mustaudit delegation to filtervfs (issue3673)
Bryan O'Sullivan <bryano@fb.com>
parents: 17845
diff changeset
   394
        auditvfs.__init__(self, vfs)
14090
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   395
        self._filter = filter
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   396
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   397
    def __call__(self, path, *args, **kwargs):
17846
f42cf30873dc scmutil: add mustaudit delegation to filtervfs (issue3673)
Bryan O'Sullivan <bryano@fb.com>
parents: 17845
diff changeset
   398
        return self.vfs(self._filter(path), *args, **kwargs)
14090
e24b5e3c2f27 add filteropener abstraction for store openers
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 14089
diff changeset
   399
17725
ffd589d4b785 vfs: define "join()" in each classes derived from "abstractvfs"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17723
diff changeset
   400
    def join(self, path):
ffd589d4b785 vfs: define "join()" in each classes derived from "abstractvfs"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17723
diff changeset
   401
        if path:
17846
f42cf30873dc scmutil: add mustaudit delegation to filtervfs (issue3673)
Bryan O'Sullivan <bryano@fb.com>
parents: 17845
diff changeset
   402
            return self.vfs.join(self._filter(path))
17725
ffd589d4b785 vfs: define "join()" in each classes derived from "abstractvfs"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17723
diff changeset
   403
        else:
17846
f42cf30873dc scmutil: add mustaudit delegation to filtervfs (issue3673)
Bryan O'Sullivan <bryano@fb.com>
parents: 17845
diff changeset
   404
            return self.vfs.join(path)
17725
ffd589d4b785 vfs: define "join()" in each classes derived from "abstractvfs"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17723
diff changeset
   405
17649
f65c6a5f256c scmutil: rename classes from "opener" to "vfs"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17561
diff changeset
   406
filteropener = filtervfs
f65c6a5f256c scmutil: rename classes from "opener" to "vfs"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17561
diff changeset
   407
18213
c38a62af000e vfs: add a read only vfs
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18206
diff changeset
   408
class readonlyvfs(abstractvfs, auditvfs):
c38a62af000e vfs: add a read only vfs
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18206
diff changeset
   409
    '''Wrapper vfs preventing any writing.'''
c38a62af000e vfs: add a read only vfs
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18206
diff changeset
   410
c38a62af000e vfs: add a read only vfs
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18206
diff changeset
   411
    def __init__(self, vfs):
c38a62af000e vfs: add a read only vfs
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18206
diff changeset
   412
        auditvfs.__init__(self, vfs)
c38a62af000e vfs: add a read only vfs
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18206
diff changeset
   413
c38a62af000e vfs: add a read only vfs
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18206
diff changeset
   414
    def __call__(self, path, mode='r', *args, **kw):
c38a62af000e vfs: add a read only vfs
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18206
diff changeset
   415
        if mode not in ('r', 'rb'):
c38a62af000e vfs: add a read only vfs
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18206
diff changeset
   416
            raise util.Abort('this vfs is read only')
c38a62af000e vfs: add a read only vfs
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18206
diff changeset
   417
        return self.vfs(path, mode, *args, **kw)
c38a62af000e vfs: add a read only vfs
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18206
diff changeset
   418
c38a62af000e vfs: add a read only vfs
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18206
diff changeset
   419
13971
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   420
def canonpath(root, cwd, myname, auditor=None):
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   421
    '''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
   422
    if util.endswithsep(root):
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   423
        rootsep = root
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   424
    else:
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   425
        rootsep = root + os.sep
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   426
    name = myname
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   427
    if not os.path.isabs(name):
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   428
        name = os.path.join(root, cwd, name)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   429
    name = os.path.normpath(name)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   430
    if auditor is None:
14220
21b8ce4d3331 rename path_auditor to pathauditor
Adrian Buehlmann <adrian@cadifra.com>
parents: 14167
diff changeset
   431
        auditor = pathauditor(root)
13971
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   432
    if name != rootsep and name.startswith(rootsep):
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   433
        name = name[len(rootsep):]
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   434
        auditor(name)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   435
        return util.pconvert(name)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   436
    elif name == root:
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   437
        return ''
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   438
    else:
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   439
        # 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
   440
        # 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
   441
        # 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
   442
        # `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
   443
        # file name we want.
13971
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   444
        rel = []
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   445
        while True:
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   446
            try:
17007
21e18c608b68 scmutil: change canonpath to use util.samefile (issue2167)
Adrian Buehlmann <adrian@cadifra.com>
parents: 16828
diff changeset
   447
                s = util.samefile(name, root)
13971
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   448
            except OSError:
17007
21e18c608b68 scmutil: change canonpath to use util.samefile (issue2167)
Adrian Buehlmann <adrian@cadifra.com>
parents: 16828
diff changeset
   449
                s = False
21e18c608b68 scmutil: change canonpath to use util.samefile (issue2167)
Adrian Buehlmann <adrian@cadifra.com>
parents: 16828
diff changeset
   450
            if s:
13971
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   451
                if not rel:
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   452
                    # 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
   453
                    return ''
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   454
                rel.reverse()
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   455
                name = os.path.join(*rel)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   456
                auditor(name)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   457
                return util.pconvert(name)
17561
4647aa33ad81 scmutil: use the new faster path split
Bryan O'Sullivan <bryano@fb.com>
parents: 17559
diff changeset
   458
            dirname, basename = util.split(name)
13971
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   459
            rel.append(basename)
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   460
            if dirname == name:
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   461
                break
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   462
            name = dirname
bfeaa88b875d move canonpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13970
diff changeset
   463
18450
4f9a52858512 scmutil: localize and improve 'not under root' message
Mads Kiilerich <madski@unity3d.com>
parents: 18327
diff changeset
   464
        raise util.Abort(_("%s not under root '%s'") % (myname, root))
13975
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   465
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   466
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
   467
    '''yield every hg repository under path, always recursively.
5a9acb0b2086 help: improve hgweb help
Mads Kiilerich <mads@kiilerich.com>
parents: 17037
diff changeset
   468
    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
   469
    def errhandler(err):
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   470
        if err.filename == path:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   471
            raise err
14961
5523529bd1af walkrepos: use getattr instead of hasattr for samestat
Augie Fackler <durin42@gmail.com>
parents: 14928
diff changeset
   472
    samestat = getattr(os.path, 'samestat', None)
5523529bd1af walkrepos: use getattr instead of hasattr for samestat
Augie Fackler <durin42@gmail.com>
parents: 14928
diff changeset
   473
    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
   474
        def adddir(dirlst, dirname):
13975
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   475
            match = False
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   476
            dirstat = os.stat(dirname)
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   477
            for lstdirstat in dirlst:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   478
                if samestat(dirstat, lstdirstat):
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   479
                    match = True
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   480
                    break
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   481
            if not match:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   482
                dirlst.append(dirstat)
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   483
            return not match
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   484
    else:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   485
        followsym = False
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   486
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   487
    if (seen_dirs is None) and followsym:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   488
        seen_dirs = []
14227
94985b5a8278 scmutil: rename local function _add_dir_if_not_there
Adrian Buehlmann <adrian@cadifra.com>
parents: 14226
diff changeset
   489
        adddir(seen_dirs, path)
13975
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   490
    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
   491
        dirs.sort()
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   492
        if '.hg' in dirs:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   493
            yield root # found a repository
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   494
            qroot = os.path.join(root, '.hg', 'patches')
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   495
            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
   496
                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
   497
            if recurse:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   498
                # avoid recursing inside the .hg directory
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   499
                dirs.remove('.hg')
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   500
            else:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   501
                dirs[:] = [] # don't descend further
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   502
        elif followsym:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   503
            newdirs = []
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   504
            for d in dirs:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   505
                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
   506
                if adddir(seen_dirs, fname):
13975
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   507
                    if os.path.islink(fname):
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   508
                        for hgname in walkrepos(fname, True, seen_dirs):
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   509
                            yield hgname
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   510
                    else:
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   511
                        newdirs.append(d)
938fbeacac84 move walkrepos from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13974
diff changeset
   512
            dirs[:] = newdirs
13984
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   513
14224
f4189866c76c rename scmutil.os_rcpath to osrcpath
Adrian Buehlmann <adrian@cadifra.com>
parents: 14220
diff changeset
   514
def osrcpath():
13985
26335a817dd0 move os_rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13984
diff changeset
   515
    '''return default os-specific hgrc search path'''
14225
f0ca440b5722 rename scmutil.system_rcpath to systemrcpath
Adrian Buehlmann <adrian@cadifra.com>
parents: 14224
diff changeset
   516
    path = systemrcpath()
14226
73cca883370d rename scmutil.user_rcpath to userrcpath
Adrian Buehlmann <adrian@cadifra.com>
parents: 14225
diff changeset
   517
    path.extend(userrcpath())
13985
26335a817dd0 move os_rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13984
diff changeset
   518
    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
   519
    return path
26335a817dd0 move os_rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13984
diff changeset
   520
13984
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   521
_rcpath = None
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   522
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   523
def rcpath():
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   524
    '''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
   525
    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
   526
    else use item.
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   527
    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
   528
    if no HGRCPATH, use default os-specific path.'''
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   529
    global _rcpath
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   530
    if _rcpath is None:
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   531
        if 'HGRCPATH' in os.environ:
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   532
            _rcpath = []
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   533
            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
   534
                if not p:
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   535
                    continue
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   536
                p = util.expandpath(p)
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   537
                if os.path.isdir(p):
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   538
                    for f, kind in osutil.listdir(p):
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   539
                        if f.endswith('.rc'):
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   540
                            _rcpath.append(os.path.join(p, f))
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   541
                else:
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   542
                    _rcpath.append(p)
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   543
        else:
14224
f4189866c76c rename scmutil.os_rcpath to osrcpath
Adrian Buehlmann <adrian@cadifra.com>
parents: 14220
diff changeset
   544
            _rcpath = osrcpath()
13984
af60153b5e3b move rcpath from util to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13975
diff changeset
   545
    return _rcpath
13986
9c374cf76b7d move system_rcpath and user_rcpath to scmutil
Adrian Buehlmann <adrian@cadifra.com>
parents: 13985
diff changeset
   546
14319
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   547
def revsingle(repo, revspec, default='.'):
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   548
    if not revspec:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   549
        return repo[default]
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   550
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   551
    l = revrange(repo, [revspec])
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   552
    if len(l) < 1:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   553
        raise util.Abort(_('empty revision set'))
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   554
    return repo[l[-1]]
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   555
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   556
def revpair(repo, revs):
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   557
    if not revs:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   558
        return repo.dirstate.p1(), None
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
    l = revrange(repo, revs)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   561
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   562
    if len(l) == 0:
16790
2a0efa1112ac revpair: handle odd ranges (issue3474)
Matt Mackall <mpm@selenic.com>
parents: 16479
diff changeset
   563
        if revs:
2a0efa1112ac revpair: handle odd ranges (issue3474)
Matt Mackall <mpm@selenic.com>
parents: 16479
diff changeset
   564
            raise util.Abort(_('empty revision range'))
14319
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   565
        return repo.dirstate.p1(), None
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   566
16790
2a0efa1112ac revpair: handle odd ranges (issue3474)
Matt Mackall <mpm@selenic.com>
parents: 16479
diff changeset
   567
    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
   568
        return repo.lookup(l[0]), None
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
    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
   571
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   572
_revrangesep = ':'
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   573
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   574
def revrange(repo, revs):
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   575
    """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
   576
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   577
    def revfix(repo, val, defval):
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   578
        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
   579
            return defval
16379
5cbfbb838198 scmutil: use context instead of lookup
Matt Mackall <mpm@selenic.com>
parents: 16208
diff changeset
   580
        return repo[val].rev()
14319
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   581
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   582
    seen, l = set(), []
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   583
    for spec in revs:
16390
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   584
        if l and not seen:
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   585
            seen = set(l)
14319
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   586
        # 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
   587
        # 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
   588
        try:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   589
            if isinstance(spec, int):
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   590
                seen.add(spec)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   591
                l.append(spec)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   592
                continue
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   593
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   594
            if _revrangesep in spec:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   595
                start, end = spec.split(_revrangesep, 1)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   596
                start = revfix(repo, start, 0)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   597
                end = revfix(repo, end, len(repo) - 1)
18466
ac0c12123743 log: remove any ancestors of nullrev (issue3772)
Sean Farley <sean.michael.farley@gmail.com>
parents: 18450
diff changeset
   598
                if end == nullrev and start <= 0:
ac0c12123743 log: remove any ancestors of nullrev (issue3772)
Sean Farley <sean.michael.farley@gmail.com>
parents: 18450
diff changeset
   599
                    start = nullrev
17992
c95210b82c0e clfilter: remove usage of `range` and `xrange` in scmutil.revrange
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 17937
diff changeset
   600
                rangeiter = repo.changelog.revs(start, end)
16390
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   601
                if not seen and not l:
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   602
                    # by far the most common case: revs = ["-1:0"]
17992
c95210b82c0e clfilter: remove usage of `range` and `xrange` in scmutil.revrange
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 17937
diff changeset
   603
                    l = list(rangeiter)
16390
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   604
                    # defer syncing seen until next iteration
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   605
                    continue
17992
c95210b82c0e clfilter: remove usage of `range` and `xrange` in scmutil.revrange
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 17937
diff changeset
   606
                newrevs = set(rangeiter)
16390
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   607
                if seen:
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   608
                    newrevs.difference_update(seen)
16814
9da5a2864f3f scmutil: seen.union should be seen.update (issue3476)
Bryan O'Sullivan <bryano@fb.com>
parents: 16790
diff changeset
   609
                    seen.update(newrevs)
16390
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   610
                else:
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   611
                    seen = newrevs
4df76d5506a9 scmutil: speed up revrange
Bryan O'Sullivan <bryano@fb.com>
parents: 16383
diff changeset
   612
                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
   613
                continue
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   614
            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
   615
                rev = revfix(repo, spec, None)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   616
                if rev in seen:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   617
                    continue
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   618
                seen.add(rev)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   619
                l.append(rev)
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   620
                continue
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   621
        except error.RepoLookupError:
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   622
            pass
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   623
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   624
        # 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
   625
        m = revset.match(repo.ui, spec)
17675
8575f4a2126e clfilter: remove usage of `range` in favor of iteration over changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 17649
diff changeset
   626
        dl = [r for r in m(repo, list(repo)) if r not in seen]
17037
419966126a05 scmutil: speed up new-style range extension
Bryan O'Sullivan <bryano@fb.com>
parents: 17007
diff changeset
   627
        l.extend(dl)
419966126a05 scmutil: speed up new-style range extension
Bryan O'Sullivan <bryano@fb.com>
parents: 17007
diff changeset
   628
        seen.update(dl)
14319
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   629
b33f3e35efb0 scmutil: move revsingle/pair/range from cmdutil
Matt Mackall <mpm@selenic.com>
parents: 14261
diff changeset
   630
    return l
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   631
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   632
def expandpats(pats):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   633
    if not util.expandglobs:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   634
        return list(pats)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   635
    ret = []
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   636
    for p in pats:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   637
        kind, name = matchmod._patsplit(p, None)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   638
        if kind is None:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   639
            try:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   640
                globbed = glob.glob(name)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   641
            except re.error:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   642
                globbed = [name]
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   643
            if globbed:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   644
                ret.extend(globbed)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   645
                continue
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   646
        ret.append(p)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   647
    return ret
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   648
16171
336e61875335 graphlog: restore FILE glob expansion on Windows
Patrick Mezard <patrick@mezard.eu>
parents: 16167
diff changeset
   649
def matchandpats(ctx, pats=[], opts={}, globbed=False, default='relpath'):
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   650
    if pats == ("",):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   651
        pats = []
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   652
    if not globbed and default == 'relpath':
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   653
        pats = expandpats(pats or [])
14670
19197fa4c41c scmutil: match now accepts a context or a repo
Matt Mackall <mpm@selenic.com>
parents: 14669
diff changeset
   654
19197fa4c41c scmutil: match now accepts a context or a repo
Matt Mackall <mpm@selenic.com>
parents: 14669
diff changeset
   655
    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
   656
                         default)
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   657
    def badfn(f, msg):
14671
35c2cc322ba8 scmutil: switch match users to supplying contexts
Matt Mackall <mpm@selenic.com>
parents: 14670
diff changeset
   658
        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
   659
    m.bad = badfn
16171
336e61875335 graphlog: restore FILE glob expansion on Windows
Patrick Mezard <patrick@mezard.eu>
parents: 16167
diff changeset
   660
    return m, pats
336e61875335 graphlog: restore FILE glob expansion on Windows
Patrick Mezard <patrick@mezard.eu>
parents: 16167
diff changeset
   661
336e61875335 graphlog: restore FILE glob expansion on Windows
Patrick Mezard <patrick@mezard.eu>
parents: 16167
diff changeset
   662
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
   663
    return matchandpats(ctx, pats, opts, globbed, default)[0]
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   664
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   665
def matchall(repo):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   666
    return matchmod.always(repo.root, repo.getcwd())
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   667
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   668
def matchfiles(repo, files):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   669
    return matchmod.exact(repo.root, repo.getcwd(), files)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   670
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   671
def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   672
    if dry_run is None:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   673
        dry_run = opts.get('dry_run')
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   674
    if similarity is None:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   675
        similarity = float(opts.get('similarity') or 0)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   676
    # 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
   677
    added, unknown, deleted, removed = [], [], [], []
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   678
    audit_path = pathauditor(repo.root)
14671
35c2cc322ba8 scmutil: switch match users to supplying contexts
Matt Mackall <mpm@selenic.com>
parents: 14670
diff changeset
   679
    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
   680
    rejected = []
94a8396c9305 addremove: return 1 if we failed to handle any explicit files
Matt Mackall <mpm@selenic.com>
parents: 16115
diff changeset
   681
    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
   682
18559
d1582dd6288e addremove: don't call lexists, isdir, and islink
Durham Goode <durham@fb.com>
parents: 18558
diff changeset
   683
    ctx = repo[None]
18861
ec91b66e8965 scmutil.addremove: pull repo.dirstate fetch out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18860
diff changeset
   684
    dirstate = repo.dirstate
ec91b66e8965 scmutil.addremove: pull repo.dirstate fetch out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18860
diff changeset
   685
    walkresults = dirstate.walk(m, sorted(ctx.substate), True, False)
18865
835e9dfd1e49 scmutil.addremove: use iteritems on walk results
Siddharth Agarwal <sid0@fb.com>
parents: 18864
diff changeset
   686
    for abs, st in walkresults.iteritems():
18861
ec91b66e8965 scmutil.addremove: pull repo.dirstate fetch out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18860
diff changeset
   687
        dstate = dirstate[abs]
18626
b114e41c4df3 addremove: don't audit the path for paths already in the dirstate
Durham Goode <durham@fb.com>
parents: 18624
diff changeset
   688
        if dstate == '?' and audit_path.check(abs):
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   689
            unknown.append(abs)
18862
6de8cd5c719a scmutil.addremove: remove redundant directory and symlink checks
Siddharth Agarwal <sid0@fb.com>
parents: 18861
diff changeset
   690
        elif dstate != 'r' and not st:
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   691
            deleted.append(abs)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   692
        # for finding renames
18558
eb95cf4e219d addremove: only query dirstate once per path
Durham Goode <durham@fb.com>
parents: 18466
diff changeset
   693
        elif dstate == 'r':
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   694
            removed.append(abs)
18558
eb95cf4e219d addremove: only query dirstate once per path
Durham Goode <durham@fb.com>
parents: 18466
diff changeset
   695
        elif dstate == 'a':
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   696
            added.append(abs)
18863
1b70e5941ad7 scmutil.addremove: pull ui.status printing out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18862
diff changeset
   697
1b70e5941ad7 scmutil.addremove: pull ui.status printing out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18862
diff changeset
   698
    unknownset = set(unknown)
1b70e5941ad7 scmutil.addremove: pull ui.status printing out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18862
diff changeset
   699
    toprint = unknownset.copy()
1b70e5941ad7 scmutil.addremove: pull ui.status printing out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18862
diff changeset
   700
    toprint.update(deleted)
1b70e5941ad7 scmutil.addremove: pull ui.status printing out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18862
diff changeset
   701
    for abs in sorted(toprint):
1b70e5941ad7 scmutil.addremove: pull ui.status printing out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18862
diff changeset
   702
        if repo.ui.verbose or not m.exact(abs):
1b70e5941ad7 scmutil.addremove: pull ui.status printing out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18862
diff changeset
   703
            rel = m.rel(abs)
1b70e5941ad7 scmutil.addremove: pull ui.status printing out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18862
diff changeset
   704
            if abs in unknownset:
1b70e5941ad7 scmutil.addremove: pull ui.status printing out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18862
diff changeset
   705
                status = _('adding %s\n') % ((pats and rel) or abs)
1b70e5941ad7 scmutil.addremove: pull ui.status printing out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18862
diff changeset
   706
            else:
1b70e5941ad7 scmutil.addremove: pull ui.status printing out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18862
diff changeset
   707
                status = _('removing %s\n') % ((pats and rel) or abs)
1b70e5941ad7 scmutil.addremove: pull ui.status printing out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18862
diff changeset
   708
            repo.ui.status(status)
1b70e5941ad7 scmutil.addremove: pull ui.status printing out of the loop
Siddharth Agarwal <sid0@fb.com>
parents: 18862
diff changeset
   709
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   710
    copies = {}
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   711
    if similarity > 0:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   712
        for old, new, score in similar.findrenames(repo,
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   713
                added + unknown, removed + deleted, similarity):
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   714
            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
   715
                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
   716
                                 '(%d%% similar)\n') %
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   717
                               (m.rel(old), m.rel(new), score * 100))
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   718
            copies[new] = old
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   719
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   720
    if not dry_run:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   721
        wctx = repo[None]
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   722
        wlock = repo.wlock()
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   723
        try:
14435
5f6090e559fa context: make forget work like commands.forget
Matt Mackall <mpm@selenic.com>
parents: 14404
diff changeset
   724
            wctx.forget(deleted)
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   725
            wctx.add(unknown)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   726
            for new, old in copies.iteritems():
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   727
                wctx.copy(old, new)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   728
        finally:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   729
            wlock.release()
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   730
16167
94a8396c9305 addremove: return 1 if we failed to handle any explicit files
Matt Mackall <mpm@selenic.com>
parents: 16115
diff changeset
   731
    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
   732
        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
   733
            return 1
94a8396c9305 addremove: return 1 if we failed to handle any explicit files
Matt Mackall <mpm@selenic.com>
parents: 16115
diff changeset
   734
    return 0
94a8396c9305 addremove: return 1 if we failed to handle any explicit files
Matt Mackall <mpm@selenic.com>
parents: 16115
diff changeset
   735
14320
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   736
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
   737
    """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
   738
    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
   739
    """
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   740
    origsrc = repo.dirstate.copied(src) or src
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   741
    if dst == origsrc: # copying back a copy?
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   742
        if repo.dirstate[dst] not in 'mn' and not dryrun:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   743
            repo.dirstate.normallookup(dst)
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   744
    else:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   745
        if repo.dirstate[origsrc] == 'a' and origsrc == src:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   746
            if not ui.quiet:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   747
                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
   748
                          "data will be stored for %s.\n")
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   749
                        % (repo.pathto(origsrc, cwd), repo.pathto(dst, cwd)))
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   750
            if repo.dirstate[dst] in '?r' and not dryrun:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   751
                wctx.add([dst])
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   752
        elif not dryrun:
3438417a6657 scmutil: fold in wdutil
Matt Mackall <mpm@selenic.com>
parents: 14319
diff changeset
   753
            wctx.copy(origsrc, dst)
14482
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   754
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   755
def readrequires(opener, supported):
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   756
    '''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
   757
    are in the list of supported features.'''
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   758
    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
   759
    missings = []
14482
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   760
    for r in requirements:
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   761
        if r not in supported:
14484
4582a4dd1817 requires: note apparent corruption
Matt Mackall <mpm@selenic.com>
parents: 14483
diff changeset
   762
            if not r or not r[0].isalnum():
4582a4dd1817 requires: note apparent corruption
Matt Mackall <mpm@selenic.com>
parents: 14483
diff changeset
   763
                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
   764
            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
   765
    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
   766
    if missings:
16683
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   767
        raise error.RequirementError(
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   768
            _("unknown repository format: requires features '%s' (upgrade "
525fdb738975 cleanup: eradicate long lines
Brodie Rao <brodie@sf.io>
parents: 16479
diff changeset
   769
              "Mercurial)") % "', '".join(missings))
14482
58b36e9ea783 introduce new function scmutil.readrequires
Adrian Buehlmann <adrian@cadifra.com>
parents: 14435
diff changeset
   770
    return requirements
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   771
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   772
class filecacheentry(object):
18315
216230643ae2 filecache: allow filecacheentry to be created without stating in __init__
Idan Kamara <idankk86@gmail.com>
parents: 18213
diff changeset
   773
    def __init__(self, path, stat=True):
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   774
        self.path = path
18315
216230643ae2 filecache: allow filecacheentry to be created without stating in __init__
Idan Kamara <idankk86@gmail.com>
parents: 18213
diff changeset
   775
        self.cachestat = None
216230643ae2 filecache: allow filecacheentry to be created without stating in __init__
Idan Kamara <idankk86@gmail.com>
parents: 18213
diff changeset
   776
        self._cacheable = None
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   777
18315
216230643ae2 filecache: allow filecacheentry to be created without stating in __init__
Idan Kamara <idankk86@gmail.com>
parents: 18213
diff changeset
   778
        if stat:
216230643ae2 filecache: allow filecacheentry to be created without stating in __init__
Idan Kamara <idankk86@gmail.com>
parents: 18213
diff changeset
   779
            self.cachestat = filecacheentry.stat(self.path)
216230643ae2 filecache: allow filecacheentry to be created without stating in __init__
Idan Kamara <idankk86@gmail.com>
parents: 18213
diff changeset
   780
216230643ae2 filecache: allow filecacheentry to be created without stating in __init__
Idan Kamara <idankk86@gmail.com>
parents: 18213
diff changeset
   781
            if self.cachestat:
216230643ae2 filecache: allow filecacheentry to be created without stating in __init__
Idan Kamara <idankk86@gmail.com>
parents: 18213
diff changeset
   782
                self._cacheable = self.cachestat.cacheable()
216230643ae2 filecache: allow filecacheentry to be created without stating in __init__
Idan Kamara <idankk86@gmail.com>
parents: 18213
diff changeset
   783
            else:
216230643ae2 filecache: allow filecacheentry to be created without stating in __init__
Idan Kamara <idankk86@gmail.com>
parents: 18213
diff changeset
   784
                # None means we don't know yet
216230643ae2 filecache: allow filecacheentry to be created without stating in __init__
Idan Kamara <idankk86@gmail.com>
parents: 18213
diff changeset
   785
                self._cacheable = None
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   786
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   787
    def refresh(self):
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   788
        if self.cacheable():
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   789
            self.cachestat = filecacheentry.stat(self.path)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   790
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   791
    def cacheable(self):
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   792
        if self._cacheable is not None:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   793
            return self._cacheable
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   794
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   795
        # we don't know yet, assume it is for now
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   796
        return True
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   797
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   798
    def changed(self):
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   799
        # no point in going further if we can't cache it
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   800
        if not self.cacheable():
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   801
            return True
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   802
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   803
        newstat = filecacheentry.stat(self.path)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   804
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   805
        # 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
   806
        if newstat and self._cacheable is None:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   807
            self._cacheable = newstat.cacheable()
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   808
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   809
            # check again
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   810
            if not self._cacheable:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   811
                return True
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 != newstat:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   814
            self.cachestat = newstat
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   815
            return True
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   816
        else:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   817
            return False
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
    @staticmethod
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   820
    def stat(path):
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   821
        try:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   822
            return util.cachestat(path)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   823
        except OSError, e:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   824
            if e.errno != errno.ENOENT:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   825
                raise
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
class filecache(object):
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   828
    '''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
   829
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   830
    Records stat info when called in _filecache.
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   831
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   832
    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
   833
    the object when needed, updating the new stat info in _filecache.
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
    Mercurial either atomic renames or appends for files under .hg,
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   836
    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
   837
    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
   838
    recreating the object on every call (essentially the same behaviour as
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   839
    propertycache).'''
16198
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   840
    def __init__(self, path):
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   841
        self.path = path
16198
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   842
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   843
    def join(self, obj, fname):
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   844
        """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
   845
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   846
        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
   847
        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
   848
        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
   849
        """
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   850
        return obj.join(fname)
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   851
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   852
    def __call__(self, func):
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   853
        self.func = func
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   854
        self.name = func.__name__
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   855
        return self
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   856
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   857
    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
   858
        # 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
   859
        if self.name in obj.__dict__:
18316
f36375576ed5 filecache: create an entry in _filecache when __set__ is called for a missing one
Idan Kamara <idankk86@gmail.com>
parents: 18315
diff changeset
   860
            assert self.name in obj._filecache, self.name
16115
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   861
            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
   862
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   863
        entry = obj._filecache.get(self.name)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   864
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   865
        if entry:
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   866
            if entry.changed():
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   867
                entry.obj = self.func(obj)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   868
        else:
16198
fa8488565afd filecache: refactor path join logic to a function
Idan Kamara <idankk86@gmail.com>
parents: 16115
diff changeset
   869
            path = self.join(obj, self.path)
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   870
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   871
            # 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
   872
            # a writer modified between the time we read and stat
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   873
            entry = filecacheentry(path)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   874
            entry.obj = self.func(obj)
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   875
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   876
            obj._filecache[self.name] = entry
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   877
16115
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   878
        obj.__dict__[self.name] = entry.obj
14928
dca59d5be12d scmutil: introduce filecache
Idan Kamara <idankk86@gmail.com>
parents: 14861
diff changeset
   879
        return entry.obj
16115
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   880
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   881
    def __set__(self, obj, value):
18316
f36375576ed5 filecache: create an entry in _filecache when __set__ is called for a missing one
Idan Kamara <idankk86@gmail.com>
parents: 18315
diff changeset
   882
        if self.name not in obj._filecache:
f36375576ed5 filecache: create an entry in _filecache when __set__ is called for a missing one
Idan Kamara <idankk86@gmail.com>
parents: 18315
diff changeset
   883
            # we add an entry for the missing value because X in __dict__
f36375576ed5 filecache: create an entry in _filecache when __set__ is called for a missing one
Idan Kamara <idankk86@gmail.com>
parents: 18315
diff changeset
   884
            # implies X in _filecache
f36375576ed5 filecache: create an entry in _filecache when __set__ is called for a missing one
Idan Kamara <idankk86@gmail.com>
parents: 18315
diff changeset
   885
            ce = filecacheentry(self.join(obj, self.path), False)
f36375576ed5 filecache: create an entry in _filecache when __set__ is called for a missing one
Idan Kamara <idankk86@gmail.com>
parents: 18315
diff changeset
   886
            obj._filecache[self.name] = ce
f36375576ed5 filecache: create an entry in _filecache when __set__ is called for a missing one
Idan Kamara <idankk86@gmail.com>
parents: 18315
diff changeset
   887
        else:
f36375576ed5 filecache: create an entry in _filecache when __set__ is called for a missing one
Idan Kamara <idankk86@gmail.com>
parents: 18315
diff changeset
   888
            ce = obj._filecache[self.name]
f36375576ed5 filecache: create an entry in _filecache when __set__ is called for a missing one
Idan Kamara <idankk86@gmail.com>
parents: 18315
diff changeset
   889
f36375576ed5 filecache: create an entry in _filecache when __set__ is called for a missing one
Idan Kamara <idankk86@gmail.com>
parents: 18315
diff changeset
   890
        ce.obj = value # update cached copy
16115
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   891
        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
   892
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   893
    def __delete__(self, obj):
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   894
        try:
236bb604dc39 scmutil: update cached copy when filecached attribute is assigned (issue3263)
Idan Kamara <idankk86@gmail.com>
parents: 16068
diff changeset
   895
            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
   896
        except KeyError:
18177
203b7a759218 scmutil: clean up use of two-argument raise
Augie Fackler <raf@durin42.com>
parents: 17992
diff changeset
   897
            raise AttributeError(self.name)
18897
38982de2b4eb scmutil: migrate finddirs from dirstate
Bryan O'Sullivan <bryano@fb.com>
parents: 18865
diff changeset
   898
18898
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   899
class dirs(object):
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   900
    '''a multiset of directory names from a dirstate or manifest'''
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   901
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   902
    def __init__(self, map, skip=None):
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   903
        self._dirs = {}
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   904
        addpath = self.addpath
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   905
        if util.safehasattr(map, 'iteritems') and skip is not None:
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   906
            for f, s in map.iteritems():
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   907
                if s[0] != skip:
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   908
                    addpath(f)
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   909
        else:
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   910
            for f in map:
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   911
                addpath(f)
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   912
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   913
    def addpath(self, path):
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   914
        dirs = self._dirs
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   915
        for base in finddirs(path):
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   916
            if base in dirs:
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   917
                dirs[base] += 1
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   918
                return
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   919
            dirs[base] = 1
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   920
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   921
    def delpath(self, path):
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   922
        dirs = self._dirs
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   923
        for base in finddirs(path):
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   924
            if dirs[base] > 1:
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   925
                dirs[base] -= 1
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   926
                return
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   927
            del dirs[base]
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   928
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   929
    def __iter__(self):
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   930
        return self._dirs.iterkeys()
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   931
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   932
    def __contains__(self, d):
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   933
        return d in self._dirs
856960173630 scmutil: add a dirs class
Bryan O'Sullivan <bryano@fb.com>
parents: 18897
diff changeset
   934
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents: 18898
diff changeset
   935
if util.safehasattr(parsers, 'dirs'):
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents: 18898
diff changeset
   936
    dirs = parsers.dirs
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents: 18898
diff changeset
   937
18897
38982de2b4eb scmutil: migrate finddirs from dirstate
Bryan O'Sullivan <bryano@fb.com>
parents: 18865
diff changeset
   938
def finddirs(path):
38982de2b4eb scmutil: migrate finddirs from dirstate
Bryan O'Sullivan <bryano@fb.com>
parents: 18865
diff changeset
   939
    pos = path.rfind('/')
38982de2b4eb scmutil: migrate finddirs from dirstate
Bryan O'Sullivan <bryano@fb.com>
parents: 18865
diff changeset
   940
    while pos != -1:
38982de2b4eb scmutil: migrate finddirs from dirstate
Bryan O'Sullivan <bryano@fb.com>
parents: 18865
diff changeset
   941
        yield path[:pos]
38982de2b4eb scmutil: migrate finddirs from dirstate
Bryan O'Sullivan <bryano@fb.com>
parents: 18865
diff changeset
   942
        pos = path.rfind('/', 0, pos)