##// END OF EJS Templates
rust-status: update rust-cpython bridge to account for the changes in core...
rust-status: update rust-cpython bridge to account for the changes in core Differential Revision: https://phab.mercurial-scm.org/D7930

File last commit:

r44833:bed8d08c default
r45016:f96b28aa default
Show More
dirstate.py
1866 lines | 63.7 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.
mpm@selenic.com
Break apart hg.py...
r1089
Gregory Szorc
dirstate: use absolute_import
r27503 from __future__ import absolute_import
Laurent Charignon
dirstate: add a way to get the ignore file/line matching an ignored file...
r27670 import collections
Augie Fackler
dirstate: introduce new context manager for marking dirstate parent changes
r32346 import contextlib
Gregory Szorc
dirstate: use absolute_import
r27503 import errno
import os
import stat
from .i18n import _
from .node import nullid
Gregory Szorc
py3: manually import pycompat.delattr where it is needed...
r43360 from .pycompat import delattr
Augie Fackler
dirstate: add some traces on listdir calls...
r43533
from hgdemandimport import tracing
Gregory Szorc
dirstate: use absolute_import
r27503 from . import (
encoding,
error,
match as matchmod,
pathutil,
Yuya Nishihara
parsers: switch to policy importer...
r32372 policy,
Pulkit Goyal
py3: use pycompat.ossep at certain places...
r30304 pycompat,
Gregory Szorc
dirstate: use absolute_import
r27503 scmutil,
FUJIWARA Katsunori
txnutil: factor out the logic to read file in according to HG_PENDING...
r31050 txnutil,
Gregory Szorc
dirstate: use absolute_import
r27503 util,
)
mpm@selenic.com
Break apart hg.py...
r1089
Augie Fackler
interfaces: introduce an interface for dirstate implementations...
r43197 from .interfaces import (
dirstate as intdirstate,
util as interfaceutil,
)
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 parsers = policy.importmod('parsers')
rustmod = policy.importrust('dirstate')
Yuya Nishihara
parsers: switch to policy importer...
r32372
Matt Mackall
dirstate: use propertycache
r8261 propertycache = util.propertycache
Idan Kamara
dirstate: filecacheify _branch...
r16201 filecache = scmutil.filecache
Augie Fackler
formatting: blacken the codebase...
r43346 _rangemask = 0x7FFFFFFF
Idan Kamara
dirstate: filecacheify _branch...
r16201
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000 dirstatetuple = parsers.dirstatetuple
Siddharth Agarwal
dirstate: add dirstatetuple to create dirstate values...
r21808
Augie Fackler
formatting: blacken the codebase...
r43346
Idan Kamara
dirstate: filecacheify _branch...
r16201 class repocache(filecache):
"""filecache for files in .hg/"""
Augie Fackler
formatting: blacken the codebase...
r43346
Idan Kamara
dirstate: filecacheify _branch...
r16201 def join(self, obj, fname):
return obj._opener.join(fname)
Matt Mackall
dirstate: simplify state()
r4610
Augie Fackler
formatting: blacken the codebase...
r43346
Idan Kamara
dirstate: filecacheify _ignore (issue3278)...
r16202 class rootcache(filecache):
"""filecache for files in the repository root"""
Augie Fackler
formatting: blacken the codebase...
r43346
Idan Kamara
dirstate: filecacheify _ignore (issue3278)...
r16202 def join(self, obj, fname):
return obj._join(fname)
Augie Fackler
formatting: blacken the codebase...
r43346
FUJIWARA Katsunori
dirstate: make writing in-memory changes aware of transaction activity...
r26634 def _getfsnow(vfs):
'''Get "now" timestamp on filesystem'''
tmpfd, tmpname = vfs.mkstemp()
try:
Augie Fackler
cleanup: use stat_result[stat.ST_MTIME] instead of stat_result.st_mtime...
r36799 return os.fstat(tmpfd)[stat.ST_MTIME]
FUJIWARA Katsunori
dirstate: make writing in-memory changes aware of transaction activity...
r26634 finally:
os.close(tmpfd)
vfs.unlink(tmpname)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
interfaces: introduce an interface for dirstate implementations...
r43197 @interfaceutil.implementer(intdirstate.idirstate)
Eric Hopper
Convert all classes to new-style classes by deriving them from object.
r1559 class dirstate(object):
Gregory Szorc
dirstate: expose a sparse matcher on dirstate (API)...
r33373 def __init__(self, opener, ui, root, validate, sparsematchfn):
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
Gregory Szorc
dirstate: expose a sparse matcher on dirstate (API)...
r33373 self._sparsematchfn = sparsematchfn
Yuya Nishihara
dirstate: make sure rootdir ends with directory separator (issue4557)...
r24198 # ntpath.join(root, '') of Python 2.7.9 does not add sep if root is
# UNC path pointing to root share (issue4557)
FUJIWARA Katsunori
dirstate: use pathutil.normasprefix to ensure os.sep at the end of root...
r24833 self._rootdir = pathutil.normasprefix(root)
Matt Mackall
dirstate: use True and false for _dirty
r4903 self._dirty = 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 = {}
Durham Goode
dirstate: add begin/endparentchange to dirstate...
r22404 self._parentwriters = 0
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._filename = b'dirstate'
self._pendingfilename = b'%s.pending' % self._filename
Mateusz Kwapich
dirstate: add callback to notify extensions about wd parent change...
r29772 self._plchangecallbacks = {}
self._origpl = None
Durham Goode
dirstate: track updated files to improve write time...
r31206 self._updatedfiles = set()
Mark Thomas
dirstate: make map implementation overridable...
r35085 self._mapcls = dirstatemap
Martin von Zweigbergk
dirstate: call and cache os.getcwd() in constructor...
r41823 # Access and cache cwd early, so we don't access it for the first time
# after a working-copy update caused it to not exist (accessing it then
# raises an exception).
self._cwd
Durham Goode
dirstate: add begin/endparentchange to dirstate...
r22404
Augie Fackler
dirstate: introduce new context manager for marking dirstate parent changes
r32346 @contextlib.contextmanager
def parentchange(self):
'''Context manager for handling dirstate parents.
If an exception occurs in the scope of the context manager,
the incoherent dirstate won't be written when wlock is
released.
'''
self._parentwriters += 1
yield
# Typically we want the "undo" step of a context manager in a
# finally block so it happens even when an exception
# occurs. In this case, however, we only want to decrement
# parentwriters if the code in the with statement exits
# normally, so we don't have a try/finally here on purpose.
self._parentwriters -= 1
Durham Goode
dirstate: add begin/endparentchange to dirstate...
r22404 def pendingparentchange(self):
'''Returns true if the dirstate is in the middle of a set of changes
that modify the dirstate parent.
'''
return self._parentwriters > 0
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
dirstate: use propertycache
r8261 @propertycache
def _map(self):
Mark Thomas
dirstate: document dirstatemap interface...
r35077 """Return the dirstate contents (see documentation for dirstatemap)."""
Mark Thomas
dirstate: make map implementation overridable...
r35085 self._map = self._mapcls(self._ui, self._opener, self._root)
Matt Mackall
dirstate: use propertycache
r8261 return self._map
Gregory Szorc
dirstate: expose a sparse matcher on dirstate (API)...
r33373 @property
def _sparsematcher(self):
"""The matcher for the sparse checkout.
The working directory may not include every file from a manifest. The
matcher obtained by this property will match a path if it is to be
included in the working directory.
"""
# TODO there is potential to cache this property. For now, the matcher
# is resolved on every access. (But the called function does use a
# cache to keep the lookup fast.)
return self._sparsematchfn()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @repocache(b'branch')
Matt Mackall
dirstate: use propertycache
r8261 def _branch(self):
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return self._opener.read(b"branch").strip() or b"default"
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as inst:
Pierre-Yves David
dirstate: propagate IOError other than ENOENT when reading branch
r15799 if inst.errno != errno.ENOENT:
raise
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b"default"
Matt Mackall
dirstate: use propertycache
r8261
Durham Goode
dirstate: move parents source of truth to dirstatemap...
r34340 @property
Matt Mackall
dirstate: use propertycache
r8261 def _pl(self):
Durham Goode
dirstate: move parent reading to the dirstatemap class...
r34339 return self._map.parents()
Matt Mackall
dirstate: use propertycache
r8261
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 def hasdir(self, d):
return self._map.hastrackeddir(d)
FUJIWARA Katsunori
context: add 'dirs()' to changectx/workingctx for directory patterns...
r16143
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @rootcache(b'.hgignore')
Matt Mackall
dirstate: use propertycache
r8261 def _ignore(self):
Laurent Charignon
dirstate: extract logic to compute the list of ignorefiles...
r27594 files = self._ignorefiles()
Durham Goode
ignore: use 'include:' rules instead of custom syntax...
r25216 if not files:
Martin von Zweigbergk
match: delete unused root and cwd arguments from {always,never,exact}() (API)...
r41825 return matchmod.never()
Durham Goode
ignore: use 'include:' rules instead of custom syntax...
r25216
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 pats = [b'include:%s' % f for f in files]
return matchmod.match(self._root, b'', [], pats, warn=self._ui.warn)
Matt Mackall
dirstate: use propertycache
r8261
@propertycache
def _slash(self):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return self._ui.configbool(b'ui', b'slash') and pycompat.ossep != b'/'
Matt Mackall
dirstate: use propertycache
r8261
@propertycache
def _checklink(self):
return util.checklink(self._root)
@propertycache
def _checkexec(self):
return util.checkexec(self._root)
@propertycache
def _checkcase(self):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return not util.fscasesensitive(self._join(b'.hg'))
Matt Mackall
dirstate: use propertycache
r8261
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:
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
windows: recompute flags when committing a merge (issue1802)...
r15337 def f(x):
Bryan O'Sullivan
dirstate: only call lstat once per flags invocation...
r18869 try:
st = os.lstat(self._join(x))
if util.statislink(st):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'l'
Bryan O'Sullivan
dirstate: only call lstat once per flags invocation...
r18869 if util.statisexec(st):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'x'
Bryan O'Sullivan
dirstate: only call lstat once per flags invocation...
r18869 except OSError:
pass
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b''
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
windows: recompute flags when committing a merge (issue1802)...
r15337 return f
fallback = buildfallback()
Matt Mackall
simplify flag handling...
r6743 if self._checklink:
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
simplify flag handling...
r6743 def f(x):
Benoit Boissinot
performance: normalize self._root, avoid calling os.path.join() in dirstate...
r6972 if os.path.islink(self._join(x)):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'l'
if b'x' in fallback(x):
return b'x'
return b''
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
simplify flag handling...
r6743 return f
if self._checkexec:
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
simplify flag handling...
r6743 def f(x):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'l' in fallback(x):
return b'l'
Adrian Buehlmann
rename util.is_exec to isexec
r14273 if util.isexec(self._join(x)):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'x'
return b''
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
simplify flag handling...
r6743 return f
Matt Mackall
windows: recompute flags when committing a merge (issue1802)...
r15337 else:
return fallback
Matt Mackall
simplify flag handling...
r6743
Pierre-Yves David
rebase: do not crash in panic when cwd disapear in the process (issue4121)...
r20335 @propertycache
def _cwd(self):
FUJIWARA Katsunori
dirstate: centralize _cwd handling into _cwd method...
r33212 # internal config: ui.forcecwd
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 forcecwd = self._ui.config(b'ui', b'forcecwd')
FUJIWARA Katsunori
dirstate: centralize _cwd handling into _cwd method...
r33212 if forcecwd:
return forcecwd
Matt Harbison
py3: rename pycompat.getcwd() to encoding.getcwd() (API)...
r39843 return encoding.getcwd()
Pierre-Yves David
rebase: do not crash in panic when cwd disapear in the process (issue4121)...
r20335
mpm@selenic.com
Break apart hg.py...
r1089 def getcwd(self):
Yuya Nishihara
dirstate: state that getcwd() shouldn't be used to get real file path...
r26293 '''Return the path from which a canonical path is calculated.
This path should be used to resolve file patterns or to convert
canonical paths back to file paths for display. It shouldn't be
used to get real file paths. Use vfs functions instead.
'''
Pierre-Yves David
rebase: do not crash in panic when cwd disapear in the process (issue4121)...
r20335 cwd = self._cwd
Matt Mackall
many, many trivial check-code fixups
r10282 if cwd == self._root:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b''
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):
Pulkit Goyal
py3: replace os.sep with pycompat.ossep (part 2 of 4)...
r30614 rootsep += pycompat.ossep
Alexis S. L. Carvalho
Fix handling of paths when run outside the repo....
r4230 if cwd.startswith(rootsep):
Augie Fackler
formatting: blacken the codebase...
r43346 return cwd[len(rootsep) :]
Alexis S. L. Carvalho
Fix handling of paths when run outside the repo....
r4230 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:
Matt Mackall
dirstate: don't overnormalize for ui.slash...
r19210 return util.pconvert(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
'''
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return self._map.get(key, (b"?",))[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):
Alex Gaynor
dirstate: simplify dirstate's __iter__...
r33673 return iter(sorted(self._map))
mpm@selenic.com
Break apart hg.py...
r1089
Augie Fackler
cleanup: rename all iteritems methods to items and add iteritems alias...
r32550 def items(self):
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 return pycompat.iteritems(self._map)
Bryan O'Sullivan
completion: add a debugpathcomplete command...
r18792
Augie Fackler
cleanup: rename all iteritems methods to items and add iteritems alias...
r32550 iteritems = items
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):
Patrick Mezard
localrepo: add setparents() to adjust dirstate copies (issue3407)...
r16551 """Set dirstate parents to p1 and p2.
When moving from two parents to one, 'm' merged entries a
adjusted to normal and previous copy records discarded and
returned by the call.
See localrepo.setparents()
"""
Durham Goode
dirstate: add exception when calling setparent without begin/end (API)...
r22407 if self._parentwriters == 0:
Augie Fackler
formatting: blacken the codebase...
r43346 raise ValueError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"cannot set dirstate parent outside of "
b"dirstate.parentchange context manager"
Augie Fackler
formatting: blacken the codebase...
r43346 )
Durham Goode
dirstate: add exception when calling setparent without begin/end (API)...
r22407
Durham Goode
dirstate: move parents source of truth to dirstatemap...
r34340 self._dirty = True
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 oldp2 = self._pl[1]
Mateusz Kwapich
dirstate: add callback to notify extensions about wd parent change...
r29772 if self._origpl is None:
self._origpl = self._pl
Durham Goode
dirstate: move parents source of truth to dirstatemap...
r34340 self._map.setparents(p1, p2)
Patrick Mezard
localrepo: add setparents() to adjust dirstate copies (issue3407)...
r16551 copies = {}
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 if oldp2 != nullid and p2 == nullid:
Durham Goode
dirstate: move nonnormal and otherparent sets to dirstatemap...
r34675 candidatefiles = self._map.nonnormalset.union(
Augie Fackler
formatting: blacken the codebase...
r43346 self._map.otherparentset
)
Durham Goode
dirstate: track otherparent files same as nonnormal...
r31278 for f in candidatefiles:
s = self._map.get(f)
if s is None:
continue
Matt Mackall
dirstate: properly clean-up some more merge state on setparents
r22895 # Discard 'm' markers when moving away from a merge state
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if s[0] == b'm':
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 source = self._map.copymap.get(f)
Michael Bolin
dirstate: perform transactions with _copymap using single call, where possible...
r33983 if source:
copies[f] = source
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 self.normallookup(f)
Matt Mackall
dirstate: properly clean-up some more merge state on setparents
r22895 # Also fix up otherparent markers
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif s[0] == b'n' and s[2] == -2:
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 source = self._map.copymap.get(f)
Michael Bolin
dirstate: perform transactions with _copymap using single call, where possible...
r33983 if source:
copies[f] = source
Matt Mackall
dirstate: properly clean-up some more merge state on setparents
r22895 self.add(f)
Patrick Mezard
localrepo: add setparents() to adjust dirstate copies (issue3407)...
r16551 return copies
mpm@selenic.com
Break apart hg.py...
r1089
Matt Mackall
Move branch read/write to dirstate where it belongs
r4179 def setbranch(self, branch):
Yuya Nishihara
filecache: unimplement __set__() and __delete__() (API)...
r40454 self.__class__._branch.set(self, encoding.fromlocal(branch))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = self._opener(b'branch', b'w', atomictemp=True, checkambig=True)
Idan Kamara
dirstate: write branch file atomically
r16472 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f.write(self._branch + b'\n')
Idan Kamara
dirstate: write branch file atomically
r16472 f.close()
Idan Kamara
dirstate: refresh _branch cache entry after writing it
r18317
# make sure filecache has the correct stat info for _branch after
# replacing the underlying file
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ce = self._filecache[b'_branch']
Idan Kamara
dirstate: refresh _branch cache entry after writing it
r18317 if ce:
ce.refresh()
Augie Fackler
formatting: blacken the codebase...
r43346 except: # re-raises
Idan Kamara
dirstate: don't rename branch file if writing it failed
r18076 f.discard()
raise
Matt Mackall
Move branch read/write to dirstate where it belongs
r4179
Matt Mackall
localrepo and dirstate: rename reload to invalidate...
r4613 def invalidate(self):
Siddharth Agarwal
dirstate: add docstring for invalidate...
r32682 '''Causes the next access to reread the dirstate.
This is different from localrepo.invalidatedirstate() because it always
rereads the dirstate. Use localrepo.invalidatedirstate() if you want to
check whether the dirstate has changed before rereading it.'''
Augie Fackler
cleanup: remove pointless r-prefixes on double-quoted strings...
r43809 for a in ("_map", "_branch", "_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
Durham Goode
dirstate: track updated files to improve write time...
r31206 self._updatedfiles.clear()
Durham Goode
dirstate: add begin/endparentchange to dirstate...
r22404 self._parentwriters = 0
Mateusz Kwapich
dirstate: add callback to notify extensions about wd parent change...
r29772 self._origpl = None
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:
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 self._map.copymap[dest] = source
Durham Goode
dirstate: track updated files to improve write time...
r31206 self._updatedfiles.add(source)
self._updatedfiles.add(dest)
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 elif self._map.copymap.pop(dest, None):
Durham Goode
dirstate: track updated files to improve write time...
r31206 self._updatedfiles.add(dest)
mpm@selenic.com
Break apart hg.py...
r1089
def copied(self, file):
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 return self._map.copymap.get(file, None)
Matt Mackall
dirstate: add copies function...
r3154
def copies(self):
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 return self._map.copymap
mpm@selenic.com
Break apart hg.py...
r1089
Adrian Buehlmann
dirstate: eliminate redundant check parameter on _addpath()...
r17196 def _addpath(self, f, state, mode, size, mtime):
Maxim Dounin
Fix file-changed-to-dir and dir-to-file commits (issue660)....
r5487 oldstate = self[f]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if state == b'a' or oldstate == b'r':
Adrian Buehlmann
move checkfilename from util to scmutil...
r13974 scmutil.checkfilename(f)
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 if self._map.hastrackeddir(f):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'directory %r already in dirstate') % pycompat.bytestr(f)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 # shadows
Martin von Zweigbergk
utils: move finddirs() to pathutil...
r44032 for d in pathutil.finddirs(f):
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 if self._map.hastrackeddir(d):
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 break
Michael Bolin
dirstate: perform transactions with _map using single call, where possible...
r34189 entry = self._map.get(d)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if entry is not None and entry[0] != b'r':
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'file %r in dirstate clashes with %r')
Augie Fackler
formatting: blacken the codebase...
r43346 % (pycompat.bytestr(d), pycompat.bytestr(f))
)
Joshua Redstone
dirstate: factor common update code into _addpath...
r17094 self._dirty = True
Durham Goode
dirstate: track updated files to improve write time...
r31206 self._updatedfiles.add(f)
Mark Thomas
dirstate: move management of the dirstate dirs into the dirstatemap...
r35080 self._map.addfile(f, oldstate, state, mode, size, mtime)
Maxim Dounin
Fix file-changed-to-dir and dir-to-file commits (issue660)....
r5487
Valentin Gatien-Baron
merge: fix race that could cause wrong size in dirstate...
r42656 def normal(self, f, parentfiledata=None):
'''Mark a file normal and clean.
parentfiledata: (mode, size, mtime) of the clean file
parentfiledata should be computed from memory (for mode,
size), as or close as possible from the point where we
determined the file was clean, to limit the risk of the
file having been changed by an external process between the
moment where the file was determined to be clean and now.'''
if parentfiledata:
(mode, size, mtime) = parentfiledata
else:
s = os.lstat(self._join(f))
mode = s.st_mode
size = s.st_size
mtime = s[stat.ST_MTIME]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._addpath(f, b'n', mode, size & _rangemask, mtime & _rangemask)
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 self._map.copymap.pop(f, None)
Durham Goode
dirstate: move nonnormal and otherparent sets to dirstatemap...
r34675 if f in self._map.nonnormalset:
self._map.nonnormalset.remove(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.'''
Michael Bolin
dirstate: perform transactions with _map using single call, where possible...
r34189 if self._pl[1] != nullid:
Alexis S. L. Carvalho
normallookup: during merges, restore the state saved by remove
r6298 # 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.
Michael Bolin
dirstate: perform transactions with _map using single call, where possible...
r34189 entry = self._map.get(f)
if entry is not None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if entry[0] == b'r' and entry[2] in (-1, -2):
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 source = self._map.copymap.get(f)
Michael Bolin
dirstate: perform transactions with _map using single call, where possible...
r34189 if entry[2] == -1:
self.merge(f)
elif entry[2] == -2:
self.otherparent(f)
if source:
self.copy(source, f)
return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if entry[0] == b'm' or entry[0] == b'n' and entry[2] == -2:
Michael Bolin
dirstate: perform transactions with _map using single call, where possible...
r34189 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._addpath(f, b'n', 0, -1, -1)
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 self._map.copymap.pop(f, None)
Alexis S. L. Carvalho
merge: forcefully mark files that we get from the second parent as dirty...
r5210
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:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b"setting %r to other parent only allowed in merges") % f
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if f in self and self[f] == b'n':
Matt Mackall
dirstate: use 'm' state in otherparent to reduce ambiguity...
r22896 # merge-like
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._addpath(f, b'm', 0, -2, -1)
Matt Mackall
dirstate: use 'm' state in otherparent to reduce ambiguity...
r22896 else:
# add-like
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._addpath(f, b'n', 0, -2, -1)
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 self._map.copymap.pop(f, None)
Matt Mackall
dirstate: break update into separate functions
r4904
def add(self, f):
Martin Geisler
dirstate: improve docstring formatting...
r10145 '''Mark a file added.'''
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._addpath(f, b'a', 0, -1, -1)
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 self._map.copymap.pop(f, None)
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
Mark Thomas
dirstate: move management of the dirstate dirs into the dirstatemap...
r35080 oldstate = self[f]
Alexis S. L. Carvalho
dirstate.remove: during merges, remember the previous file state...
r6297 size = 0
Michael Bolin
dirstate: perform transactions with _map using single call, where possible...
r34189 if self._pl[1] != nullid:
entry = self._map.get(f)
if entry is not None:
# backup the previous state
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if entry[0] == b'm': # merge
Michael Bolin
dirstate: perform transactions with _map using single call, where possible...
r34189 size = -1
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif entry[0] == b'n' and entry[2] == -2: # other parent
Michael Bolin
dirstate: perform transactions with _map using single call, where possible...
r34189 size = -2
Durham Goode
dirstate: move nonnormal and otherparent sets to dirstatemap...
r34675 self._map.otherparentset.add(f)
Mark Thomas
dirstate: remove _droppath method...
r35082 self._updatedfiles.add(f)
Mark Thomas
dirstate: move management of the dirstate dirs into the dirstatemap...
r35080 self._map.removefile(f, oldstate, size)
Michael Bolin
dirstate: perform transactions with _copymap using single call, where possible...
r33983 if size == 0:
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 self._map.copymap.pop(f, None)
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.'''
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 if self._pl[1] == nullid:
return self.normallookup(f)
Matt Mackall
dirstate: merge falls through to otherparent...
r22897 return self.otherparent(f)
Matt Mackall
dirstate: break update into separate functions
r4904
Matt Mackall
dirstate: rename forget to drop...
r14434 def drop(self, f):
'''Drop a file from the dirstate'''
Mark Thomas
dirstate: move management of the dirstate dirs into the dirstatemap...
r35080 oldstate = self[f]
if self._map.dropfile(f, oldstate):
Matt Mackall
dirstate: don't fail when dropping a not-tracked file (issue3080)...
r15399 self._dirty = True
Mark Thomas
dirstate: remove _droppath method...
r35082 self._updatedfiles.add(f)
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 self._map.copymap.pop(f, None)
mpm@selenic.com
Break apart hg.py...
r1089
Siddharth Agarwal
dirstate: factor out code to discover normalized path...
r24538 def _discoverpath(self, path, normed, ignoremissing, exists, storemap):
if exists is None:
exists = os.path.lexists(os.path.join(self._root, path))
if not exists:
# Maybe a path component exists
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not ignoremissing and b'/' in path:
d, f = path.rsplit(b'/', 1)
Siddharth Agarwal
dirstate: factor out code to discover normalized path...
r24538 d = self._normalize(d, False, ignoremissing, None)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 folded = d + b"/" + f
Siddharth Agarwal
dirstate: factor out code to discover normalized path...
r24538 else:
# No path components, preserve original case
folded = path
else:
# recursively normalize leading directory components
# against dirstate
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'/' in normed:
d, f = normed.rsplit(b'/', 1)
Siddharth Agarwal
dirstate: factor out code to discover normalized path...
r24538 d = self._normalize(d, False, ignoremissing, True)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 r = self._root + b"/" + d
folded = d + b"/" + util.fspath(f, r)
Siddharth Agarwal
dirstate: factor out code to discover normalized path...
r24538 else:
folded = util.fspath(normed, self._root)
storemap[normed] = folded
return folded
Siddharth Agarwal
dirstate: introduce function to normalize just filenames...
r24539 def _normalizefile(self, path, isknown, ignoremissing=False, exists=None):
Matt Mackall
dirstate: fix case-folding identity for traditional Unix...
r15488 normed = util.normcase(path)
Durham Goode
dirstate: remove _filefoldmap property cache...
r34677 folded = self._map.filefoldmap.get(normed, None)
Matt Mackall
dirstate: introduce a public case normalizing method
r13717 if folded is None:
Patrick Mezard
dirstate: preserve path components case on renames (issue3402)...
r16542 if isknown:
Matt Mackall
dirstate: introduce a public case normalizing method
r13717 folded = path
Petr Kodl
issue 1286: dirstat regression on case folding systems...
r7068 else:
Augie Fackler
formatting: blacken the codebase...
r43346 folded = self._discoverpath(
path, normed, ignoremissing, exists, self._map.filefoldmap
)
Siddharth Agarwal
dirstate: introduce function to normalize just filenames...
r24539 return folded
Matt Mackall
dirstate: normalize case of directory components...
r16302
Patrick Mezard
dirstate: preserve path components case on renames (issue3402)...
r16542 def _normalize(self, path, isknown, ignoremissing=False, exists=None):
Matt Mackall
dirstate: fix case-folding identity for traditional Unix...
r15488 normed = util.normcase(path)
Durham Goode
dirstate: remove _filefoldmap property cache...
r34677 folded = self._map.filefoldmap.get(normed, None)
Siddharth Agarwal
dirstate._normalize: don't construct dirfoldmap if not necessary...
r24561 if folded is None:
Durham Goode
dirstate: move the _dirfoldmap to dirstatemap...
r34679 folded = self._map.dirfoldmap.get(normed, None)
Matt Mackall
dirstate: introduce a public case normalizing method
r13717 if folded is None:
Patrick Mezard
dirstate: preserve path components case on renames (issue3402)...
r16542 if isknown:
Matt Mackall
dirstate: introduce a public case normalizing method
r13717 folded = path
Petr Kodl
issue 1286: dirstat regression on case folding systems...
r7068 else:
Siddharth Agarwal
dirstate: split the foldmap into separate ones for files and directories...
r24540 # store discovered result in dirfoldmap so that future
# normalizefile calls don't start matching directories
Augie Fackler
formatting: blacken the codebase...
r43346 folded = self._discoverpath(
path, normed, ignoremissing, exists, self._map.dirfoldmap
)
Matt Mackall
dirstate: introduce a public case normalizing method
r13717 return folded
Patrick Mezard
dirstate: preserve path components case on renames (issue3402)...
r16542 def normalize(self, path, isknown=False, ignoremissing=False):
Matt Mackall
dirstate: introduce a public case normalizing method
r13717 '''
normalize the case of a pathname when on a casefolding filesystem
isknown specifies whether the filename came from walking the
Patrick Mezard
dirstate: preserve path components case on renames (issue3402)...
r16542 disk, to avoid extra filesystem access.
If ignoremissing is True, missing path are returned
unchanged. Otherwise, we try harder to normalize possibly
existing path components.
Matt Mackall
dirstate: introduce a public case normalizing method
r13717
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:
Patrick Mezard
dirstate: preserve path components case on renames (issue3402)...
r16542 return self._normalize(path, isknown, ignoremissing)
Matt Mackall
dirstate: introduce a public case normalizing method
r13717 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):
Durham Goode
dirstate: move clear onto dirstatemap class...
r34934 self._map.clear()
Martin Geisler
Use explicit integer division...
r15791 self._lastnormaltime = 0
Durham Goode
dirstate: track updated files to improve write time...
r31206 self._updatedfiles.clear()
Alexis S. L. Carvalho
merge with crew-stable
r5123 self._dirty = True
Alexis S. L. Carvalho
dirstate: fix rebuild; add a test...
r5065
Durham Goode
strip: make --keep option not set all dirstate times to 0...
r18760 def rebuild(self, parent, allfiles, changedfiles=None):
Pierre-Yves David
dirstate: avoid invalidating every entries when list is empty...
r25448 if changedfiles is None:
Christian Delahousse
dirstate: change debugrebuilddirstate --minimal to use dirstate.rebuild...
r27176 # Rebuild entire dirstate
Kyle Lippincott
dirstate: when calling rebuild(), avoid some N^2 codepaths...
r44343 to_lookup = allfiles
to_drop = []
Christian Delahousse
dirstate: change debugrebuilddirstate --minimal to use dirstate.rebuild...
r27176 lastnormaltime = self._lastnormaltime
self.clear()
self._lastnormaltime = lastnormaltime
Kyle Lippincott
dirstate: when calling rebuild(), avoid some N^2 codepaths...
r44343 elif len(changedfiles) < 10:
# Avoid turning allfiles into a set, which can be expensive if it's
# large.
to_lookup = []
to_drop = []
for f in changedfiles:
if f in allfiles:
to_lookup.append(f)
else:
to_drop.append(f)
else:
changedfilesset = set(changedfiles)
to_lookup = changedfilesset & set(allfiles)
to_drop = changedfilesset - to_lookup
Christian Delahousse
dirstate: change debugrebuilddirstate --minimal to use dirstate.rebuild...
r27176
Mateusz Kwapich
dirstate: add callback to notify extensions about wd parent change...
r29772 if self._origpl is None:
self._origpl = self._pl
Durham Goode
dirstate: move parents source of truth to dirstatemap...
r34340 self._map.setparents(parent, nullid)
Kyle Lippincott
dirstate: when calling rebuild(), avoid some N^2 codepaths...
r44343
for f in to_lookup:
self.normallookup(f)
for f in to_drop:
self.drop(f)
Mateusz Kwapich
dirstate: rebuild should update dirstate properly...
r30026
Matt Mackall
dirstate: use True and false for _dirty
r4903 self._dirty = True
mpm@selenic.com
Break apart hg.py...
r1089
FUJIWARA Katsunori
dirstate: add identity information to detect simultaneous changing in storage...
r32750 def identity(self):
'''Return identity of dirstate itself to detect changing in storage
If identity of previous dirstate is equal to this, writing
changes based on the former dirstate out can keep consistency.
'''
Durham Goode
dirstate: move identity to dirstatemap...
r34676 return self._map.identity
FUJIWARA Katsunori
dirstate: add identity information to detect simultaneous changing in storage...
r32750
Pierre-Yves David
deprecation: enforce thew 'tr' argument of 'dirstate.write' (API)...
r29673 def write(self, tr):
Matt Mackall
dirstate: simplify dirty handling
r4612 if not self._dirty:
Benoit Boissinot
only write the dirstate when something changed
r1794 return
FUJIWARA Katsunori
dirstate: delay writing out to ensure timestamp of each entries explicitly...
r21931
FUJIWARA Katsunori
dirstate: make writing in-memory changes aware of transaction activity...
r26634 filename = self._filename
Pierre-Yves David
deprecation: enforce thew 'tr' argument of 'dirstate.write' (API)...
r29673 if tr:
FUJIWARA Katsunori
dirstate: make writing in-memory changes aware of transaction activity...
r26634 # 'dirstate.write()' is not only for writing in-memory
# changes out, but also for dropping ambiguous timestamp.
# delayed writing re-raise "ambiguous timestamp issue".
# See also the wiki page below for detail:
# https://www.mercurial-scm.org/wiki/DirstateTransactionPlan
# emulate dropping timestamp in 'parsers.pack_dirstate'
FUJIWARA Katsunori
dirstate: remove layering violation around writing dirstate out...
r26747 now = _getfsnow(self._opener)
Mark Thomas
dirstate: move management of nonnormal sets into dirstate map...
r35079 self._map.clearambiguoustimes(self._updatedfiles, now)
FUJIWARA Katsunori
dirstate: make writing in-memory changes aware of transaction activity...
r26634
# emulate that all 'dirstate.normal' results are written out
self._lastnormaltime = 0
Durham Goode
dirstate: track updated files to improve write time...
r31206 self._updatedfiles.clear()
FUJIWARA Katsunori
dirstate: make writing in-memory changes aware of transaction activity...
r26634
# delay writing in-memory changes out
Augie Fackler
formatting: blacken the codebase...
r43346 tr.addfilegenerator(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'dirstate',
Augie Fackler
formatting: blacken the codebase...
r43346 (self._filename,),
self._writedirstate,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 location=b'plain',
Augie Fackler
formatting: blacken the codebase...
r43346 )
FUJIWARA Katsunori
dirstate: make writing in-memory changes aware of transaction activity...
r26634 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 st = self._opener(filename, b"w", atomictemp=True, checkambig=True)
FUJIWARA Katsunori
dirstate: split write to write changes into files other than .hg/dirstate...
r26521 self._writedirstate(st)
Mateusz Kwapich
dirstate: add callback to notify extensions about wd parent change...
r29772 def addparentchangecallback(self, category, callback):
"""add a callback to be called when the wd parents are changed
Callback will be called with the following arguments:
dirstate, (oldp1, oldp2), (newp1, newp2)
Category is a unique identifier to allow overwriting an old callback
with a newer callback.
"""
self._plchangecallbacks[category] = callback
FUJIWARA Katsunori
dirstate: split write to write changes into files other than .hg/dirstate...
r26521 def _writedirstate(self, st):
Mateusz Kwapich
dirstate: add callback to notify extensions about wd parent change...
r29772 # notify callbacks about parents change
if self._origpl is not None and self._origpl != self._pl:
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for c, callback in sorted(
pycompat.iteritems(self._plchangecallbacks)
):
Mateusz Kwapich
dirstate: add callback to notify extensions about wd parent change...
r29772 callback(self, self._origpl, self._pl)
self._origpl = None
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'
Augie Fackler
cleanup: use stat_result[stat.ST_MTIME] instead of stat_result.st_mtime...
r36799 now = util.fstat(st)[stat.ST_MTIME] & _rangemask
Matt Mackall
dirstate: move delaywrite logic from write to _write...
r27397
# enough 'delaywrite' prevents 'pack_dirstate' from dropping
# timestamp of each entries in dirstate, because of 'now > mtime'
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 delaywrite = self._ui.configint(b'debug', b'dirstate.delaywrite')
Matt Mackall
dirstate: move delaywrite logic from write to _write...
r27397 if delaywrite > 0:
Matt Mackall
dirstate: only invoke delaywrite if relevant...
r27398 # do we have any files to delay for?
Yuya Nishihara
rust-cpython: allow mutation unless leaked reference is borrowed...
r43606 for f, e in pycompat.iteritems(self._map):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if e[0] == b'n' and e[3] == now:
Augie Fackler
formatting: blacken the codebase...
r43346 import time # to avoid useless import
Matt Mackall
dirstate: make delaywrite sleep until the next multiple of n seconds...
r27399 # rather than sleep n seconds, sleep until the next
# multiple of n seconds
clock = time.time()
start = int(clock) - (int(clock) % delaywrite)
end = start + delaywrite
time.sleep(end - clock)
Augie Fackler
formatting: blacken the codebase...
r43346 now = end # trust our estimate that the end is near now
Matt Mackall
dirstate: only invoke delaywrite if relevant...
r27398 break
Matt Mackall
dirstate: move delaywrite logic from write to _write...
r27397
Durham Goode
dirstate: move write into dirstatemap...
r34674 self._map.write(st, now)
Mads Kiilerich
dirstate: inline local finish function...
r21026 self._lastnormaltime = 0
Durham Goode
dirstate: move write into dirstatemap...
r34674 self._dirty = False
mpm@selenic.com
Break apart hg.py...
r1089
Alexis S. L. Carvalho
dirstate: don't walk ignored directories...
r6032 def _dirignore(self, f):
if self._ignore(f):
return True
Martin von Zweigbergk
utils: move finddirs() to pathutil...
r44032 for p in pathutil.finddirs(f):
Matt Mackall
dirstate: simplify/optimize path checking...
r6767 if self._ignore(p):
Alexis S. L. Carvalho
dirstate: don't walk ignored directories...
r6032 return True
return False
Laurent Charignon
dirstate: extract logic to compute the list of ignorefiles...
r27594 def _ignorefiles(self):
files = []
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if os.path.exists(self._join(b'.hgignore')):
files.append(self._join(b'.hgignore'))
for name, path in self._ui.configitems(b"ui"):
if name == b'ignore' or name.startswith(b'ignore.'):
Laurent Charignon
dirstate: extract logic to compute the list of ignorefiles...
r27594 # we need to use os.path.join here rather than self._join
# because path is arbitrary and user-specified
files.append(os.path.join(self._rootdir, util.expandpath(path)))
return files
Laurent Charignon
dirstate: add a way to get the ignore file/line matching an ignored file...
r27670 def _ignorefileandline(self, f):
files = collections.deque(self._ignorefiles())
visited = set()
while files:
i = files.popleft()
Augie Fackler
formatting: blacken the codebase...
r43346 patterns = matchmod.readpatternfile(
i, self._ui.warn, sourceinfo=True
)
Laurent Charignon
dirstate: add a way to get the ignore file/line matching an ignored file...
r27670 for pattern, lineno, line in patterns:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kind, p = matchmod._patsplit(pattern, b'glob')
if kind == b"subinclude":
Laurent Charignon
dirstate: add a way to get the ignore file/line matching an ignored file...
r27670 if p not in visited:
files.append(p)
continue
Augie Fackler
formatting: blacken the codebase...
r43346 m = matchmod.match(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._root, b'', [], [pattern], warn=self._ui.warn
Augie Fackler
formatting: blacken the codebase...
r43346 )
Laurent Charignon
dirstate: add a way to get the ignore file/line matching an ignored file...
r27670 if m(f):
return (i, lineno, line)
visited.add(i)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return (None, -1, b"")
Laurent Charignon
dirstate: add a way to get the ignore file/line matching an ignored file...
r27670
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173 def _walkexplicit(self, match, subrepos):
'''Get stat data about the files explicitly specified by match.
Matt Mackall
simplify dirstate walking...
r3529
Siddharth Agarwal
dirstate._walkexplicit: rename work to dirsfound...
r19174 Return a triple (results, dirsfound, dirsnotfound).
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173 - results is a mapping from filename to stat result. It also contains
listings mapping subrepos and .hg to None.
Siddharth Agarwal
dirstate._walkexplicit: rename work to dirsfound...
r19174 - dirsfound is a list of files found to be directories.
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173 - dirsnotfound is a list of files that the dirstate thinks are
directories and that were not found.'''
Matt Mackall
walk: begin refactoring badmatch handling
r6578
Matt Mackall
walk: use match.bad callback for filetype messages
r8681 def badtype(mode):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kind = _(b'unknown')
Matt Mackall
many, many trivial check-code fixups
r10282 if stat.S_ISCHR(mode):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kind = _(b'character device')
Matt Mackall
many, many trivial check-code fixups
r10282 elif stat.S_ISBLK(mode):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kind = _(b'block device')
Matt Mackall
many, many trivial check-code fixups
r10282 elif stat.S_ISFIFO(mode):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kind = _(b'fifo')
Matt Mackall
many, many trivial check-code fixups
r10282 elif stat.S_ISSOCK(mode):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kind = _(b'socket')
Matt Mackall
many, many trivial check-code fixups
r10282 elif stat.S_ISDIR(mode):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kind = _(b'directory')
return _(b'unsupported file type (type is %s)') % kind
Matt Mackall
dirstate.walk: fold in _supported...
r6830
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 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
Siddharth Agarwal
dirstate._walkexplicit: rename work to dirsfound...
r19174 dirsfound = []
foundadd = dirsfound.append
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173 dirsnotfound = []
Siddharth Agarwal
dirstate._walkexplicit: inline dirsnotfound.append
r19175 notfoundadd = dirsnotfound.append
Matt Mackall
dirstate.walk: fold findfiles into main walk loop
r6820
Martin von Zweigbergk
match: add isexact() method to hide internals...
r24448 if not match.isexact() and self._checkcase:
Matt Mackall
dirstate: skip optimization on case-folding FS (issue2440)
r12907 normalize = self._normalize
else:
Siddharth Agarwal
dirstate: test normalize is truthy instead of using a no-op lambda...
r18032 normalize = None
Matt Mackall
dirstate: skip optimization on case-folding FS (issue2440)
r12907
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):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 subpath = subrepos[j] + b"/"
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
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not files or b'' in files:
files = [b'']
Martin von Zweigbergk
dirstate: move special handling of files==['.'] together...
r42527 # constructing the foldmap is expensive, so don't do it for the
Martin von Zweigbergk
match: use '' instead of '.' for root directory (API)...
r42528 # common case where files is ['']
Martin von Zweigbergk
dirstate: move special handling of files==['.'] together...
r42527 normalize = None
Augie Fackler
dirstate: don't check state of subrepo directories
r10176 results = dict.fromkeys(subrepos)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 results[b'.hg'] = None
Matt Mackall
dirstate: localize a bunch of methods for findfiles
r5000
Martin Geisler
dirstate: use one pass to filter out files in subrepos
r12211 for ff in files:
Martin von Zweigbergk
dirstate: move special handling of files==['.'] together...
r42527 if normalize:
Siddharth Agarwal
dirstate._walkexplicit: drop normpath calls...
r24522 nf = normalize(ff, False, True)
Siddharth Agarwal
dirstate: test normalize is truthy instead of using a no-op lambda...
r18032 else:
Siddharth Agarwal
dirstate._walkexplicit: drop normpath calls...
r24522 nf = ff
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:
Simon Heimberg
dirstate: set more states in step 1 of walk
r8588 if nf in dmap:
Mads Kiilerich
dirstate: improve documentation and readability of match and ignore in the walker
r21115 # file replaced by dir on disk but still in dirstate
Simon Heimberg
dirstate: set more states in step 1 of walk
r8588 results[nf] = None
Matt Harbison
dirstate: don't require exact case when adding dirs on icasefs (issue4578)...
r24537 foundadd((nf, ff))
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
Augie Fackler
formatting: blacken the codebase...
r43346 except OSError as inst: # nf not found on disk - it is dirstate only
if nf in dmap: # does it exactly match a missing file?
Matt Mackall
walk: simplify check for missing file
r8675 results[nf] = None
Augie Fackler
formatting: blacken the codebase...
r43346 else: # does it match a missing directory?
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 if self._map.hasdir(nf):
Martin von Zweigbergk
dirstate: speed up repeated missing directory checks...
r23375 notfoundadd(nf)
Matt Mackall
walk: simplify logic for badfn clause...
r8677 else:
Augie Fackler
python3: wrap all uses of <exception>.strerror with strtolocal...
r34024 badfn(ff, encoding.strtolocal(inst.strerror))
Matt Mackall
dirstate.walk: fold findfiles into main walk loop
r6820
Yuya Nishihara
dirstate: drop explicit files that shouldn't match (BC) (issue4679)...
r36218 # match.files() may contain explicitly-specified paths that shouldn't
# be taken; drop them from the list of files found. dirsfound/notfound
# aren't filtered here because they will be tested later.
if match.anypats():
for f in list(results):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if f == b'.hg' or f in subrepos:
Yuya Nishihara
dirstate: drop explicit files that shouldn't match (BC) (issue4679)...
r36218 # keep sentinel to disable further out-of-repo walks
continue
if not match(f):
del results[f]
Matt Harbison
dirstate: ensure mv source is marked deleted when walking icasefs (issue4760)...
r25877 # Case insensitive filesystems cannot rely on lstat() failing to detect
# a case-only rename. Prune the stat object for any file that does not
# match the case in the filesystem, if there are multiple files that
# normalize to the same path.
if match.isexact() and self._checkcase:
normed = {}
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for f, st in pycompat.iteritems(results):
Matt Harbison
dirstate: ensure mv source is marked deleted when walking icasefs (issue4760)...
r25877 if st is None:
continue
nc = util.normcase(f)
paths = normed.get(nc)
if paths is None:
paths = set()
normed[nc] = paths
paths.add(f)
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for norm, paths in pycompat.iteritems(normed):
Matt Harbison
dirstate: ensure mv source is marked deleted when walking icasefs (issue4760)...
r25877 if len(paths) > 1:
for path in paths:
Augie Fackler
formatting: blacken the codebase...
r43346 folded = self._discoverpath(
path, norm, True, None, self._map.dirfoldmap
)
Matt Harbison
dirstate: ensure mv source is marked deleted when walking icasefs (issue4760)...
r25877 if path != folded:
results[path] = None
Siddharth Agarwal
dirstate._walkexplicit: rename work to dirsfound...
r19174 return results, dirsfound, dirsnotfound
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173
Siddharth Agarwal
dirstate.walk: add a flag to let extensions avoid full walks...
r19190 def walk(self, match, subrepos, unknown, ignored, full=True):
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173 '''
Walk recursively through the directory tree, finding all files
matched by match.
Siddharth Agarwal
dirstate.walk: add a flag to let extensions avoid full walks...
r19190 If full is False, maybe skip some known-clean files.
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173 Return a dict mapping filename to stat-like object (either
mercurial.osutil.stat instance or return value of os.stat()).
Siddharth Agarwal
dirstate.walk: add a flag to let extensions avoid full walks...
r19190
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173 '''
Siddharth Agarwal
dirstate.walk: add a flag to let extensions avoid full walks...
r19190 # full is a flag that extensions that hook into walk can use -- this
# implementation doesn't use it at all. This satisfies the contract
# because we only guarantee a "maybe".
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173
if ignored:
ignore = util.never
dirignore = util.never
Mads Kiilerich
dirstate: improve documentation and readability of match and ignore in the walker
r21115 elif unknown:
ignore = self._ignore
dirignore = self._dirignore
else:
# if not unknown and not ignored, drop dir recursion and step 2
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173 ignore = util.always
dirignore = util.always
matchfn = match.matchfn
matchalways = match.always()
matchtdir = match.traversedir
dmap = self._map
Yuya Nishihara
osutil: proxy through util (and platform) modules (API)...
r32203 listdir = util.listdir
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173 lstat = os.lstat
dirkind = stat.S_IFDIR
regkind = stat.S_IFREG
lnkkind = stat.S_IFLNK
join = self._join
exact = skipstep3 = False
Augie Fackler
formatting: blacken the codebase...
r43346 if match.isexact(): # match.exact
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173 exact = True
Augie Fackler
formatting: blacken the codebase...
r43346 dirignore = util.always # skip step 2
elif match.prefix(): # match.match, no patterns
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173 skipstep3 = True
if not exact and self._checkcase:
normalize = self._normalize
Siddharth Agarwal
dirstate.walk: use the file foldmap to normalize...
r24541 normalizefile = self._normalizefile
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173 skipstep3 = False
else:
Siddharth Agarwal
dirstate.walk: don't keep track of normalized files in parallel...
r24560 normalize = self._normalize
Siddharth Agarwal
dirstate.walk: use the file foldmap to normalize...
r24541 normalizefile = None
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173
# step 1: find all explicit files
results, work, dirsnotfound = self._walkexplicit(match, subrepos)
Martin von Zweigbergk
dirstate: include explicit matches in match.traversedir calls...
r44112 if matchtdir:
for d in work:
matchtdir(d[0])
for d in dirsnotfound:
matchtdir(d)
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173
Siddharth Agarwal
dirstate.walk: pull skipstep3 out of the explicit walk code...
r19172 skipstep3 = skipstep3 and not (work or dirsnotfound)
Matt Harbison
dirstate: don't require exact case when adding dirs on icasefs (issue4578)...
r24537 work = [d for d in work if not dirignore(d[0])]
Siddharth Agarwal
dirstate.walk: move dirignore filter out of explicit walk code...
r19171
Matt Mackall
dirstate.walk: pull directory scanning into top-level loop
r6826 # step 2: visit subdirectories
Siddharth Agarwal
dirstate.walk: don't keep track of normalized files in parallel...
r24560 def traverse(work, alreadynormed):
Siddharth Agarwal
dirstate.walk: factor out directory traversal...
r24559 wadd = work.append
while work:
Augie Fackler
dirstate: add some traces on listdir calls...
r43533 tracing.counter('dirstate.walk work', len(work))
Siddharth Agarwal
dirstate.walk: don't keep track of normalized files in parallel...
r24560 nd = work.pop()
Kyle Lippincott
dirstate: use visitchildrenset in traverse...
r38991 visitentries = match.visitchildrenset(nd)
if not visitentries:
Martin von Zweigbergk
dirstate: optimize walk() by using match.visitdir()...
r32177 continue
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if visitentries == b'this' or visitentries == b'all':
Kyle Lippincott
dirstate: use visitchildrenset in traverse...
r38991 visitentries = None
Siddharth Agarwal
dirstate.walk: factor out directory traversal...
r24559 skip = None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if nd != b'':
skip = b'.hg'
Siddharth Agarwal
dirstate.walk: factor out directory traversal...
r24559 try:
Augie Fackler
dirstate: add some traces on listdir calls...
r43533 with tracing.log('dirstate.walk.traverse listdir %s', nd):
entries = listdir(join(nd), stat=True, skip=skip)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except OSError as inst:
Siddharth Agarwal
dirstate.walk: factor out directory traversal...
r24559 if inst.errno in (errno.EACCES, errno.ENOENT):
Augie Fackler
formatting: blacken the codebase...
r43346 match.bad(
self.pathto(nd), encoding.strtolocal(inst.strerror)
)
Siddharth Agarwal
dirstate.walk: factor out directory traversal...
r24559 continue
raise
for f, kind, st in entries:
Kyle Lippincott
match: document that visitchildrenset might return files...
r39296 # Some matchers may return files in the visitentries set,
# instead of 'this', if the matcher explicitly mentions them
# and is not an exactmatcher. This is acceptable; we do not
# make any hard assumptions about file-or-directory below
# based on the presence of `f` in visitentries. If
# visitchildrenset returned a set, we can always skip the
# entries *not* in the set it provided regardless of whether
# they're actually a file or a directory.
Kyle Lippincott
dirstate: use visitchildrenset in traverse...
r38991 if visitentries and f not in visitentries:
continue
Siddharth Agarwal
dirstate.walk: factor out directory traversal...
r24559 if normalizefile:
# even though f might be a directory, we're only
# interested in comparing it to files currently in the
# dmap -- therefore normalizefile is enough
Augie Fackler
formatting: blacken the codebase...
r43346 nf = normalizefile(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 nd and (nd + b"/" + f) or f, True, True
Augie Fackler
formatting: blacken the codebase...
r43346 )
Siddharth Agarwal
dirstate.walk: factor out directory traversal...
r24559 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 nf = nd and (nd + b"/" + f) or f
Siddharth Agarwal
dirstate.walk: factor out directory traversal...
r24559 if nf not in results:
if kind == dirkind:
if not ignore(nf):
if matchtdir:
matchtdir(nf)
Siddharth Agarwal
dirstate.walk: don't keep track of normalized files in parallel...
r24560 wadd(nf)
Siddharth Agarwal
dirstate.walk: factor out directory traversal...
r24559 if nf in dmap and (matchalways or matchfn(nf)):
results[nf] = None
elif kind == regkind or kind == lnkkind:
if nf in dmap:
if matchalways or matchfn(nf):
results[nf] = st
Augie Fackler
formatting: blacken the codebase...
r43346 elif (matchalways or matchfn(nf)) and not ignore(
nf
):
Siddharth Agarwal
dirstate.walk: don't keep track of normalized files in parallel...
r24560 # unknown file -- normalize if necessary
if not alreadynormed:
nf = normalize(nf, False, True)
Siddharth Agarwal
dirstate.walk: factor out directory traversal...
r24559 results[nf] = st
elif nf in dmap and (matchalways or matchfn(nf)):
Matt Mackall
dirstate.walk: build a dict rather than yield...
r6829 results[nf] = None
Siddharth Agarwal
dirstate.walk: factor out directory traversal...
r24559
Siddharth Agarwal
dirstate.walk: don't keep track of normalized files in parallel...
r24560 for nd, d in work:
# alreadynormed means that processwork doesn't have to do any
# expensive directory normalization
alreadynormed = not normalize or nd == d
traverse([d], alreadynormed)
mpm@selenic.com
Break apart hg.py...
r1089
Siddharth Agarwal
dirstate.walk: remove subrepo and .hg from results before step 3...
r18812 for s in subrepos:
del results[s]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 del results[b'.hg']
Siddharth Agarwal
dirstate.walk: remove subrepo and .hg from results before step 3...
r18812
Mads Kiilerich
dirstate: improve documentation and readability of match and ignore in the walker
r21115 # step 3: visit remaining files from dmap
Matt Mackall
match: fold plan cases down to two special cases...
r8684 if not skipstep3 and not exact:
Mads Kiilerich
dirstate: improve documentation and readability of match and ignore in the walker
r21115 # If a dmap file is not in results yet, it was either
# a) not matching matchfn b) ignored, c) missing, or d) under a
# symlink directory.
Siddharth Agarwal
dirstate.walk: fast path none-seen + match-always case for step 3...
r18815 if not results and matchalways:
Pulkit Goyal
dirstate: use list comprehension to get a list of keys...
r31422 visit = [f for f in dmap]
Siddharth Agarwal
dirstate.walk: fast path none-seen + match-always case for step 3...
r18815 else:
visit = [f for f in dmap if f not in results and matchfn(f)]
visit.sort()
Durham Goode
dirstate: walk returns None for files that have a symlink in their path...
r18625 if unknown:
Mads Kiilerich
dirstate: improve documentation and readability of match and ignore in the walker
r21115 # unknown == True means we walked all dirs under the roots
# that wasn't ignored, and everything that matched was stat'ed
# and is already in results.
# The rest must thus be ignored or under a symlink.
Yuya Nishihara
pathauditor: disable cache of audited paths by default (issue5628)...
r33722 audit_path = pathutil.pathauditor(self._root, cached=True)
Durham Goode
dirstate: walk returns None for files that have a symlink in their path...
r18625
for nf in iter(visit):
Martin von Zweigbergk
dirstate.walk: don't report same file stat multiple times...
r24621 # If a stat for the same file was already added with a
# different case, don't add one for this, since that would
# make it appear as if the file exists under both names
# on disk.
Augie Fackler
formatting: blacken the codebase...
r43346 if (
normalizefile
and normalizefile(nf, True, True) in results
):
Martin von Zweigbergk
dirstate.walk: don't report same file stat multiple times...
r24621 results[nf] = None
Durham Goode
dirstate: walk returns None for files that have a symlink in their path...
r18625 # Report ignored items in the dmap as long as they are not
# under a symlink directory.
Martin von Zweigbergk
dirstate.walk: don't report same file stat multiple times...
r24621 elif audit_path.check(nf):
Durham Goode
dirstate: fix generator/list error when using python 2.7...
r18663 try:
results[nf] = lstat(join(nf))
Mads Kiilerich
dirstate: improve documentation and readability of match and ignore in the walker
r21115 # file was just ignored, no links, and exists
Durham Goode
dirstate: fix generator/list error when using python 2.7...
r18663 except OSError:
# file doesn't exist
results[nf] = None
Durham Goode
dirstate: walk returns None for files that have a symlink in their path...
r18625 else:
# It's either missing or under a symlink directory
Mads Kiilerich
dirstate: improve documentation and readability of match and ignore in the walker
r21115 # which we in this case report as missing
Durham Goode
dirstate: walk returns None for files that have a symlink in their path...
r18625 results[nf] = None
else:
# We may not have walked the full directory tree above,
Mads Kiilerich
dirstate: improve documentation and readability of match and ignore in the walker
r21115 # so stat and check everything we missed.
Augie Fackler
dirstate: use future-proof next(iter) instead of iter.next...
r31507 iv = iter(visit)
Bryan O'Sullivan
dirstate: back out 502b56a9e897...
r26984 for st in util.statfiles([join(i) for i in visit]):
Augie Fackler
dirstate: use future-proof next(iter) instead of iter.next...
r31507 results[next(iv)] = st
Matt Mackall
dirstate.walk: build a dict rather than yield...
r6829 return results
mpm@selenic.com
Break apart hg.py...
r1089
Raphaël Gomès
dirstate: move rust fast-path calling code to its own method...
r44537 def _rust_status(self, matcher, list_clean):
# Force Rayon (Rust parallelism library) to respect the number of
# workers. This is a temporary workaround until Rust code knows
# how to read the config file.
numcpus = self._ui.configint(b"worker", b"numcpus")
if numcpus is not None:
encoding.environ.setdefault(b'RAYON_NUM_THREADS', b'%d' % numcpus)
workers_enabled = self._ui.configbool(b"worker", b"enabled", True)
if not workers_enabled:
encoding.environ[b"RAYON_NUM_THREADS"] = b"1"
(
lookup,
modified,
added,
removed,
deleted,
unknown,
clean,
) = rustmod.status(
self._map._rustmap,
matcher,
self._rootdir,
bool(list_clean),
self._lastnormaltime,
self._checkexec,
)
status = scmutil.status(
modified=modified,
added=added,
removed=removed,
deleted=deleted,
unknown=unknown,
ignored=[],
clean=clean,
)
return (lookup, status)
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
Martin von Zweigbergk
status: update and move documentation of status types to status class...
r22915 dirstate and return a pair of (unsure, status), where status is of type
scmutil.status and:
Greg Ward
dirstate: add/improve method docstrings....
r9518
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)
Martin von Zweigbergk
status: update and move documentation of status types to status class...
r22915 status.modified:
Greg Ward
dirstate: add/improve method docstrings....
r9518 files that have definitely been modified since the dirstate
was written (different size or mode)
Martin von Zweigbergk
status: update and move documentation of status types to status class...
r22915 status.clean:
Greg Ward
dirstate: add/improve method docstrings....
r9518 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
Durham Goode
dirstate: remove excess attribute lookups for dirstate.status (issue5714)...
r34936 dmap.preload()
Raphaël Gomès
rust-dirstate-status: add call to rust-fast path for `dirstate.status`...
r43568
use_rust = True
Raphaël Gomès
rust-matchers: add support for `exactmatcher` in `dirstate.status`...
r44369
allowed_matchers = (matchmod.alwaysmatcher, matchmod.exactmatcher)
Raphaël Gomès
rust-dirstate-status: add call to rust-fast path for `dirstate.status`...
r43568 if rustmod is None:
use_rust = False
elif subrepos:
use_rust = False
Raphaël Gomès
rust-matchers: add support for `exactmatcher` in `dirstate.status`...
r44369 elif bool(listunknown):
Raphaël Gomès
rust-dirstate-status: add call to rust-fast path for `dirstate.status`...
r43568 # Pathauditor does not exist yet in Rust, unknown files
# can't be trusted.
use_rust = False
elif self._ignorefiles() and listignored:
# Rust has no ignore mechanism yet, so don't use Rust for
# commands that need ignore.
use_rust = False
Raphaël Gomès
rust-matchers: add support for `exactmatcher` in `dirstate.status`...
r44369 elif not isinstance(match, allowed_matchers):
Raphaël Gomès
rust-dirstate-status: add call to rust-fast path for `dirstate.status`...
r43568 # Matchers have yet to be implemented
use_rust = False
if use_rust:
Raphaël Gomès
dirstate: move rust fast-path calling code to its own method...
r44537 return self._rust_status(match, listclean)
Raphaël Gomès
rust-dirstate-status: add call to rust-fast path for `dirstate.status`...
r43568
Martin von Zweigbergk
dirstate: respect request to not list unknown/ignored/clean files (API)...
r44019 def noop(f):
pass
Durham Goode
dirstate: remove excess attribute lookups for dirstate.status (issue5714)...
r34936 dcontains = dmap.__contains__
dget = dmap.__getitem__
Augie Fackler
formatting: blacken the codebase...
r43346 ladd = lookup.append # aka "unsure"
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 madd = modified.append
aadd = added.append
Martin von Zweigbergk
dirstate: respect request to not list unknown/ignored/clean files (API)...
r44019 uadd = unknown.append if listunknown else noop
iadd = ignored.append if listignored else noop
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 radd = removed.append
dadd = deleted.append
Martin von Zweigbergk
dirstate: respect request to not list unknown/ignored/clean files (API)...
r44019 cadd = clean.append if listclean else noop
Siddharth Agarwal
dirstate: inline more properties and methods in status...
r18034 mexact = match.exact
dirignore = self._dirignore
checkexec = self._checkexec
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 copymap = self._map.copymap
Siddharth Agarwal
dirstate: inline more properties and methods in status...
r18034 lastnormaltime = self._lastnormaltime
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003
Siddharth Agarwal
dirstate.status: avoid full walks when possible
r19191 # We need to do full walks when either
# - we're listing all clean files, or
# - match.traversedir does something, because match.traversedir should
# be called for every dir in the working dir
full = listclean or match.traversedir is not None
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for fn, st in pycompat.iteritems(
self.walk(match, subrepos, listunknown, listignored, full=full)
):
Durham Goode
dirstate: remove excess attribute lookups for dirstate.status (issue5714)...
r34936 if not dcontains(fn):
Siddharth Agarwal
dirstate: inline more properties and methods in status...
r18034 if (listignored or mexact(fn)) and dirignore(fn):
Matt Mackall
repo.status: eliminate list_
r6753 if listignored:
Alexis S. L. Carvalho
dirstate.status: avoid putting ignored files in the unknown list...
r6033 iadd(fn)
Siddharth Agarwal
dirstate.status: return explicit unknown files even when not asked...
r19910 else:
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
Siddharth Agarwal
dirstate.status: assign members one by one instead of unpacking the tuple...
r21810 # This is equivalent to 'state, mode, size, time = dmap[fn]' but not
# written like that for performance reasons. dmap[fn] is not a
# Python tuple in compiled builds. The CPython UNPACK_SEQUENCE
# opcode has fast paths when the value to be unpacked is a tuple or
# a list, but falls back to creating a full-fledged iterator in
# general. That is much slower than simply accessing and storing the
# tuple members one by one.
Durham Goode
dirstate: remove excess attribute lookups for dirstate.status (issue5714)...
r34936 t = dget(fn)
Siddharth Agarwal
dirstate.status: assign members one by one instead of unpacking the tuple...
r21810 state = t[0]
mode = t[1]
size = t[2]
time = t[3]
Matt Mackall
dirstate: minor status cleanups
r6591
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not st and state in b"nma":
Matt Mackall
dirstate.walk: eliminate src from yield...
r6818 dadd(fn)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif state == b'n':
Augie Fackler
formatting: blacken the codebase...
r43346 if (
size >= 0
and (
(size != st.st_size and size != st.st_size & _rangemask)
or ((mode ^ st.st_mode) & 0o100 and checkexec)
)
or size == -2 # other parent
or fn in copymap
):
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 madd(fn)
Augie Fackler
formatting: blacken the codebase...
r43346 elif (
time != st[stat.ST_MTIME]
and time != st[stat.ST_MTIME] & _rangemask
):
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 ladd(fn)
Augie Fackler
cleanup: use stat_result[stat.ST_MTIME] instead of stat_result.st_mtime...
r36799 elif st[stat.ST_MTIME] == lastnormaltime:
Mads Kiilerich
dirstate: clarify comment about leaving normal files undef if changed 'now'...
r24181 # fn may have just been marked as normal and it may have
# changed in the same second without changing its size.
# This can happen if we quickly do multiple commits.
Adrian Buehlmann
dirstate: eliminate _lastnormal set...
r13763 # 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)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif state == b'm':
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 madd(fn)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif state == b'a':
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 aadd(fn)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif state == b'r':
Matt Mackall
dirstate: localize a bunch of methods in status fastpath
r5003 radd(fn)
mason@suse.com
Optimize dirstate walking...
r1183
Augie Fackler
formatting: blacken the codebase...
r43346 return (
lookup,
scmutil.status(
modified, added, removed, deleted, unknown, ignored, clean
),
)
Siddharth Agarwal
dirstate: add a method to efficiently filter by match...
r21984
def matches(self, match):
'''
return files in the dirstate (in whatever state) filtered by match
'''
dmap = self._map
Raphaël Gomès
rust-dirstatemap: remove additional lookup in dirstate.matches...
r44833 if rustmod is not None:
dmap = self._map._rustmap
Siddharth Agarwal
dirstate: add a method to efficiently filter by match...
r21984 if match.always():
return dmap.keys()
files = match.files()
Martin von Zweigbergk
match: add isexact() method to hide internals...
r24448 if match.isexact():
Siddharth Agarwal
dirstate: add a method to efficiently filter by match...
r21984 # fast path -- filter the other way around, since typically files is
# much smaller than dmap
return [f for f in files if f in dmap]
Martin von Zweigbergk
dirstate: use match.prefix() instead of 'not match.anypats()'...
r25275 if match.prefix() and all(fn in dmap for fn in files):
Siddharth Agarwal
dirstate: add a method to efficiently filter by match...
r21984 # fast path -- all the values are known to be files, so just return
# that
return list(files)
return [f for f in dmap if match(f)]
FUJIWARA Katsunori
dirstate: move code paths for backup from dirstateguard to dirstate...
r26632
FUJIWARA Katsunori
dirstateguard: remove layering violation around saving/restoring backup...
r26746 def _actualfilename(self, tr):
if tr:
FUJIWARA Katsunori
dirstate: make functions for backup aware of transaction activity...
r26633 return self._pendingfilename
else:
return self._filename
Adam Simpkins
dirstate: update backup functions to take full backup filename...
r33440 def savebackup(self, tr, backupname):
'''Save current dirstate into backup file'''
FUJIWARA Katsunori
dirstateguard: remove layering violation around saving/restoring backup...
r26746 filename = self._actualfilename(tr)
Adam Simpkins
dirstate: update backup functions to take full backup filename...
r33440 assert backupname != filename
FUJIWARA Katsunori
dirstate: make functions for backup aware of transaction activity...
r26633
# use '_writedirstate' instead of 'write' to write changes certainly,
# because the latter omits writing out if transaction is running.
# output file will be used to create backup of dirstate at this point.
Jun Wu
dirstate: avoid unnecessary load+dump during backup...
r31208 if self._dirty or not self._opener.exists(filename):
Augie Fackler
formatting: blacken the codebase...
r43346 self._writedirstate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._opener(filename, b"w", atomictemp=True, checkambig=True)
Augie Fackler
formatting: blacken the codebase...
r43346 )
FUJIWARA Katsunori
dirstate: make functions for backup aware of transaction activity...
r26633
if tr:
# ensure that subsequent tr.writepending returns True for
# changes written out above, even if dirstate is never
# changed after this
Augie Fackler
formatting: blacken the codebase...
r43346 tr.addfilegenerator(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'dirstate',
Augie Fackler
formatting: blacken the codebase...
r43346 (self._filename,),
self._writedirstate,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 location=b'plain',
Augie Fackler
formatting: blacken the codebase...
r43346 )
FUJIWARA Katsunori
dirstate: make functions for backup aware of transaction activity...
r26633
# ensure that pending file written above is unlinked at
# failure, even if tr.writepending isn't invoked until the
# end of this transaction
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 tr.registertmp(filename, location=b'plain')
FUJIWARA Katsunori
dirstate: make functions for backup aware of transaction activity...
r26633
Ryan McElroy
dirstate: use tryunlink
r31547 self._opener.tryunlink(backupname)
Jun Wu
dirstate: try to use hardlink to backup dirstate...
r31207 # hardlink backup is okay because _writedirstate is always called
# with an "atomictemp=True" file.
Augie Fackler
formatting: blacken the codebase...
r43346 util.copyfile(
self._opener.join(filename),
self._opener.join(backupname),
hardlink=True,
)
FUJIWARA Katsunori
dirstate: move code paths for backup from dirstateguard to dirstate...
r26632
Adam Simpkins
dirstate: update backup functions to take full backup filename...
r33440 def restorebackup(self, tr, backupname):
'''Restore dirstate by backup file'''
FUJIWARA Katsunori
dirstate: move code paths for backup from dirstateguard to dirstate...
r26632 # this "invalidate()" prevents "wlock.release()" from writing
# changes of dirstate out after restoring from backup file
self.invalidate()
FUJIWARA Katsunori
dirstateguard: remove layering violation around saving/restoring backup...
r26746 filename = self._actualfilename(tr)
Mark Thomas
dirstate: clean up when restoring identical backups...
r34941 o = self._opener
if util.samefile(o.join(backupname), o.join(filename)):
o.unlink(backupname)
else:
o.rename(backupname, filename, checkambig=True)
FUJIWARA Katsunori
dirstate: move code paths for backup from dirstateguard to dirstate...
r26632
Adam Simpkins
dirstate: update backup functions to take full backup filename...
r33440 def clearbackup(self, tr, backupname):
'''Clear backup file'''
self._opener.unlink(backupname)
Durham Goode
dirstate: create new dirstatemap class...
r34333
Augie Fackler
formatting: blacken the codebase...
r43346
Durham Goode
dirstate: create new dirstatemap class...
r34333 class dirstatemap(object):
Mark Thomas
dirstate: document dirstatemap interface...
r35077 """Map encapsulating the dirstate's contents.
The dirstate contains the following state:
- `identity` is the identity of the dirstate file, which can be used to
detect when changes have occurred to the dirstate file.
- `parents` is a pair containing the parents of the working copy. The
parents are updated by calling `setparents`.
- the state map maps filenames to tuples of (state, mode, size, mtime),
where state is a single character representing 'normal', 'added',
Mark Thomas
dirstate: add explicit methods for modifying dirstate...
r35078 'removed', or 'merged'. It is read by treating the dirstate as a
dict. File state is updated by calling the `addfile`, `removefile` and
`dropfile` methods.
Mark Thomas
dirstate: document dirstatemap interface...
r35077
- `copymap` maps destination filenames to their source filename.
The dirstate also provides the following views onto the state:
- `nonnormalset` is a set of the filenames that have state other
than 'normal', or are normal but have an mtime of -1 ('normallookup').
- `otherparentset` is a set of the filenames that are marked as coming
from the second parent when the dirstate is currently being merged.
- `filefoldmap` is a dict mapping normalized filenames to the denormalized
form that they appear as in the dirstate.
- `dirfoldmap` is a dict mapping normalized directory names to the
denormalized form that they appear as in the dirstate.
"""
Durham Goode
dirstate: move opendirstatefile to dirstatemap...
r34338 def __init__(self, ui, opener, root):
self._ui = ui
self._opener = opener
self._root = root
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._filename = b'dirstate'
Durham Goode
dirstate: move opendirstatefile to dirstatemap...
r34338
Durham Goode
dirstate: move parents source of truth to dirstatemap...
r34340 self._parents = None
self._dirtyparents = False
Durham Goode
dirstate: create new dirstatemap class...
r34333
Durham Goode
dirstate: move opendirstatefile to dirstatemap...
r34338 # for consistent view between _pl() and _read() invocations
self._pendingmode = None
Durham Goode
dirstate: avoid reading the map when possible (issue5713) (issue5717)...
r34935 @propertycache
def _map(self):
self._map = {}
self.read()
return self._map
@propertycache
def copymap(self):
self.copymap = {}
self._map
return self.copymap
Durham Goode
dirstate: move clear onto dirstatemap class...
r34934 def clear(self):
Durham Goode
dirstate: remove excess attribute lookups for dirstate.status (issue5714)...
r34936 self._map.clear()
self.copymap.clear()
Durham Goode
dirstate: move clear onto dirstatemap class...
r34934 self.setparents(nullid, nullid)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 util.clearcachedproperty(self, b"_dirs")
util.clearcachedproperty(self, b"_alldirs")
util.clearcachedproperty(self, b"filefoldmap")
util.clearcachedproperty(self, b"dirfoldmap")
util.clearcachedproperty(self, b"nonnormalset")
util.clearcachedproperty(self, b"otherparentset")
Durham Goode
dirstate: move clear onto dirstatemap class...
r34934
Augie Fackler
contrib: fix dirstatenonnormalcheck to work in Python 3...
r35896 def items(self):
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 return pycompat.iteritems(self._map)
Durham Goode
dirstate: create new dirstatemap class...
r34333
Augie Fackler
contrib: fix dirstatenonnormalcheck to work in Python 3...
r35896 # forward for python2,3 compat
iteritems = items
Simon Whitaker
dirstate: implement __len__ on dirstatemap (issue5695)...
r34409 def __len__(self):
return len(self._map)
Durham Goode
dirstate: create new dirstatemap class...
r34333 def __iter__(self):
return iter(self._map)
def get(self, key, default=None):
return self._map.get(key, default)
def __contains__(self, key):
return key in self._map
def __getitem__(self, key):
return self._map[key]
def keys(self):
return self._map.keys()
Durham Goode
dirstate: move nonnormalentries to dirstatemap...
r34334
Durham Goode
dirstate: remove excess attribute lookups for dirstate.status (issue5714)...
r34936 def preload(self):
"""Loads the underlying data, if it's not already loaded"""
self._map
Mark Thomas
dirstate: move management of the dirstate dirs into the dirstatemap...
r35080 def addfile(self, f, oldstate, state, mode, size, mtime):
Mark Thomas
dirstate: add explicit methods for modifying dirstate...
r35078 """Add a tracked file to the dirstate."""
Augie Fackler
cleanup: remove pointless r-prefixes on double-quoted strings...
r43809 if oldstate in b"?r" and "_dirs" in self.__dict__:
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 self._dirs.addpath(f)
Augie Fackler
cleanup: remove pointless r-prefixes on double-quoted strings...
r43809 if oldstate == b"?" and "_alldirs" in self.__dict__:
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 self._alldirs.addpath(f)
Mark Thomas
dirstate: add explicit methods for modifying dirstate...
r35078 self._map[f] = dirstatetuple(state, mode, size, mtime)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if state != b'n' or mtime == -1:
Mark Thomas
dirstate: move management of nonnormal sets into dirstate map...
r35079 self.nonnormalset.add(f)
if size == -2:
self.otherparentset.add(f)
Mark Thomas
dirstate: add explicit methods for modifying dirstate...
r35078
Mark Thomas
dirstate: move management of the dirstate dirs into the dirstatemap...
r35080 def removefile(self, f, oldstate, size):
Mark Thomas
dirstate: add explicit methods for modifying dirstate...
r35078 """
Mark a file as removed in the dirstate.
The `size` parameter is used to store sentinel values that indicate
the file's previous state. In the future, we should refactor this
to be more explicit about what that state is.
"""
Augie Fackler
cleanup: remove pointless r-prefixes on double-quoted strings...
r43809 if oldstate not in b"?r" and "_dirs" in self.__dict__:
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 self._dirs.delpath(f)
Augie Fackler
cleanup: remove pointless r-prefixes on double-quoted strings...
r43809 if oldstate == b"?" and "_alldirs" in self.__dict__:
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 self._alldirs.addpath(f)
Augie Fackler
cleanup: remove pointless r-prefixes on double-quoted strings...
r43809 if "filefoldmap" in self.__dict__:
Mark Thomas
dirstate: move dropping of folded filenames into the dirstate map...
r35081 normed = util.normcase(f)
self.filefoldmap.pop(normed, None)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._map[f] = dirstatetuple(b'r', 0, size, 0)
Mark Thomas
dirstate: move management of nonnormal sets into dirstate map...
r35079 self.nonnormalset.add(f)
Mark Thomas
dirstate: add explicit methods for modifying dirstate...
r35078
Mark Thomas
dirstate: move management of the dirstate dirs into the dirstatemap...
r35080 def dropfile(self, f, oldstate):
Mark Thomas
dirstate: add explicit methods for modifying dirstate...
r35078 """
Remove a file from the dirstate. Returns True if the file was
previously recorded.
"""
Mark Thomas
dirstate: move management of nonnormal sets into dirstate map...
r35079 exists = self._map.pop(f, None) is not None
Mark Thomas
dirstate: move management of the dirstate dirs into the dirstatemap...
r35080 if exists:
Augie Fackler
cleanup: remove pointless r-prefixes on double-quoted strings...
r43809 if oldstate != b"r" and "_dirs" in self.__dict__:
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 self._dirs.delpath(f)
Augie Fackler
cleanup: remove pointless r-prefixes on double-quoted strings...
r43809 if "_alldirs" in self.__dict__:
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 self._alldirs.delpath(f)
Augie Fackler
cleanup: remove pointless r-prefixes on double-quoted strings...
r43809 if "filefoldmap" in self.__dict__:
Mark Thomas
dirstate: move dropping of folded filenames into the dirstate map...
r35081 normed = util.normcase(f)
self.filefoldmap.pop(normed, None)
Mark Thomas
dirstate: move management of nonnormal sets into dirstate map...
r35079 self.nonnormalset.discard(f)
return exists
def clearambiguoustimes(self, files, now):
for f in files:
e = self.get(f)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if e is not None and e[0] == b'n' and e[3] == now:
Mark Thomas
dirstate: move management of nonnormal sets into dirstate map...
r35079 self._map[f] = dirstatetuple(e[0], e[1], e[2], -1)
self.nonnormalset.add(f)
Mark Thomas
dirstate: add explicit methods for modifying dirstate...
r35078
Durham Goode
dirstate: move nonnormalentries to dirstatemap...
r34334 def nonnormalentries(self):
'''Compute the nonnormal dirstate entries from the dmap'''
try:
return parsers.nonnormalotherparententries(self._map)
except AttributeError:
nonnorm = set()
otherparent = set()
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for fname, e in pycompat.iteritems(self._map):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if e[0] != b'n' or e[3] == -1:
Durham Goode
dirstate: move nonnormalentries to dirstatemap...
r34334 nonnorm.add(fname)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if e[0] == b'n' and e[2] == -2:
Durham Goode
dirstate: move nonnormalentries to dirstatemap...
r34334 otherparent.add(fname)
return nonnorm, otherparent
Durham Goode
dirstate: remove _filefoldmap property cache...
r34677 @propertycache
Durham Goode
dirstate: move filefoldmap to dirstatemap...
r34335 def filefoldmap(self):
"""Returns a dictionary mapping normalized case paths to their
non-normalized versions.
"""
try:
makefilefoldmap = parsers.make_file_foldmap
except AttributeError:
pass
else:
Augie Fackler
formatting: blacken the codebase...
r43346 return makefilefoldmap(
self._map, util.normcasespec, util.normcasefallback
)
Durham Goode
dirstate: move filefoldmap to dirstatemap...
r34335
f = {}
normcase = util.normcase
Gregory Szorc
py3: finish porting iteritems() to pycompat and remove source transformer...
r43376 for name, s in pycompat.iteritems(self._map):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if s[0] != b'r':
Durham Goode
dirstate: move filefoldmap to dirstatemap...
r34335 f[normcase(name)] = name
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f[b'.'] = b'.' # prevents useless util.fspath() invocation
Durham Goode
dirstate: move filefoldmap to dirstatemap...
r34335 return f
Durham Goode
dirstate: move _dirs to dirstatemap...
r34336
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 def hastrackeddir(self, d):
"""
Returns True if the dirstate contains a tracked (not removed) file
in this directory.
"""
return d in self._dirs
def hasdir(self, d):
"""
Returns True if the dirstate contains a file (tracked or removed)
in this directory.
"""
return d in self._alldirs
Durham Goode
dirstate: remove _dirs property cache...
r34678 @propertycache
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 def _dirs(self):
utils: move the `dirs` definition in pathutil (API)...
r43923 return pathutil.dirs(self._map, b'r')
Durham Goode
dirstate: move opendirstatefile to dirstatemap...
r34338
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 @propertycache
def _alldirs(self):
utils: move the `dirs` definition in pathutil (API)...
r43923 return pathutil.dirs(self._map)
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083
Durham Goode
dirstate: move opendirstatefile to dirstatemap...
r34338 def _opendirstatefile(self):
fp, mode = txnutil.trypending(self._root, self._opener, self._filename)
if self._pendingmode is not None and self._pendingmode != mode:
fp.close()
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'working directory state may be changed parallelly')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Durham Goode
dirstate: move opendirstatefile to dirstatemap...
r34338 self._pendingmode = mode
return fp
Durham Goode
dirstate: move parent reading to the dirstatemap class...
r34339 def parents(self):
Durham Goode
dirstate: move parents source of truth to dirstatemap...
r34340 if not self._parents:
try:
fp = self._opendirstatefile()
st = fp.read(40)
fp.close()
except IOError as err:
if err.errno != errno.ENOENT:
raise
# File doesn't exist, so the current state is empty
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 st = b''
Durham Goode
dirstate: move parents source of truth to dirstatemap...
r34340
Durham Goode
dirstate: move parent reading to the dirstatemap class...
r34339 l = len(st)
if l == 40:
Yuya Nishihara
dirstate: use tuple interface to fix leak in pack_dirstate()...
r39485 self._parents = (st[:20], st[20:40])
Durham Goode
dirstate: move parents source of truth to dirstatemap...
r34340 elif l == 0:
Yuya Nishihara
dirstate: use tuple interface to fix leak in pack_dirstate()...
r39485 self._parents = (nullid, nullid)
Durham Goode
dirstate: move parents source of truth to dirstatemap...
r34340 else:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'working directory state appears damaged!')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Durham Goode
dirstate: move parents source of truth to dirstatemap...
r34340
return self._parents
def setparents(self, p1, p2):
self._parents = (p1, p2)
self._dirtyparents = True
Durham Goode
dirstate: move _read into dirstatemap...
r34673
def read(self):
Durham Goode
dirstate: move identity to dirstatemap...
r34676 # ignore HG_PENDING because identity is used only for writing
self.identity = util.filestat.frompath(
Augie Fackler
formatting: blacken the codebase...
r43346 self._opener.join(self._filename)
)
Durham Goode
dirstate: move identity to dirstatemap...
r34676
Durham Goode
dirstate: move _read into dirstatemap...
r34673 try:
fp = self._opendirstatefile()
try:
st = fp.read()
finally:
fp.close()
except IOError as err:
if err.errno != errno.ENOENT:
raise
return
if not st:
return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if util.safehasattr(parsers, b'dict_new_presized'):
Durham Goode
dirstate: move _read into dirstatemap...
r34673 # Make an estimate of the number of files in the dirstate based on
# its size. From a linear regression on a set of real-world repos,
# all over 10,000 files, the size of a dirstate entry is 85
# bytes. The cost of resizing is significantly higher than the cost
# of filling in a larger presized dict, so subtract 20% from the
# size.
#
# This heuristic is imperfect in many ways, so in a future dirstate
# format update it makes sense to just record the number of entries
# on write.
Yuya Nishihara
py3: do not pass a float to dict_new_presized()...
r36640 self._map = parsers.dict_new_presized(len(st) // 71)
Durham Goode
dirstate: move _read into dirstatemap...
r34673
# Python's garbage collector triggers a GC each time a certain number
# of container objects (the number being defined by
# gc.get_threshold()) are allocated. parse_dirstate creates a tuple
# for each file in the dirstate. The C version then immediately marks
# them as not to be tracked by the collector. However, this has no
# effect on when GCs are triggered, only on what objects the GC looks
# into. This means that O(number of files) GCs are unavoidable.
# Depending on when in the process's lifetime the dirstate is parsed,
# this can get very expensive. As a workaround, disable GC while
# parsing the dirstate.
#
# (we cannot decorate the function directly since it is in a C module)
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 parse_dirstate = util.nogc(parsers.parse_dirstate)
Durham Goode
dirstate: move _read into dirstatemap...
r34673 p = parse_dirstate(self._map, self.copymap, st)
if not self._dirtyparents:
self.setparents(*p)
Durham Goode
dirstate: move write into dirstatemap...
r34674
Durham Goode
dirstate: remove excess attribute lookups for dirstate.status (issue5714)...
r34936 # Avoid excess attribute lookups by fast pathing certain checks
self.__contains__ = self._map.__contains__
self.__getitem__ = self._map.__getitem__
self.get = self._map.get
Durham Goode
dirstate: move write into dirstatemap...
r34674 def write(self, st, now):
Augie Fackler
formatting: blacken the codebase...
r43346 st.write(
parsers.pack_dirstate(self._map, self.copymap, self.parents(), now)
)
Durham Goode
dirstate: move write into dirstatemap...
r34674 st.close()
self._dirtyparents = False
Durham Goode
dirstate: move nonnormal and otherparent sets to dirstatemap...
r34675 self.nonnormalset, self.otherparentset = self.nonnormalentries()
@propertycache
def nonnormalset(self):
nonnorm, otherparents = self.nonnormalentries()
self.otherparentset = otherparents
return nonnorm
@propertycache
def otherparentset(self):
nonnorm, otherparents = self.nonnormalentries()
self.nonnormalset = nonnorm
return otherparents
Durham Goode
dirstate: move identity to dirstatemap...
r34676 @propertycache
def identity(self):
Durham Goode
dirstate: avoid reading the map when possible (issue5713) (issue5717)...
r34935 self._map
Durham Goode
dirstate: move identity to dirstatemap...
r34676 return self.identity
Durham Goode
dirstate: move the _dirfoldmap to dirstatemap...
r34679 @propertycache
def dirfoldmap(self):
f = {}
normcase = util.normcase
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 for name in self._dirs:
Durham Goode
dirstate: move the _dirfoldmap to dirstatemap...
r34679 f[normcase(name)] = name
return f
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000
if rustmod is not None:
Augie Fackler
formatting: blacken the codebase...
r43346
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000 class dirstatemap(object):
def __init__(self, ui, opener, root):
self._ui = ui
self._opener = opener
self._root = root
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._filename = b'dirstate'
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000 self._parents = None
self._dirtyparents = False
# for consistent view between _pl() and _read() invocations
self._pendingmode = None
def addfile(self, *args, **kwargs):
return self._rustmap.addfile(*args, **kwargs)
def removefile(self, *args, **kwargs):
return self._rustmap.removefile(*args, **kwargs)
def dropfile(self, *args, **kwargs):
return self._rustmap.dropfile(*args, **kwargs)
def clearambiguoustimes(self, *args, **kwargs):
return self._rustmap.clearambiguoustimes(*args, **kwargs)
def nonnormalentries(self):
return self._rustmap.nonnormalentries()
def get(self, *args, **kwargs):
return self._rustmap.get(*args, **kwargs)
@propertycache
def _rustmap(self):
self._rustmap = rustmod.DirstateMap(self._root)
self.read()
return self._rustmap
@property
def copymap(self):
return self._rustmap.copymap()
def preload(self):
self._rustmap
def clear(self):
self._rustmap.clear()
self.setparents(nullid, nullid)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 util.clearcachedproperty(self, b"_dirs")
util.clearcachedproperty(self, b"_alldirs")
util.clearcachedproperty(self, b"dirfoldmap")
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000
def items(self):
return self._rustmap.items()
def keys(self):
return iter(self._rustmap)
def __contains__(self, key):
return key in self._rustmap
def __getitem__(self, item):
return self._rustmap[item]
def __len__(self):
return len(self._rustmap)
def __iter__(self):
return iter(self._rustmap)
# forward for python2,3 compat
iteritems = items
def _opendirstatefile(self):
Augie Fackler
formatting: blacken the codebase...
r43346 fp, mode = txnutil.trypending(
self._root, self._opener, self._filename
)
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000 if self._pendingmode is not None and self._pendingmode != mode:
fp.close()
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'working directory state may be changed parallelly')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000 self._pendingmode = mode
return fp
def setparents(self, p1, p2):
self._rustmap.setparents(p1, p2)
self._parents = (p1, p2)
self._dirtyparents = True
def parents(self):
if not self._parents:
try:
fp = self._opendirstatefile()
st = fp.read(40)
fp.close()
except IOError as err:
if err.errno != errno.ENOENT:
raise
# File doesn't exist, so the current state is empty
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 st = b''
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000
try:
self._parents = self._rustmap.parents(st)
except ValueError:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 _(b'working directory state appears damaged!')
Augie Fackler
formatting: blacken the codebase...
r43346 )
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000
return self._parents
def read(self):
# ignore HG_PENDING because identity is used only for writing
self.identity = util.filestat.frompath(
Augie Fackler
formatting: blacken the codebase...
r43346 self._opener.join(self._filename)
)
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000
try:
fp = self._opendirstatefile()
try:
st = fp.read()
finally:
fp.close()
except IOError as err:
if err.errno != errno.ENOENT:
raise
return
if not st:
return
parse_dirstate = util.nogc(self._rustmap.read)
parents = parse_dirstate(st)
if parents and not self._dirtyparents:
self.setparents(*parents)
Raphaël Gomès
rust-dirstatemap: remove additional lookups in dirstatemap...
r43574 self.__contains__ = self._rustmap.__contains__
self.__getitem__ = self._rustmap.__getitem__
self.get = self._rustmap.get
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000 def write(self, st, now):
parents = self.parents()
st.write(self._rustmap.write(parents[0], parents[1], now))
st.close()
self._dirtyparents = False
@propertycache
def filefoldmap(self):
"""Returns a dictionary mapping normalized case paths to their
non-normalized versions.
"""
return self._rustmap.filefoldmapasdict()
def hastrackeddir(self, d):
Augie Fackler
formatting: blacken the codebase...
r43346 self._dirs # Trigger Python's propertycache
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000 return self._rustmap.hastrackeddir(d)
def hasdir(self, d):
Augie Fackler
formatting: blacken the codebase...
r43346 self._dirs # Trigger Python's propertycache
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000 return self._rustmap.hasdir(d)
@propertycache
def _dirs(self):
return self._rustmap.getdirs()
@propertycache
def _alldirs(self):
return self._rustmap.getalldirs()
@propertycache
def identity(self):
self._rustmap
return self.identity
@property
def nonnormalset(self):
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44779 nonnorm = self._rustmap.non_normal_entries()
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000 return nonnorm
Raphaël Gomès
rust-dirstatemap: add missing @propertycache...
r44719 @propertycache
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000 def otherparentset(self):
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44779 otherparents = self._rustmap.other_parent_entries()
Raphaël Gomès
rust-dirstate: call rust dirstatemap from Python...
r43000 return otherparents
@propertycache
def dirfoldmap(self):
f = {}
normcase = util.normcase
for name in self._dirs:
f[normcase(name)] = name
return f