##// END OF EJS Templates
dirstate: add filecache support
dirstate: add filecache support

File last commit:

r16200:9d4a2942 stable
r16200:9d4a2942 stable
Show More
dirstate.py
737 lines | 23.8 KiB | text/x-python | PythonLexer
Martin Geisler
put license and copyright info into comment blocks
r8226 # dirstate.py - working directory tracking for mercurial
#
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Pierre-Yves David
dirstate: propagate IOError other than ENOENT when reading branch
r15799 import errno
mpm@selenic.com
Break apart hg.py...
r1089
Joel Rosdahl
Expand import * to allow Pyflakes to find problems
r6211 from node import nullid
Matt Mackall
Simplify i18n imports
r3891 from i18n import _
Adrian Buehlmann
move checkfilename from util to scmutil...
r13974 import scmutil, util, ignore, osutil, parsers, encoding
Simon Heimberg
separate import lines from mercurial and general python modules
r8312 import struct, os, stat, errno
Benoit Boissinot
remove unused imports
r9678 import cStringIO
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
dirstate: simplify state()
r4610 _format = ">cllll"
Matt Mackall
dirstate: use propertycache
r8261 propertycache = util.propertycache
Matt Mackall
dirstate: simplify state()
r4610
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 def _finddirs(path):
Matt Mackall
dirstate: improve performance for building _dirs
r7032 pos = path.rfind('/')
while pos != -1:
yield path[:pos]
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 pos = path.rfind('/', 0, pos)
Benoit Boissinot
dirstate._dirs: fix refcounting broken by 7dfac37cfabf...
r7096 def _incdirs(dirs, path):
for base in _finddirs(path):
if base in dirs:
dirs[base] += 1
return
dirs[base] = 1
def _decdirs(dirs, path):
for base in _finddirs(path):
if dirs[base] > 1:
dirs[base] -= 1
return
del dirs[base]
Eric Hopper
Convert all classes to new-style classes by deriving them from object.
r1559 class dirstate(object):
Benoit Boissinot
dirstate: refactor the dirstate binary format, remove magic numbers
r2393
Matt Mackall
dirstate: warn on invalid parents rather than aborting...
r13032 def __init__(self, opener, ui, root, validate):
Martin Geisler
dirstate: improve docstring formatting...
r10145 '''Create a new dirstate object.
opener is an open()-like callable that can be used to open the
dirstate file; root is the root of the directory tracked by
the dirstate.
'''
Matt Mackall
dirstate: hide internal vars...
r4614 self._opener = opener
Matt Mackall
dirstate: warn on invalid parents rather than aborting...
r13032 self._validate = validate
Matt Mackall
dirstate: hide internal vars...
r4614 self._root = root
Benoit Boissinot
performance: normalize self._root, avoid calling os.path.join() in dirstate...
r6972 self._rootdir = os.path.join(root, '')
Matt Mackall
dirstate: use True and false for _dirty
r4903 self._dirty = False
Matt Mackall
Merge with crew
r4965 self._dirtypl = False
Martin Geisler
Use explicit integer division...
r15791 self._lastnormaltime = 0
Matt Mackall
dirstate: hide internal vars...
r4614 self._ui = ui
Idan Kamara
dirstate: add filecache support
r16200 self._filecache = {}
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
dirstate: use propertycache
r8261 @propertycache
def _map(self):
Greg Ward
dirstate: add/improve method docstrings....
r9518 '''Return the dirstate contents as a map from filename to
(state, mode, size, time).'''
Matt Mackall
dirstate: use propertycache
r8261 self._read()
return self._map
@propertycache
def _copymap(self):
self._read()
return self._copymap
@propertycache
FUJIWARA Katsunori
icasefs: avoid normcase()-ing in util.fspath() for efficiency...
r15670 def _normroot(self):
return util.normcase(self._root)
@propertycache
Matt Mackall
dirstate: use propertycache
r8261 def _foldmap(self):
f = {}
for name in self._map:
Matt Mackall
dirstate: use util.normcase to build foldmap
r15550 f[util.normcase(name)] = name
FUJIWARA Katsunori
dirstate: prevent useless util.fspath() invocation for '.'...
r15668 f['.'] = '.' # prevents useless util.fspath() invocation
Matt Mackall
dirstate: use propertycache
r8261 return f
@propertycache
def _branch(self):
try:
Dan Villiom Podlaski Christiansen
prevent transient leaks of file handle by using new helper functions...
r14168 return self._opener.read("branch").strip() or "default"
Pierre-Yves David
dirstate: propagate IOError other than ENOENT when reading branch
r15799 except IOError, inst:
if inst.errno != errno.ENOENT:
raise
Matt Mackall
dirstate: use propertycache
r8261 return "default"
@propertycache
def _pl(self):
try:
Dan Villiom Podlaski Christiansen
explicitly close files...
r13400 fp = self._opener("dirstate")
st = fp.read(40)
fp.close()
Matt Mackall
dirstate: don't complain about 0-length files
r8716 l = len(st)
if l == 40:
Matt Mackall
dirstate: use propertycache
r8261 return st[:20], st[20:40]
Matt Mackall
dirstate: don't complain about 0-length files
r8716 elif l > 0 and l < 40:
Matt Mackall
dirstate: notice truncated parents read
r8640 raise util.Abort(_('working directory state appears damaged!'))
Matt Mackall
dirstate: use propertycache
r8261 except IOError, err:
Matt Mackall
many, many trivial check-code fixups
r10282 if err.errno != errno.ENOENT:
raise
Matt Mackall
dirstate: use propertycache
r8261 return [nullid, nullid]
@propertycache
def _dirs(self):
dirs = {}
Matt Mackall
many, many trivial check-code fixups
r10282 for f, s in self._map.iteritems():
Matt Mackall
dirstate: use propertycache
r8261 if s[0] != 'r':
_incdirs(dirs, f)
return dirs
FUJIWARA Katsunori
context: add 'dirs()' to changectx/workingctx for directory patterns...
r16143 def dirs(self):
return self._dirs
Matt Mackall
dirstate: use propertycache
r8261 @propertycache
def _ignore(self):
files = [self._join('.hgignore')]
for name, path in self._ui.configitems("ui"):
if name == 'ignore' or name.startswith('ignore.'):
Alexander Solovyov
make path expanding more consistent...
r9610 files.append(util.expandpath(path))
Matt Mackall
dirstate: use propertycache
r8261 return ignore.ignore(self._root, files, self._ui.warn)
@propertycache
def _slash(self):
return self._ui.configbool('ui', 'slash') and os.sep != '/'
@propertycache
def _checklink(self):
return util.checklink(self._root)
@propertycache
def _checkexec(self):
return util.checkexec(self._root)
@propertycache
def _checkcase(self):
return not util.checkcase(self._join('.hg'))
Matt Mackall
dirstate: make wjoin function private
r4905 def _join(self, f):
Benoit Boissinot
performance: normalize self._root, avoid calling os.path.join() in dirstate...
r6972 # much faster than os.path.join()
Benoit Boissinot
dirstate: explain why appending instead of os.path.join() is safe
r6973 # it's safe because f is always a relative path
Benoit Boissinot
performance: normalize self._root, avoid calling os.path.join() in dirstate...
r6972 return self._rootdir + f
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
windows: recompute flags when committing a merge (issue1802)...
r15337 def flagfunc(self, buildfallback):
if self._checklink and self._checkexec:
def f(x):
p = self._join(x)
if os.path.islink(p):
return 'l'
if util.isexec(p):
return 'x'
return ''
return f
fallback = buildfallback()
Matt Mackall
simplify flag handling...
r6743 if self._checklink:
def f(x):
Benoit Boissinot
performance: normalize self._root, avoid calling os.path.join() in dirstate...
r6972 if os.path.islink(self._join(x)):
Matt Mackall
simplify flag handling...
r6743 return 'l'
if 'x' in fallback(x):
return 'x'
return ''
return f
if self._checkexec:
def f(x):
if 'l' in fallback(x):
return 'l'
Adrian Buehlmann
rename util.is_exec to isexec
r14273 if util.isexec(self._join(x)):
Matt Mackall
simplify flag handling...
r6743 return 'x'
return ''
return f
Matt Mackall
windows: recompute flags when committing a merge (issue1802)...
r15337 else:
return fallback
Matt Mackall
simplify flag handling...
r6743
mpm@selenic.com
Break apart hg.py...
r1089 def getcwd(self):
cwd = os.getcwd()
Matt Mackall
many, many trivial check-code fixups
r10282 if cwd == self._root:
return ''
Matt Mackall
dirstate: hide internal vars...
r4614 # self._root ends with a path separator if self._root is '/' or 'C:\'
rootsep = self._root
Shun-ichi GOTO
Add endswithsep() and use it instead of using os.sep and os.altsep directly....
r5843 if not util.endswithsep(rootsep):
Alexis S. L. Carvalho
Fix handling of paths when run outside the repo....
r4230 rootsep += os.sep
if cwd.startswith(rootsep):
return cwd[len(rootsep):]
else:
# we're outside the repo. return an absolute path.
return cwd
mpm@selenic.com
Break apart hg.py...
r1089
Alexis S. L. Carvalho
Add dirstate.pathto and localrepo.pathto....
r4525 def pathto(self, f, cwd=None):
if cwd is None:
cwd = self.getcwd()
Matt Mackall
dirstate: hide internal vars...
r4614 path = util.pathto(self._root, cwd, f)
Alexis S. L. Carvalho
Add ui.slash hgrc setting...
r4527 if self._slash:
Shun-ichi GOTO
Use util.normpath() instead of direct path string operation....
r5842 return util.normpath(path)
Alexis S. L. Carvalho
Add ui.slash hgrc setting...
r4527 return path
Alexis S. L. Carvalho
Add dirstate.pathto and localrepo.pathto....
r4525
mpm@selenic.com
Break apart hg.py...
r1089 def __getitem__(self, key):
Greg Ward
dirstate: add/improve method docstrings....
r9518 '''Return the current state of key (a filename) in the dirstate.
Martin Geisler
dirstate: improve docstring formatting...
r10145
Greg Ward
dirstate: add/improve method docstrings....
r9518 States are:
n normal
m needs merging
r marked for removal
a marked for addition
? not tracked
'''
Matt Mackall
dirstate: add __contains__ and make __getitem__ more useful...
r4906 return self._map.get(key, ("?",))[0]
mpm@selenic.com
Break apart hg.py...
r1089
def __contains__(self, key):
Matt Mackall
dirstate: hide internal vars...
r4614 return key in self._map
def __iter__(self):
Matt Mackall
replace util.sort with sorted built-in...
r8209 for x in sorted(self._map):
Matt Mackall
dirstate: hide internal vars...
r4614 yield x
mpm@selenic.com
Break apart hg.py...
r1089
def parents(self):
Matt Mackall
dirstate: warn on invalid parents rather than aborting...
r13032 return [self._validate(p) for p in self._pl]
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
dirstate: add p1/p2 convenience methods
r13876 def p1(self):
return self._validate(self._pl[0])
def p2(self):
return self._validate(self._pl[1])
Matt Mackall
Move branch read/write to dirstate where it belongs
r4179 def branch(self):
Matt Mackall
branch: operate on branch names in local string space where possible...
r13047 return encoding.tolocal(self._branch)
Matt Mackall
Move branch read/write to dirstate where it belongs
r4179
mpm@selenic.com
Break apart hg.py...
r1089 def setparents(self, p1, p2=nullid):
Matt Mackall
Merge with crew
r4965 self._dirty = self._dirtypl = True
Matt Mackall
dirstate: hide internal vars...
r4614 self._pl = p1, p2
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
Move branch read/write to dirstate where it belongs
r4179 def setbranch(self, branch):
Wagner Bruna
branch: avoid using reserved tag names...
r10417 if branch in ['tip', '.', 'null']:
raise util.Abort(_('the name \'%s\' is reserved') % branch)
Matt Mackall
branch: operate on branch names in local string space where possible...
r13047 self._branch = encoding.fromlocal(branch)
Dan Villiom Podlaski Christiansen
prevent transient leaks of file handle by using new helper functions...
r14168 self._opener.write("branch", self._branch + '\n')
Matt Mackall
Move branch read/write to dirstate where it belongs
r4179
Matt Mackall
dirstate: hide some more internals
r4615 def _read(self):
Matt Mackall
dirstate: hide internal vars...
r4614 self._map = {}
self._copymap = {}
Matt Mackall
dirstate: fold parse into read
r4607 try:
Dan Villiom Podlaski Christiansen
prevent transient leaks of file handle by using new helper functions...
r14168 st = self._opener.read("dirstate")
Matt Mackall
dirstate: fold parse into read
r4607 except IOError, err:
Matt Mackall
many, many trivial check-code fixups
r10282 if err.errno != errno.ENOENT:
raise
Matt Mackall
dirstate: fold parse into read
r4607 return
if not st:
return
Dirkjan Ochtman
get rid of semi-colon introduced in 16bafcebd3d1
r7128 p = parsers.parse_dirstate(self._map, self._copymap, st)
Alexis S. L. Carvalho
add dirstate._dirtypl variable...
r4952 if not self._dirtypl:
Matt Mackall
dirstate: C parsing extension
r7093 self._pl = p
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
localrepo and dirstate: rename reload to invalidate...
r4613 def invalidate(self):
David Soria Parra
avoid .split() in for loops and use tuples instead...
r13200 for a in ("_map", "_copymap", "_foldmap", "_branch", "_pl", "_dirs",
"_ignore"):
Alexis S. L. Carvalho
dirstate.invalidate: avoid rebuilding _map...
r4953 if a in self.__dict__:
delattr(self, a)
Martin Geisler
Use explicit integer division...
r15791 self._lastnormaltime = 0
Matt Mackall
dirstate: use True and false for _dirty
r4903 self._dirty = False
Bryan O'Sullivan
When reloading the dirstate, recompute ignore information if needed.
r4375
mpm@selenic.com
Break apart hg.py...
r1089 def copy(self, source, dest):
Martin Geisler
dirstate: improve docstring formatting...
r10145 """Mark dest as a copy of source. Unmark dest if source is None."""
Patrick Mezard
Ignore dummy copies in dirstate and localrepo.filecommit()
r6680 if source == dest:
return
Matt Mackall
dirstate: use True and false for _dirty
r4903 self._dirty = True
Patrick Mezard
mq: drop copy records when refreshing regular patches (issue1441)...
r7566 if source is not None:
self._copymap[dest] = source
elif dest in self._copymap:
del self._copymap[dest]
mpm@selenic.com
Break apart hg.py...
r1089
def copied(self, file):
Matt Mackall
dirstate: hide internal vars...
r4614 return self._copymap.get(file, None)
Matt Mackall
dirstate: add copies function...
r3154
def copies(self):
Matt Mackall
dirstate: hide internal vars...
r4614 return self._copymap
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 def _droppath(self, f):
if self[f] not in "?r" and "_dirs" in self.__dict__:
Benoit Boissinot
dirstate._dirs: fix refcounting broken by 7dfac37cfabf...
r7096 _decdirs(self._dirs, f)
Vadim Gelfer
fix issue 322....
r2953
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 def _addpath(self, f, check=False):
Maxim Dounin
Fix file-changed-to-dir and dir-to-file commits (issue660)....
r5487 oldstate = self[f]
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 if check or oldstate == "r":
Adrian Buehlmann
move checkfilename from util to scmutil...
r13974 scmutil.checkfilename(f)
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 if f in self._dirs:
raise util.Abort(_('directory %r already in dirstate') % f)
# shadows
for d in _finddirs(f):
if d in self._dirs:
break
if d in self._map and self[d] != 'r':
raise util.Abort(
_('file %r in dirstate clashes with %r') % (d, f))
if oldstate in "?r" and "_dirs" in self.__dict__:
Benoit Boissinot
dirstate._dirs: fix refcounting broken by 7dfac37cfabf...
r7096 _incdirs(self._dirs, f)
Maxim Dounin
Fix file-changed-to-dir and dir-to-file commits (issue660)....
r5487
Matt Mackall
dirstate: break update into separate functions
r4904 def normal(self, f):
Martin Geisler
dirstate: improve docstring formatting...
r10145 '''Mark a file normal and clean.'''
Matt Mackall
dirstate: break update into separate functions
r4904 self._dirty = True
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 self._addpath(f)
Matt Mackall
dirstate: make wjoin function private
r4905 s = os.lstat(self._join(f))
Adrian Buehlmann
dirstate: check mtime when adding to _lastnormal...
r13754 mtime = int(s.st_mtime)
self._map[f] = ('n', s.st_mode, s.st_size, mtime)
Christian Ebert
Prefer i in d over d.has_key(i)
r5915 if f in self._copymap:
Matt Mackall
dirstate: break update into separate functions
r4904 del self._copymap[f]
Adrian Buehlmann
dirstate: eliminate _lastnormal set...
r13763 if mtime > self._lastnormaltime:
# Remember the most recent modification timeslot for status(),
Adrian Buehlmann
dirstate: check mtime when adding to _lastnormal...
r13754 # to make sure we won't miss future size-preserving file content
# modifications that happen within the same timeslot.
Adrian Buehlmann
dirstate: eliminate _lastnormal set...
r13763 self._lastnormaltime = mtime
Greg Ward
dirstate: avoid a race with multiple commits in the same process...
r13704
Alexis S. L. Carvalho
merge: forcefully mark files that we get from the second parent as dirty...
r5210 def normallookup(self, f):
Martin Geisler
dirstate: improve docstring formatting...
r10145 '''Mark a file normal, but possibly dirty.'''
Alexis S. L. Carvalho
normallookup: during merges, restore the state saved by remove
r6298 if self._pl[1] != nullid and f in self._map:
# if there is a merge going on and the file was either
Benoit Boissinot
dirstate: more explicit name, rename normaldirty() to otherparent()
r10968 # in state 'm' (-1) or coming from other parent (-2) before
# being removed, restore that state.
Alexis S. L. Carvalho
normallookup: during merges, restore the state saved by remove
r6298 entry = self._map[f]
if entry[0] == 'r' and entry[2] in (-1, -2):
source = self._copymap.get(f)
if entry[2] == -1:
self.merge(f)
elif entry[2] == -2:
Benoit Boissinot
dirstate: more explicit name, rename normaldirty() to otherparent()
r10968 self.otherparent(f)
Alexis S. L. Carvalho
normallookup: during merges, restore the state saved by remove
r6298 if source:
self.copy(source, f)
return
if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2:
return
Matt Mackall
dirstate: use True and false for _dirty
r4903 self._dirty = True
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 self._addpath(f)
Matt Mackall
dirstate: C parsing extension
r7093 self._map[f] = ('n', 0, -1, -1)
Alexis S. L. Carvalho
merge: forcefully mark files that we get from the second parent as dirty...
r5210 if f in self._copymap:
del self._copymap[f]
Benoit Boissinot
dirstate: more explicit name, rename normaldirty() to otherparent()
r10968 def otherparent(self, f):
'''Mark as coming from the other parent, always dirty.'''
if self._pl[1] == nullid:
raise util.Abort(_("setting %r to other parent "
"only allowed in merges") % f)
Alexis S. L. Carvalho
merge: forcefully mark files that we get from the second parent as dirty...
r5210 self._dirty = True
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 self._addpath(f)
Matt Mackall
dirstate: C parsing extension
r7093 self._map[f] = ('n', 0, -2, -1)
Matt Mackall
dirstate: break update into separate functions
r4904 if f in self._copymap:
del self._copymap[f]
def add(self, f):
Martin Geisler
dirstate: improve docstring formatting...
r10145 '''Mark a file added.'''
Matt Mackall
dirstate: break update into separate functions
r4904 self._dirty = True
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 self._addpath(f, True)
Matt Mackall
dirstate: C parsing extension
r7093 self._map[f] = ('a', 0, -1, -1)
Matt Mackall
dirstate: break update into separate functions
r4904 if f in self._copymap:
del self._copymap[f]
Matt Mackall
dirstate: refactor checkinterfering
r4616
Matt Mackall
dirstate: break update into separate functions
r4904 def remove(self, f):
Martin Geisler
dirstate: improve docstring formatting...
r10145 '''Mark a file removed.'''
Matt Mackall
dirstate: break update into separate functions
r4904 self._dirty = True
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 self._droppath(f)
Alexis S. L. Carvalho
dirstate.remove: during merges, remember the previous file state...
r6297 size = 0
if self._pl[1] != nullid and f in self._map:
Benoit Boissinot
dirstate: more explicit name, rename normaldirty() to otherparent()
r10968 # backup the previous state
Alexis S. L. Carvalho
dirstate.remove: during merges, remember the previous file state...
r6297 entry = self._map[f]
Benoit Boissinot
dirstate: more explicit name, rename normaldirty() to otherparent()
r10968 if entry[0] == 'm': # merge
Alexis S. L. Carvalho
dirstate.remove: during merges, remember the previous file state...
r6297 size = -1
Benoit Boissinot
dirstate: more explicit name, rename normaldirty() to otherparent()
r10968 elif entry[0] == 'n' and entry[2] == -2: # other parent
Alexis S. L. Carvalho
dirstate.remove: during merges, remember the previous file state...
r6297 size = -2
Matt Mackall
dirstate: C parsing extension
r7093 self._map[f] = ('r', 0, size, 0)
Alexis S. L. Carvalho
dirstate.remove: during merges, remember the previous file state...
r6297 if size == 0 and f in self._copymap:
Matt Mackall
dirstate: break update into separate functions
r4904 del self._copymap[f]
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
dirstate: break update into separate functions
r4904 def merge(self, f):
Martin Geisler
dirstate: improve docstring formatting...
r10145 '''Mark a file merged.'''
Matt Mackall
dirstate: use True and false for _dirty
r4903 self._dirty = True
Matt Mackall
dirstate: make wjoin function private
r4905 s = os.lstat(self._join(f))
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 self._addpath(f)
Matt Mackall
dirstate: always add times to map as integers...
r7119 self._map[f] = ('m', s.st_mode, s.st_size, int(s.st_mtime))
Matt Mackall
dirstate: break update into separate functions
r4904 if f in self._copymap:
del self._copymap[f]
Matt Mackall
dirstate: rename forget to drop...
r14434 def drop(self, f):
'''Drop a file from the dirstate'''
Matt Mackall
dirstate: don't fail when dropping a not-tracked file (issue3080)...
r15399 if f in self._map:
self._dirty = True
self._droppath(f)
del self._map[f]
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
dirstate: introduce a public case normalizing method
r13717 def _normalize(self, path, isknown):
Matt Mackall
dirstate: fix case-folding identity for traditional Unix...
r15488 normed = util.normcase(path)
Matt Mackall
dirstate: introduce a public case normalizing method
r13717 folded = self._foldmap.get(normed, None)
if folded is None:
if isknown or not os.path.lexists(os.path.join(self._root, path)):
folded = path
Petr Kodl
issue 1286: dirstat regression on case folding systems...
r7068 else:
Matt Mackall
dirstate: introduce a public case normalizing method
r13717 folded = self._foldmap.setdefault(normed,
FUJIWARA Katsunori
icasefs: avoid normcase()-ing in util.fspath() for efficiency...
r15670 util.fspath(normed, self._normroot))
Matt Mackall
dirstate: introduce a public case normalizing method
r13717 return folded
def normalize(self, path, isknown=False):
'''
normalize the case of a pathname when on a casefolding filesystem
isknown specifies whether the filename came from walking the
disk, to avoid extra filesystem access
The normalized case is determined based on the following precedence:
- version of name already stored in the dirstate
- version of name stored on disk
- version provided via command arguments
'''
if self._checkcase:
return self._normalize(path, isknown)
return path
Paul Moore
Add a normalize() method to dirstate...
r6677
Alexis S. L. Carvalho
dirstate: fix rebuild; add a test...
r5065 def clear(self):
self._map = {}
Maxim Dounin
Fix file-changed-to-dir and dir-to-file commits (issue660)....
r5487 if "_dirs" in self.__dict__:
Benoit Boissinot
fix coding style (reported by pylint)
r10394 delattr(self, "_dirs")
Alexis S. L. Carvalho
dirstate: fix rebuild; add a test...
r5065 self._copymap = {}
self._pl = [nullid, nullid]
Martin Geisler
Use explicit integer division...
r15791 self._lastnormaltime = 0
Alexis S. L. Carvalho
merge with crew-stable
r5123 self._dirty = True
Alexis S. L. Carvalho
dirstate: fix rebuild; add a test...
r5065
Benoit Boissinot
add 'debugrebuildstate' to rebuild the dirstate from a given revision...
r1755 def rebuild(self, parent, files):
Alexis S. L. Carvalho
dirstate: fix rebuild; add a test...
r5065 self.clear()
Matt Mackall
Start using manifestflags methods
r2832 for f in files:
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 if 'x' in files.flags(f):
Matt Mackall
dirstate: C parsing extension
r7093 self._map[f] = ('n', 0777, -1, 0)
Benoit Boissinot
add 'debugrebuildstate' to rebuild the dirstate from a given revision...
r1755 else:
Matt Mackall
dirstate: C parsing extension
r7093 self._map[f] = ('n', 0666, -1, 0)
Matt Mackall
dirstate: hide internal vars...
r4614 self._pl = (parent, nullid)
Matt Mackall
dirstate: use True and false for _dirty
r4903 self._dirty = True
mpm@selenic.com
Break apart hg.py...
r1089
def write(self):
Matt Mackall
dirstate: simplify dirty handling
r4612 if not self._dirty:
Benoit Boissinot
only write the dirstate when something changed
r1794 return
Alexis S. L. Carvalho
dirstate: ignore stat data for files that were updated too recently...
r6326 st = self._opener("dirstate", "w", atomictemp=True)
Matt Mackall
dirstate: refactor granularity code, add a test...
r6327
Adrian Buehlmann
dirstate: kill dirstate.granularity config option...
r9509 # use the modification time of the newly created temporary file as the
# filesystem's notion of 'now'
now = int(util.fstat(st).st_mtime)
Benoit Boissinot
dirstate: no need to iterate twice, a dict can be updated in place
r10865
cs = cStringIO.StringIO()
copymap = self._copymap
pack = struct.pack
write = cs.write
write("".join(self._pl))
for f, e in self._map.iteritems():
Adrian Buehlmann
dirstate: kill dirstate.granularity config option...
r9509 if e[0] == 'n' and e[3] == now:
# The file was last modified "simultaneously" with the current
# write to dirstate (i.e. within the same second for file-
# systems with a granularity of 1 sec). This commonly happens
# for at least a couple of files on 'update'.
# The user could change the file without changing its size
# within the same second. Invalidate the file's stat data in
# dirstate, forcing future 'status' calls to compare the
# contents of the file. This prevents mistakenly treating such
# files as clean.
Benoit Boissinot
dirstate: no need to iterate twice, a dict can be updated in place
r10865 e = (e[0], 0, -1, -1) # mark entry as 'unset'
self._map[f] = e
Adrian Buehlmann
dirstate: kill dirstate.granularity config option...
r9509
Benoit Boissinot
dirstate: fix in memory dirstate entries for 1-second race...
r10836 if f in copymap:
f = "%s\0%s" % (f, copymap[f])
Matt Mackall
dirstate: speed up read and write...
r5327 e = pack(_format, e[0], e[1], e[2], e[3], len(f))
write(e)
write(f)
Bryan O'Sullivan
dirstate: speed up write by 50%.
r4374 st.write(cs.getvalue())
Greg Ward
atomictempfile: make close() consistent with other file-like objects....
r15057 st.close()
Martin Geisler
Use explicit integer division...
r15791 self._lastnormaltime = 0
Matt Mackall
Merge with crew
r4965 self._dirty = self._dirtypl = False
mpm@selenic.com
Break apart hg.py...
r1089
Alexis S. L. Carvalho
dirstate: don't walk ignored directories...
r6032 def _dirignore(self, f):
Patrick Mezard
dirstate: do not ignore current directory '.' (issue 1078)
r6479 if f == '.':
return False
Alexis S. L. Carvalho
dirstate: don't walk ignored directories...
r6032 if self._ignore(f):
return True
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 for p in _finddirs(f):
if self._ignore(p):
Alexis S. L. Carvalho
dirstate: don't walk ignored directories...
r6032 return True
return False
Augie Fackler
dirstate: don't check state of subrepo directories
r10176 def walk(self, match, subrepos, unknown, ignored):
Matt Mackall
simplify dirstate walking...
r3529 '''
Greg Ward
dirstate: add/improve method docstrings....
r9518 Walk recursively through the directory tree, finding all files
matched by match.
Matt Mackall
simplify dirstate walking...
r3529
Greg Ward
dirstate: add/improve method docstrings....
r9518 Return a dict mapping filename to stat-like object (either
mercurial.osutil.stat instance or return value of os.stat()).
Matt Mackall
simplify dirstate walking...
r3529 '''
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
walk: begin refactoring badmatch handling
r6578 def fwarn(f, msg):
Benoit Boissinot
dirstate: use the right variable (f, not ff)
r7023 self._ui.warn('%s: %s\n' % (self.pathto(f), msg))
Matt Mackall
walk: begin refactoring badmatch handling
r6578 return False
Matt Mackall
walk: use match.bad callback for filetype messages
r8681 def badtype(mode):
Simon Heimberg
dirstate: translate forgotten string
r8310 kind = _('unknown')
Matt Mackall
many, many trivial check-code fixups
r10282 if stat.S_ISCHR(mode):
kind = _('character device')
elif stat.S_ISBLK(mode):
kind = _('block device')
elif stat.S_ISFIFO(mode):
kind = _('fifo')
elif stat.S_ISSOCK(mode):
kind = _('socket')
elif stat.S_ISDIR(mode):
kind = _('directory')
Matt Mackall
walk: use match.bad callback for filetype messages
r8681 return _('unsupported file type (type is %s)') % kind
Matt Mackall
dirstate.walk: fold in _supported...
r6830
Matt Mackall
dirstate: move ignore to its own file
r4609 ignore = self._ignore
Alexis S. L. Carvalho
dirstate: don't walk ignored directories...
r6032 dirignore = self._dirignore
Alexis S. L. Carvalho
dirstate.statwalk: explicitly test for ignored directories...
r4193 if ignored:
ignore = util.never
Alexis S. L. Carvalho
dirstate: don't walk ignored directories...
r6032 dirignore = util.never
Benoit Boissinot
performance: do not stat() things when not required...
r6971 elif not unknown:
# if unknown and ignored are False, skip step 2
ignore = util.always
dirignore = util.always
Matt Mackall
Simplify ignore logic in dirstate.walk...
r3534
Matt Mackall
dirstate.walk: speed up calling match function
r6834 matchfn = match.matchfn
Matt Mackall
walk: we always have a badfn
r8676 badfn = match.bad
Matt Mackall
dirstate.walk: more cleanups...
r6831 dmap = self._map
Matt Mackall
dirstate: localize a bunch of methods for findfiles
r5000 normpath = util.normpath
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 listdir = osutil.listdir
Matt Mackall
dirstate: localize a bunch of methods for findfiles
r5000 lstat = os.lstat
Matt Mackall
dirstate.walk: fold in _supported...
r6830 getkind = stat.S_IFMT
Matt Mackall
dirstate.walk: minor cleanups...
r6828 dirkind = stat.S_IFDIR
Matt Mackall
dirstate.walk: fold in _supported...
r6830 regkind = stat.S_IFREG
lnkkind = stat.S_IFLNK
Matt Mackall
dirstate.walk: more cleanups...
r6831 join = self._join
Matt Mackall
dirstate.walk: fold findfiles into main walk loop
r6820 work = []
wadd = work.append
Matt Mackall
match: fold plan cases down to two special cases...
r8684 exact = skipstep3 = False
if matchfn == match.exact: # match.exact
Matt Mackall
walk: refactor walk plan...
r8683 exact = True
Matt Mackall
match: fold plan cases down to two special cases...
r8684 dirignore = util.always # skip step 2
elif match.files() and not match.anypats(): # match.match, no patterns
skipstep3 = True
Simon Heimberg
dirstate: skip step 3 in walk if nothing new will match...
r8589
Matt Mackall
dirstate: skip optimization on case-folding FS (issue2440)
r12907 if self._checkcase:
normalize = self._normalize
skipstep3 = False
else:
normalize = lambda x, y: x
Martin Geisler
dirstate: use one pass to filter out files in subrepos
r12211 files = sorted(match.files())
subrepos.sort()
i, j = 0, 0
while i < len(files) and j < len(subrepos):
subpath = subrepos[j] + "/"
Oleg Stepanov
subrepo: do not report known files inside repositories as unknown
r13233 if files[i] < subpath:
Martin Geisler
dirstate: use one pass to filter out files in subrepos
r12211 i += 1
continue
trbs
subrepo: fix pruning of subrepo filenames in dirstate (issue2619)
r13339 while i < len(files) and files[i].startswith(subpath):
Martin Geisler
dirstate: use one pass to filter out files in subrepos
r12211 del files[i]
j += 1
Matt Mackall
dirstate.walk: more cleanups...
r6831 if not files or '.' in files:
files = ['']
Augie Fackler
dirstate: don't check state of subrepo directories
r10176 results = dict.fromkeys(subrepos)
results['.hg'] = None
Matt Mackall
dirstate: localize a bunch of methods for findfiles
r5000
Matt Mackall
dirstate.walk: pull directory scanning into top-level loop
r6826 # step 1: find all explicit files
Martin Geisler
dirstate: use one pass to filter out files in subrepos
r12211 for ff in files:
Patrick Mezard
dirstate: fix typo introduced by 3507f6c7715c
r8804 nf = normalize(normpath(ff), False)
Matt Mackall
dirstate.walk: build a dict rather than yield...
r6829 if nf in results:
Matt Mackall
dirstate.walk: fold findfiles into main walk loop
r6820 continue
try:
Matt Mackall
dirstate.walk: more cleanups...
r6831 st = lstat(join(nf))
Matt Mackall
dirstate.walk: fold in _supported...
r6830 kind = getkind(st.st_mode)
if kind == dirkind:
Matt Mackall
match: fold plan cases down to two special cases...
r8684 skipstep3 = False
Simon Heimberg
dirstate: set more states in step 1 of walk
r8588 if nf in dmap:
Martin Geisler
dirstate: fixed typo in comment
r8645 #file deleted on disk but still in dirstate
Simon Heimberg
dirstate: set more states in step 1 of walk
r8588 results[nf] = None
Matt Mackall
dirstate: more accurate use of match.dir callback
r8708 match.dir(nf)
Matt Mackall
dirstate.walk: minor cleanups...
r6828 if not dirignore(nf):
wadd(nf)
Matt Mackall
backout most of 4f8067c94729
r12401 elif kind == regkind or kind == lnkkind:
Matt Mackall
dirstate.walk: fold in _supported...
r6830 results[nf] = st
Matt Mackall
dirstate.walk: minor cleanups...
r6828 else:
Matt Mackall
walk: use match.bad callback for filetype messages
r8681 badfn(ff, badtype(kind))
Matt Mackall
dirstate.walk: fold in _supported...
r6830 if nf in dmap:
Matt Mackall
dirstate.walk: build a dict rather than yield...
r6829 results[nf] = None
Matt Mackall
dirstate.walk: fold findfiles into main walk loop
r6820 except OSError, inst:
Matt Mackall
walk: simplify check for missing file
r8675 if nf in dmap: # does it exactly match a file?
results[nf] = None
else: # does it match a directory?
prefix = nf + "/"
for fn in dmap:
if fn.startswith(prefix):
Matt Mackall
dirstate: more accurate use of match.dir callback
r8708 match.dir(nf)
Matt Mackall
match: fold plan cases down to two special cases...
r8684 skipstep3 = False
Matt Mackall
walk: simplify check for missing file
r8675 break
Matt Mackall
walk: simplify logic for badfn clause...
r8677 else:
Matt Mackall
match: ignore return of match.bad...
r8680 badfn(ff, inst.strerror)
Matt Mackall
dirstate.walk: fold findfiles into main walk loop
r6820
Matt Mackall
dirstate.walk: pull directory scanning into top-level loop
r6826 # step 2: visit subdirectories
while work:
nd = work.pop()
Benoit Boissinot
dirstate.walk: skip unreadable directories (issue1213)...
r7099 skip = None
Matt Mackall
dirstate.walk: pull directory scanning into top-level loop
r6826 if nd == '.':
nd = ''
else:
Benoit Boissinot
dirstate.walk: skip unreadable directories (issue1213)...
r7099 skip = '.hg'
try:
entries = listdir(join(nd), stat=True, skip=skip)
except OSError, inst:
if inst.errno == errno.EACCES:
fwarn(nd, inst.strerror)
continue
raise
Matt Mackall
dirstate.walk: pull directory scanning into top-level loop
r6826 for f, kind, st in entries:
Petr Kodl
issue 1286: dirstat regression on case folding systems...
r7068 nf = normalize(nd and (nd + "/" + f) or f, True)
Matt Mackall
dirstate.walk: build a dict rather than yield...
r6829 if nf not in results:
Matt Mackall
dirstate.walk: minor cleanups...
r6828 if kind == dirkind:
if not ignore(nf):
Matt Mackall
dirstate: more accurate use of match.dir callback
r8708 match.dir(nf)
Matt Mackall
dirstate.walk: minor cleanups...
r6828 wadd(nf)
Matt Mackall
dirstate.walk: speed up calling match function
r6834 if nf in dmap and matchfn(nf):
Matt Mackall
dirstate.walk: build a dict rather than yield...
r6829 results[nf] = None
Matt Mackall
dirstate.walk: inline imatch...
r6832 elif kind == regkind or kind == lnkkind:
if nf in dmap:
Matt Mackall
dirstate.walk: speed up calling match function
r6834 if matchfn(nf):
Matt Mackall
dirstate.walk: inline imatch...
r6832 results[nf] = st
Matt Mackall
dirstate.walk: speed up calling match function
r6834 elif matchfn(nf) and not ignore(nf):
Matt Mackall
dirstate.walk: build a dict rather than yield...
r6829 results[nf] = st
Matt Mackall
dirstate.walk: speed up calling match function
r6834 elif nf in dmap and matchfn(nf):
Matt Mackall
dirstate.walk: inline imatch...
r6832 results[nf] = None
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
dirstate.walk: pull directory scanning into top-level loop
r6826 # step 3: report unseen items in the dmap hash
Matt Mackall
match: fold plan cases down to two special cases...
r8684 if not skipstep3 and not exact:
Simon Heimberg
dirstate: skip step 3 in walk if nothing new will match...
r8589 visit = sorted([f for f in dmap if f not in results and matchfn(f)])
for nf, st in zip(visit, util.statfiles([join(i) for i in visit])):
if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
st = None
results[nf] = st
Augie Fackler
dirstate: don't check state of subrepo directories
r10176 for s in subrepos:
del results[s]
Matt Mackall
dirstate.walk: more cleanups...
r6831 del results['.hg']
Matt Mackall
dirstate.walk: build a dict rather than yield...
r6829 return results
mpm@selenic.com
Break apart hg.py...
r1089
Augie Fackler
dirstate: don't check state of subrepo directories
r10176 def status(self, match, subrepos, ignored, clean, unknown):
Greg Ward
dirstate: add/improve method docstrings....
r9518 '''Determine the status of the working copy relative to the
dirstate and return a tuple of lists (unsure, modified, added,
removed, deleted, unknown, ignored, clean), where:
unsure:
files that might have been modified since the dirstate was
written, but need to be read to be sure (size is the same
but mtime differs)
modified:
files that have definitely been modified since the dirstate
was written (different size or mode)
added:
files that have been explicitly added with hg add
removed:
files that have been explicitly removed with hg remove
deleted:
files that have been deleted through other means ("missing")
unknown:
files not in the dirstate that are not ignored
ignored:
files not in the dirstate that are ignored
(by _dirignore())
clean:
files that have definitely not been modified since the
dirstate was written
'''
Matt Mackall
repo.status: eliminate list_
r6753 listignored, listclean, listunknown = ignored, clean, unknown
Thomas Arendsen Hein
New option -i/--ignored for 'hg status' to show ignored files....
r2022 lookup, modified, added, unknown, ignored = [], [], [], [], []
Vadim Gelfer
status: add -c (clean) and -A (all files) options...
r2661 removed, deleted, clean = [], [], []
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 dmap = self._map
Greg Ward
dirstate: add/improve method docstrings....
r9518 ladd = lookup.append # aka "unsure"
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 madd = modified.append
aadd = added.append
uadd = unknown.append
iadd = ignored.append
radd = removed.append
dadd = deleted.append
cadd = clean.append
Martin Geisler
dirstate: ignore symlinks when fs cannot handle them (issue1888)...
r11769 lnkkind = stat.S_IFLNK
Augie Fackler
dirstate: don't check state of subrepo directories
r10176 for fn, st in self.walk(match, subrepos, listunknown,
listignored).iteritems():
Matt Mackall
dirstate: minor status cleanups
r6591 if fn not in dmap:
Matt Mackall
repo.status: eliminate list_
r6753 if (listignored or match.exact(fn)) and self._dirignore(fn):
if listignored:
Alexis S. L. Carvalho
dirstate.status: avoid putting ignored files in the unknown list...
r6033 iadd(fn)
Matt Mackall
repo.status: eliminate list_
r6753 elif listunknown:
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 uadd(fn)
Benoit Boissinot
rewrote changes function in dirstate to use generic walk code...
r1471 continue
Matt Mackall
dirstate: minor status cleanups
r6591
Matt Mackall
dirstate: C parsing extension
r7093 state, mode, size, time = dmap[fn]
Matt Mackall
dirstate: minor status cleanups
r6591
Matt Mackall
dirstate.walk: eliminate src from yield...
r6818 if not st and state in "nma":
dadd(fn)
elif state == 'n':
Martin Geisler
dirstate: ignore symlinks when fs cannot handle them (issue1888)...
r11769 # The "mode & lnkkind != lnkkind or self._checklink"
# lines are an expansion of "islink => checklink"
# where islink means "is this a link?" and checklink
# means "can we check links?".
Adrian Buehlmann
dirstate: eliminate _lastnormal set...
r13763 mtime = int(st.st_mtime)
Alexis S. L. Carvalho
dirstate: ignore mode changes if the fs does not supports the exec bit...
r6257 if (size >= 0 and
(size != st.st_size
or ((mode ^ st.st_mode) & 0100 and self._checkexec))
Martin Geisler
dirstate: ignore symlinks when fs cannot handle them (issue1888)...
r11769 and (mode & lnkkind != lnkkind or self._checklink)
Benoit Boissinot
dirstate: more explicit name, rename normaldirty() to otherparent()
r10968 or size == -2 # other parent
Alexis S. L. Carvalho
dirstate.status: if a file is marked as copied, consider it modified...
r4677 or fn in self._copymap):
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 madd(fn)
Adrian Buehlmann
dirstate: eliminate _lastnormal set...
r13763 elif (mtime != time
Martin Geisler
dirstate: ignore symlinks when fs cannot handle them (issue1888)...
r11769 and (mode & lnkkind != lnkkind or self._checklink)):
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 ladd(fn)
Adrian Buehlmann
dirstate: eliminate _lastnormal set...
r13763 elif mtime == self._lastnormaltime:
# fn may have been changed in the same timeslot without
# changing its size. This can happen if we quickly do
# multiple commits in a single transaction.
# Force lookup, so we don't miss such a racy file change.
Greg Ward
dirstate: avoid a race with multiple commits in the same process...
r13704 ladd(fn)
Matt Mackall
repo.status: eliminate list_
r6753 elif listclean:
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 cadd(fn)
Matt Mackall
status: rename type_ to state
r6590 elif state == 'm':
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 madd(fn)
Matt Mackall
status: rename type_ to state
r6590 elif state == 'a':
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 aadd(fn)
Matt Mackall
status: rename type_ to state
r6590 elif state == 'r':
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 radd(fn)
mason@suse.com
Optimize dirstate walking...
r1183
Vadim Gelfer
status: add -c (clean) and -A (all files) options...
r2661 return (lookup, modified, added, removed, deleted, unknown, ignored,
clean)