##// END OF EJS Templates
interfaces: convert `repository.ifilestorage` to a Protocol class...
interfaces: convert `repository.ifilestorage` to a Protocol class Same as cdd4bc69bfc1 for `imanifestrevisionstored`, but also make the methods in the super classes abstract as well.

File last commit:

r52952:b332ae61 default
r53385:8c89e978 default
Show More
dirstate.py
1861 lines | 65.6 KiB | text/x-python | PythonLexer
Martin Geisler
put license and copyright info into comment blocks
r8226 # dirstate.py - working directory tracking for mercurial
#
Raphaël Gomès
contributor: change mentions of mpm to olivia...
r47575 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
Martin Geisler
put license and copyright info into comment blocks
r8226 #
# 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
Matt Harbison
typing: add `from __future__ import annotations` to most files...
r52756 from __future__ import annotations
Gregory Szorc
dirstate: use absolute_import
r27503
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 os
import stat
dirstate: introduce a "tracked-key" feature...
r49533 import uuid
Gregory Szorc
dirstate: use absolute_import
r27503
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 from typing import (
Any,
Dict,
Iterable,
Iterator,
List,
Optional,
Tuple,
)
Gregory Szorc
dirstate: use absolute_import
r27503 from .i18n import _
Augie Fackler
dirstate: add some traces on listdir calls...
r43533
from hgdemandimport import tracing
Gregory Szorc
dirstate: use absolute_import
r27503 from . import (
dirstate: split dirstatemap in its own file...
r48295 dirstatemap,
Gregory Szorc
dirstate: use absolute_import
r27503 encoding,
error,
match as matchmod,
dirstate: introduce a "tracked-key" feature...
r49533 node,
Gregory Szorc
dirstate: use absolute_import
r27503 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,
dirstate: write the `branch` as part of the transaction if any...
r51151 txnutil,
Gregory Szorc
dirstate: use absolute_import
r27503 util,
)
mpm@selenic.com
Break apart hg.py...
r1089
Simon Sapin
dirstate: store mtimes with nanosecond precision in memory...
r49079 from .dirstateutils import (
timestamp,
)
Augie Fackler
interfaces: introduce an interface for dirstate implementations...
r43197 from .interfaces import (
dirstate as intdirstate,
)
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
dirstate-v2: add an option to prevent unintentional slow dirstate-v2...
r49049 HAS_FAST_DIRSTATE_V2 = rustmod is not None
Matt Mackall
dirstate: use propertycache
r8261 propertycache = util.propertycache
Idan Kamara
dirstate: filecacheify _branch...
r16201 filecache = scmutil.filecache
dirstate: move the handling of special case within the dirstatemap...
r48310 _rangemask = dirstatemap.rangemask
Idan Kamara
dirstate: filecacheify _branch...
r16201
Simon Sapin
dirstate: Use the Rust implementation of DirstateItem when Rust is enabled...
r48858 DirstateItem = dirstatemap.DirstateItem
Siddharth Agarwal
dirstate: add dirstatetuple to create dirstate values...
r21808
dirstate: introduce a symbolic constant for the FROM_P2 marker...
r48276
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
dirstate: introduce a check_invalidated decorator...
r51013 def check_invalidated(func):
dirstate: phase-divergent update to 65943224c184...
r51051 """check that the func is called with a non-invalidated dirstate
dirstate: introduce a check_invalidated decorator...
r51013
The dirstate is in an "invalidated state" after an error occured during its
modification and remains so until we exited the top level scope that framed
such change.
"""
def wrap(self, *args, **kwargs):
if self._invalidated_context:
msg = 'calling `%s` after the dirstate was invalidated'
msg %= func.__name__
raise error.ProgrammingError(msg)
return func(self, *args, **kwargs)
return wrap
dirstate: rename `@requires_parents_change` to `@requires_changing_parents`...
r50857 def requires_changing_parents(func):
dirstate: add a function to update tracking status while "moving" parents...
r48392 def wrap(self, *args, **kwargs):
dirstate: rename `pendingparentchange` to `is_changing_parents`...
r50917 if not self.is_changing_parents:
dirstate: rename parentchange to changing_parents...
r50855 msg = 'calling `%s` outside of a changing_parents context'
dirstate: add a function to update tracking status while "moving" parents...
r48392 msg %= func.__name__
raise error.ProgrammingError(msg)
return func(self, *args, **kwargs)
dirstate: introduce a check_invalidated decorator...
r51013 return check_invalidated(wrap)
dirstate: add a function to update tracking status while "moving" parents...
r48392
dirstate: enforce the use of `changing_files` context to change tracking...
r50955 def requires_changing_files(func):
def wrap(self, *args, **kwargs):
if not self.is_changing_files:
msg = 'calling `%s` outside of a `changing_files`'
dirstate: add a function to update tracking status while "moving" parents...
r48392 msg %= func.__name__
raise error.ProgrammingError(msg)
return func(self, *args, **kwargs)
dirstate: introduce a check_invalidated decorator...
r51013 return check_invalidated(wrap)
dirstate: add a function to update tracking status while "moving" parents...
r48392
dirstate: add a `require_changing_any` decorator...
r51003 def requires_changing_any(func):
def wrap(self, *args, **kwargs):
if not self.is_changing_any:
msg = 'calling `%s` outside of a changing context'
msg %= func.__name__
raise error.ProgrammingError(msg)
return func(self, *args, **kwargs)
dirstate: introduce a check_invalidated decorator...
r51013 return check_invalidated(wrap)
dirstate: add a `require_changing_any` decorator...
r51003
dirstate: enforce context set_clean and set_possibly_dirty...
r51047 def requires_changing_files_or_status(func):
dirstate: add a `set_tracked` method for "hg add"-like usage...
r48393 def wrap(self, *args, **kwargs):
dirstate: enforce context set_clean and set_possibly_dirty...
r51047 if not (self.is_changing_files or self._running_status > 0):
msg = (
'calling `%s` outside of a changing_files '
'or running_status context'
)
dirstate: add a `set_tracked` method for "hg add"-like usage...
r48393 msg %= func.__name__
raise error.ProgrammingError(msg)
return func(self, *args, **kwargs)
dirstate: introduce a check_invalidated decorator...
r51013 return check_invalidated(wrap)
dirstate: add a `set_tracked` method for "hg add"-like usage...
r48393
dirstate: factor the "changing" context logic out...
r50919 CHANGE_TYPE_PARENTS = "parents"
dirstate: add a context for tracking files change...
r50921 CHANGE_TYPE_FILES = "files"
dirstate: factor the "changing" context logic out...
r50919
Matt Harbison
dirstate: subclass the new dirstate Protocol class...
r52818 class dirstate(intdirstate.idirstate):
dirstate: phase-divergent update to 4e95341c89aa...
r51052 # used by largefile to avoid overwritting transaction callback
dirstate: distinct transaction callback from largefile...
r51018 _tr_key_suffix = b''
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 def __init__(
Simon Sapin
dirstate-v2: Change the on-disk format when the requirement is enabled...
r48055 self,
opener,
ui,
root,
validate,
sparsematchfn,
nodeconstants,
use_dirstate_v2,
tracked-key: remove the dual write and rename to tracked-hint...
r49644 use_tracked_hint=False,
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 ):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Create a new dirstate object.
Martin Geisler
dirstate: improve docstring formatting...
r10145
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.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Simon Sapin
dirstate-v2: Change the on-disk format when the requirement is enabled...
r48055 self._use_dirstate_v2 = use_dirstate_v2
tracked-key: remove the dual write and rename to tracked-hint...
r49644 self._use_tracked_hint = use_tracked_hint
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 self._nodeconstants = nodeconstants
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
sparse: use None as the sparse matcher value when disabled...
r50250 # Either build a sparse-matcher or None if sparse is disabled
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)
dirstate: introduce a "tracked-key" feature...
r49533 # True is any internal state may be different
Matt Mackall
dirstate: use True and false for _dirty
r4903 self._dirty = False
dirstate: introduce a "tracked-key" feature...
r49533 # True if the set of tracked file may be different
self._dirty_tracked_set = False
Matt Mackall
dirstate: hide internal vars...
r4614 self._ui = ui
Idan Kamara
dirstate: add filecache support
r16200 self._filecache = {}
dirstate: rename parentchange to changing_parents...
r50855 # nesting level of `changing_parents` context
dirstate: rename _parentwriters to _changing_level...
r50916 self._changing_level = 0
dirstate: factor the "changing" context logic out...
r50919 # the change currently underway
self._change_type = None
dirstate: start tracking that we are within a `running_status` context
r51040 # number of open _running_status context
self._running_status = 0
dirstate: invalidate changes when parent-change fails...
r50852 # True if the current dirstate changing operations have been
# invalidated (used to make sure all nested contexts have been exited)
self._invalidated_context = False
dirstate: track that changes are pending in a transaction...
r51017 self._attached_to_a_transaction = False
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self._filename = b'dirstate'
tracked-key: remove the dual write and rename to tracked-hint...
r49644 self._filename_th = b'dirstate-tracked-hint'
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 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
dirstate: split dirstatemap in its own file...
r48295 self._mapcls = dirstatemap.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
dirstate: only reload the dirstate when it may have changed...
r51023 def refresh(self):
dirstate: fix a potential traceback when in `copy` and `rename`...
r51225 # XXX if this happens, you likely did not enter the `changing_xxx`
# using `repo.dirstate`, so a later `repo.dirstate` accesss might call
# `refresh`.
if self.is_changing_any:
msg = "refreshing the dirstate in the middle of a change"
raise error.ProgrammingError(msg)
dirstate: only reload the dirstate when it may have changed...
r51023 if '_branch' in vars(self):
del self._branch
if '_map' in vars(self) and self._map.may_need_refresh():
self.invalidate()
dirstate: make sure the dirstate is loaded before the changelog (issue6303)...
r45359 def prefetch_parents(self):
"""make sure the parents are loaded
Used to avoid a race condition.
"""
self._pl
Augie Fackler
dirstate: introduce new context manager for marking dirstate parent changes
r32346 @contextlib.contextmanager
dirstate: use the new `check_invalidated` decorator for `_changing`...
r51014 @check_invalidated
dirstate: introduce a (noop) running_status context...
r51027 def running_status(self, repo):
"""Wrap a status operation
dirstate: add documentation about the expectation of `running_status` context
r51039 This context is not mutally exclusive with the `changing_*` context. It
also do not warrant for the `wlock` to be taken.
dirstate: have `running_status` write the dirstate when holding the lock...
r51042 If the wlock is taken, this context will behave in a simple way, and
ensure the data are scheduled for write when leaving the top level
context.
dirstate: add documentation about the expectation of `running_status` context
r51039
If the lock is not taken, it will only warrant that the data are either
committed (written) and rolled back (invalidated) when exiting the top
level context. The write/invalidate action must be performed by the
wrapped code.
The expected logic is:
A: read the dirstate
B: run status
This might make the dirstate dirty by updating cache,
especially in Rust.
C: do more "post status fixup if relevant
D: try to take the w-lock (this will invalidate the changes if they were raced)
E0: if dirstate changed on disk → discard change (done by dirstate internal)
E1: elif lock was acquired → write the changes
E2: else → discard the changes
dirstate: introduce a (noop) running_status context...
r51027 """
dirstate: have `running_status` write the dirstate when holding the lock...
r51042 has_lock = repo.currentwlock() is not None
dirstate: check that dirstate is clean at the initial context opening...
r51041 is_changing = self.is_changing_any
dirstate: have `running_status` write the dirstate when holding the lock...
r51042 tr = repo.currenttransaction()
has_tr = tr is not None
dirstate: check that dirstate is clean at the initial context opening...
r51041 nested = bool(self._running_status)
first_and_alone = not (is_changing or has_tr or nested)
# enforce no change happened outside of a proper context.
if first_and_alone and self._dirty:
has_tr = repo.currenttransaction() is not None
if not has_tr and self._changing_level == 0 and self._dirty:
msg = "entering a status context, but dirstate is already dirty"
raise error.ProgrammingError(msg)
dirstate: have `running_status` write the dirstate when holding the lock...
r51042 should_write = has_lock and not (nested or is_changing)
dirstate: start tracking that we are within a `running_status` context
r51040 self._running_status += 1
try:
yield
except Exception:
self.invalidate()
raise
finally:
self._running_status -= 1
if self._invalidated_context:
dirstate: have `running_status` write the dirstate when holding the lock...
r51042 should_write = False
dirstate: start tracking that we are within a `running_status` context
r51040 self.invalidate()
dirstate: introduce a (noop) running_status context...
r51027
dirstate: have `running_status` write the dirstate when holding the lock...
r51042 if should_write:
assert repo.currenttransaction() is tr
self.write(tr)
dirstate: have `running_status` warn when exiting with a dirty dirstate...
r51043 elif not has_lock:
if self._dirty:
msg = b'dirstate dirty while exiting an isolated status context'
repo.ui.develwarn(msg)
self.invalidate()
dirstate: have `running_status` write the dirstate when holding the lock...
r51042
dirstate: introduce a (noop) running_status context...
r51027 @contextlib.contextmanager
@check_invalidated
dirstate: factor the "changing" context logic out...
r50919 def _changing(self, repo, change_type):
dirstate: enforce holding the lock while doing any changes...
r50860 if repo.currentwlock() is None:
dirstate: factor the "changing" context logic out...
r50919 msg = b"trying to change the dirstate without holding the wlock"
dirstate: enforce holding the lock while doing any changes...
r50860 raise error.ProgrammingError(msg)
dirstate: factor the "changing" context logic out...
r50919
dirstate: detect potential fishy transaction patterns while changing...
r50973 has_tr = repo.currenttransaction() is not None
dirstate: warn if dirty when starting an edition...
r51012 if not has_tr and self._changing_level == 0 and self._dirty:
dirstate: phase-divergent update to 3433723d1b9b...
r51050 msg = b"entering a changing context, but dirstate is already dirty"
repo.ui.develwarn(msg)
Augie Fackler
dirstate: introduce new context manager for marking dirstate parent changes
r32346
dirstate: simplify the invalidation management on context exit...
r51015 assert self._changing_level >= 0
dirstate: factor the "changing" context logic out...
r50919 # different type of change are mutually exclusive
if self._change_type is None:
assert self._changing_level == 0
self._change_type = change_type
elif self._change_type != change_type:
msg = (
'trying to open "%s" dirstate-changing context while a "%s" is'
' already open'
)
msg %= (change_type, self._change_type)
raise error.ProgrammingError(msg)
dirstate: simplify the invalidation management on context exit...
r51015 should_write = False
dirstate: rename _parentwriters to _changing_level...
r50916 self._changing_level += 1
dirstate: invalidate changes when parent-change fails...
r50852 try:
yield
dirstate: invalidate on all exceptions...
r51000 except: # re-raises
dirstate: simplify the invalidation management on context exit...
r51015 self.invalidate() # this will set `_invalidated_context`
dirstate: invalidate changes when parent-change fails...
r50852 raise
finally:
dirstate: simplify the invalidation management on context exit...
r51015 assert self._changing_level > 0
self._changing_level -= 1
# If the dirstate is being invalidated, call invalidate again.
# This will throw away anything added by a upper context and
# reset the `_invalidated_context` flag when relevant
if self._changing_level <= 0:
self._change_type = None
assert self._changing_level == 0
if self._invalidated_context:
# make sure we invalidate anything an upper context might
# have changed.
self.invalidate()
else:
should_write = self._changing_level <= 0
tr = repo.currenttransaction()
if has_tr != (tr is not None):
if has_tr:
m = "transaction vanished while changing dirstate"
else:
m = "transaction appeared while changing dirstate"
raise error.ProgrammingError(m)
if should_write:
self.write(tr)
Augie Fackler
dirstate: introduce new context manager for marking dirstate parent changes
r32346
dirstate: factor the "changing" context logic out...
r50919 @contextlib.contextmanager
def changing_parents(self, repo):
dirstate: document the `changing_*` context manager...
r51962 """Wrap a dirstate change related to a change of working copy parents
This context scopes a series of dirstate modifications that match an
update of the working copy parents (typically `hg update`, `hg merge`
etc).
The dirstate's methods that perform this kind of modifications require
this context to be present before being called.
Such methods are decorated with `@requires_changing_parents`.
The new dirstate contents will be written to disk when the top-most
`changing_parents` context exits successfully. If an exception is
raised during a `changing_parents` context of any level, all changes
are invalidated. If this context is open within an open transaction,
the dirstate writing is delayed until that transaction is successfully
committed (and the dirstate is invalidated on transaction abort).
The `changing_parents` operation is mutually exclusive with the
`changing_files` one.
"""
dirstate: factor the "changing" context logic out...
r50919 with self._changing(repo, CHANGE_TYPE_PARENTS) as c:
yield c
dirstate: add a context for tracking files change...
r50921 @contextlib.contextmanager
def changing_files(self, repo):
dirstate: document the `changing_*` context manager...
r51962 """Wrap a dirstate change related to the set of tracked files
This context scopes a series of dirstate modifications that change the
set of tracked files. (typically `hg add`, `hg remove` etc) or some
dirstate stored information (like `hg rename --after`) but preserve
the working copy parents.
The dirstate's methods that perform this kind of modifications require
this context to be present before being called.
Such methods are decorated with `@requires_changing_files`.
The new dirstate contents will be written to disk when the top-most
`changing_files` context exits successfully. If an exception is raised
during a `changing_files` context of any level, all changes are
invalidated. If this context is open within an open transaction, the
dirstate writing is delayed until that transaction is successfully
committed (and the dirstate is invalidated on transaction abort).
The `changing_files` operation is mutually exclusive with the
`changing_parents` one.
"""
dirstate: add a context for tracking files change...
r50921 with self._changing(repo, CHANGE_TYPE_FILES) as c:
yield c
dirstate: rename parentchange to changing_parents...
r50855 # here to help migration to the new code
def parentchange(self):
msg = (
"Mercurial 6.4 and later requires call to "
"`dirstate.changing_parents(repo)`"
)
raise error.ProgrammingError(msg)
dirstate: introduce a `is_changing_any` property...
r50918 @property
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def is_changing_any(self) -> bool:
dirstate: introduce a `is_changing_any` property...
r50918 """Returns true if the dirstate is in the middle of a set of changes.
This returns True for any kind of change.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
dirstate: introduce a `is_changing_any` property...
r50918 return self._changing_level > 0
Augie Fackler
dirstate: introduce new context manager for marking dirstate parent changes
r32346
dirstate: rename `pendingparentchange` to `is_changing_parents`...
r50917 @property
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def is_changing_parents(self) -> bool:
dirstate: rename `pendingparentchange` to `is_changing_parents`...
r50917 """Returns true if the dirstate is in the middle of a set of changes
that modify the dirstate parent.
"""
dirstate: factor the "changing" context logic out...
r50919 if self._changing_level <= 0:
return False
return self._change_type == CHANGE_TYPE_PARENTS
mpm@selenic.com
Break apart hg.py...
r1089
dirstate: add a context for tracking files change...
r50921 @property
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def is_changing_files(self) -> bool:
dirstate: add a context for tracking files change...
r50921 """Returns true if the dirstate is in the middle of a set of changes
that modify the files tracked or their sources.
"""
if self._changing_level <= 0:
return False
return self._change_type == CHANGE_TYPE_FILES
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)."""
dirstate: cleanup the `_map` property cache...
r51024 return self._mapcls(
Simon Sapin
dirstate-v2: Change the on-disk format when the requirement is enabled...
r48055 self._ui,
self._opener,
self._root,
self._nodeconstants,
self._use_dirstate_v2,
Joerg Sonnenberger
node: introduce nodeconstants class...
r47538 )
Matt Mackall
dirstate: use propertycache
r8261
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.
sparse: use None as the sparse matcher value when disabled...
r50250
When sparse if disabled, return None.
Gregory Szorc
dirstate: expose a sparse matcher on dirstate (API)...
r33373 """
sparse: use None as the sparse matcher value when disabled...
r50250 if self._sparsematchfn is None:
return None
Gregory Szorc
dirstate: expose a sparse matcher on dirstate (API)...
r33373 # 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):
dirstate: write the `branch` as part of the transaction if any...
r51151 f = None
data = b''
Matt Mackall
dirstate: use propertycache
r8261 try:
dirstate: write the `branch` as part of the transaction if any...
r51151 f, mode = txnutil.trypending(self._root, self._opener, b'branch')
data = f.read().strip()
Manuel Jacob
py3: catch FileNotFoundError instead of checking errno == ENOENT
r50201 except FileNotFoundError:
dirstate: write the `branch` as part of the transaction if any...
r51151 pass
finally:
if f is not None:
f.close()
if not data:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b"default"
dirstate: write the `branch` as part of the transaction if any...
r51151 return data
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
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def hasdir(self, d: bytes) -> bool:
Mark Thomas
dirstate: add explicit methods for querying directories (API)...
r35083 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 Harbison
typing: add type annotations to the dirstate classes...
r52822 def _ignore(self) -> matchmod.basematcher:
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
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def _checklink(self) -> bool:
Matt Mackall
dirstate: use propertycache
r8261 return util.checklink(self._root)
@propertycache
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def _checkexec(self) -> bool:
Mitchell Plamann
dirstate: force _checkexec to return a bool...
r45310 return bool(util.checkexec(self._root))
Matt Mackall
dirstate: use propertycache
r8261
@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 Harbison
typing: add type annotations to the dirstate classes...
r52822 def flagfunc(
self, buildfallback: intdirstate.FlagFuncFallbackT
) -> intdirstate.FlagFuncReturnT:
dirstate: use a single closure for get_flags...
r49111 """build a callable that returns flags associated with a filename
Augie Fackler
formatting: blacken the codebase...
r43346
dirstate: use a single closure for get_flags...
r49111 The information is extracted from three possible layers:
1. the file system if it supports the information
2. the "fallback" information stored in the dirstate if any
3. a more expensive mechanism inferring the flags from the parents.
"""
# small hack to cache the result of buildfallback()
fallback_func = []
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def get_flags(x: bytes) -> bytes:
dirstate: use a single closure for get_flags...
r49111 entry = None
fallback_value = None
Raphaël Gomès
dirstate: group return logic and clarify each function in flagfunc...
r49103 try:
st = os.lstat(self._join(x))
dirstate: use a single closure for get_flags...
r49111 except OSError:
return b''
if self._checklink:
Raphaël Gomès
dirstate: group return logic and clarify each function in flagfunc...
r49103 if util.statislink(st):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'l'
dirstate: use a single closure for get_flags...
r49111 else:
entry = self.get_entry(x)
if entry.has_fallback_symlink:
if entry.fallback_symlink:
return b'l'
else:
if not fallback_func:
fallback_func.append(buildfallback())
fallback_value = fallback_func[0](x)
if b'l' in fallback_value:
return b'l'
if self._checkexec:
Raphaël Gomès
dirstate: group return logic and clarify each function in flagfunc...
r49103 if util.statisexec(st):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b'x'
dirstate: use a single closure for get_flags...
r49111 else:
if entry is None:
entry = self.get_entry(x)
if entry.has_fallback_exec:
if entry.fallback_exec:
return b'x'
else:
if fallback_value is None:
if not fallback_func:
fallback_func.append(buildfallback())
fallback_value = fallback_func[0](x)
if b'x' in fallback_value:
return b'x'
Raphaël Gomès
dirstate: group return logic and clarify each function in flagfunc...
r49103 return b''
Augie Fackler
formatting: blacken the codebase...
r43346
dirstate: use a single closure for get_flags...
r49111 return get_flags
Raphaël Gomès
dirstate: add missing return on platforms without exec or symlink...
r49102
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
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def getcwd(self) -> bytes:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Return the path from which a canonical path is calculated.
Yuya Nishihara
dirstate: state that getcwd() shouldn't be used to get real file path...
r26293
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.
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
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
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def pathto(self, f: bytes, cwd: Optional[bytes] = None) -> bytes:
Alexis S. L. Carvalho
Add dirstate.pathto and localrepo.pathto....
r4525 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
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def get_entry(self, path: bytes) -> intdirstate.DirstateItemT:
dirstate: add a `get_entry` method to the dirstate...
r48897 """return a DirstateItem for the associated path"""
entry = self._map.get(path)
if entry is None:
return DirstateItem()
return entry
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def __contains__(self, key: Any) -> bool:
Matt Mackall
dirstate: hide internal vars...
r4614 return key in self._map
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def __iter__(self) -> Iterator[bytes]:
Alex Gaynor
dirstate: simplify dirstate's __iter__...
r33673 return iter(sorted(self._map))
mpm@selenic.com
Break apart hg.py...
r1089
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def items(self) -> Iterator[Tuple[bytes, intdirstate.DirstateItemT]]:
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 return self._map.items()
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
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def parents(self) -> List[bytes]:
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 Harbison
typing: add type annotations to the dirstate classes...
r52822 def p1(self) -> bytes:
Matt Mackall
dirstate: add p1/p2 convenience methods
r13876 return self._validate(self._pl[0])
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def p2(self) -> bytes:
Matt Mackall
dirstate: add p1/p2 convenience methods
r13876 return self._validate(self._pl[1])
dirstate: add a `in_merge` property...
r48299 @property
def in_merge(self):
"""True if a merge is in progress"""
return self._pl[1] != self._nodeconstants.nullid
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def branch(self) -> bytes:
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
dirstate: requires being in a `changing_parents` `context to set_parents`...
r51001 @requires_changing_parents
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def setparents(self, p1: bytes, p2: Optional[bytes] = None):
Patrick Mezard
localrepo: add setparents() to adjust dirstate copies (issue3407)...
r16551 """Set dirstate parents to p1 and p2.
dirstate-entry: add a `merged` property...
r48302 When moving from two parents to one, "merged" entries a
Patrick Mezard
localrepo: add setparents() to adjust dirstate copies (issue3407)...
r16551 adjusted to normal and previous copy records discarded and
returned by the call.
See localrepo.setparents()
"""
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 if p2 is None:
p2 = self._nodeconstants.nullid
dirstate: rename _parentwriters to _changing_level...
r50916 if self._changing_level == 0:
Augie Fackler
formatting: blacken the codebase...
r43346 raise ValueError(
Matt Harbison
dirstate: stringify a few exception messages...
r52612 "cannot set dirstate parent outside of "
"dirstate.changing_parents 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
dirstate: make a conditionnal easier to read in `setparents`...
r48801 nullid = self._nodeconstants.nullid
dirstate: move parent state handling in the dirstatemap...
r48873 # True if we need to fold p2 related state back to a linear case
fold_p2 = oldp2 != nullid and p2 == nullid
return self._map.setparents(p1, p2, fold_p2=fold_p2)
mpm@selenic.com
Break apart hg.py...
r1089
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def setbranch(
self, branch: bytes, transaction: Optional[intdirstate.TransactionT]
) -> None:
Yuya Nishihara
filecache: unimplement __set__() and __delete__() (API)...
r40454 self.__class__._branch.set(self, encoding.fromlocal(branch))
dirstate: write the `branch` as part of the transaction if any...
r51151 if transaction is not None:
self._setup_tr_abort(transaction)
transaction.addfilegenerator(
b'dirstate-3-branch%s' % self._tr_key_suffix,
(b'branch',),
self._write_branch,
location=b'plain',
post_finalize=True,
)
return
dirstate: use a context manager to handle the file used for writing the branch...
r51149 vfs = self._opener
with vfs(b'branch', b'w', atomictemp=True, checkambig=True) as f:
dirstate: write the `branch` as part of the transaction if any...
r51151 self._write_branch(f)
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
dirstate: use a context manager to handle the file used for writing the branch...
r51149 #
# XXX do we actually need this,
# refreshing the attribute is quite cheap
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()
Matt Mackall
Move branch read/write to dirstate where it belongs
r4179
dirstate: write the `branch` as part of the transaction if any...
r51151 def _write_branch(self, file_obj):
file_obj.write(self._branch + b'\n')
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def invalidate(self) -> None:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Causes the next access to reread the dirstate.
Siddharth Agarwal
dirstate: add docstring for invalidate...
r32682
This is different from localrepo.invalidatedirstate() because it always
rereads the dirstate. Use localrepo.invalidatedirstate() if you want to
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 check whether the dirstate has changed before rereading it."""
Siddharth Agarwal
dirstate: add docstring for invalidate...
r32682
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)
Matt Mackall
dirstate: use True and false for _dirty
r4903 self._dirty = False
dirstate: introduce a "tracked-key" feature...
r49533 self._dirty_tracked_set = False
dirstate: start tracking that we are within a `running_status` context
r51040 self._invalidated_context = bool(
self._changing_level > 0
or self._attached_to_a_transaction
or self._running_status
dirstate: track that changes are pending in a transaction...
r51017 )
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
dirstate: mark the `copy` method as requiring a `changing_any` context...
r51004 @requires_changing_any
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def copy(self, source: Optional[bytes], dest: bytes) -> None:
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:
sparse: directly inline the `set_tracked` and `copy` wrapping...
r50255 self._check_sparse(source)
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 self._map.copymap[dest] = source
dirstate: drop the `_updatedfiles` set...
r48871 else:
self._map.copymap.pop(dest, None)
mpm@selenic.com
Break apart hg.py...
r1089
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def copied(self, file: bytes) -> Optional[bytes]:
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 return self._map.copymap.get(file, None)
Matt Mackall
dirstate: add copies function...
r3154
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def copies(self) -> Dict[bytes, bytes]:
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 return self._map.copymap
mpm@selenic.com
Break apart hg.py...
r1089
dirstate: enforce the use of `changing_files` context to change tracking...
r50955 @requires_changing_files
dirstate: do no use `set_clean` in revert...
r49207 def set_tracked(self, filename, reset_copy=False):
dirstate: add a `set_tracked` method for "hg add"-like usage...
r48393 """a "public" method for generic code to mark a file as tracked
This function is to be called outside of "update/merge" case. For
example by a command like `hg add X`.
dirstate: do no use `set_clean` in revert...
r49207 if reset_copy is set, any existing copy information will be dropped.
dirstate: add a `set_tracked` method for "hg add"-like usage...
r48393 return True the file was previously untracked, False otherwise.
"""
dirstate: directly call the right function in `set_tracked`...
r48798 self._dirty = True
dirstate: add a `set_tracked` method for "hg add"-like usage...
r48393 entry = self._map.get(filename)
dirstate: introduce a set_tracked method on "map" and "item"...
r48804 if entry is None or not entry.tracked:
dirstate: directly call the right function in `set_tracked`...
r48798 self._check_new_tracked_filename(filename)
dirstate: do no use `set_clean` in revert...
r49207 pre_tracked = self._map.set_tracked(filename)
if reset_copy:
self._map.copymap.pop(filename, None)
dirstate: introduce a "tracked-key" feature...
r49533 if pre_tracked:
self._dirty_tracked_set = True
dirstate: do no use `set_clean` in revert...
r49207 return pre_tracked
dirstate: add a `set_tracked` method for "hg add"-like usage...
r48393
dirstate: enforce the use of `changing_files` context to change tracking...
r50955 @requires_changing_files
dirstate: add a `set_untracked` method for "hg remove"-like usage...
r48399 def set_untracked(self, filename):
"""a "public" method for generic code to mark a file as untracked
This function is to be called outside of "update/merge" case. For
example by a command like `hg remove X`.
return True the file was previously tracked, False otherwise.
"""
dirstate: make dirstatemap.set_untracked deal with added file...
r48786 ret = self._map.set_untracked(filename)
if ret:
dirstate: directly call the dirstatemap in `set_untracked`...
r48669 self._dirty = True
dirstate: introduce a "tracked-key" feature...
r49533 self._dirty_tracked_set = True
dirstate: make dirstatemap.set_untracked deal with added file...
r48786 return ret
dirstate: add a `set_untracked` method for "hg remove"-like usage...
r48399
dirstate: enforce context set_clean and set_possibly_dirty...
r51047 @requires_changing_files_or_status
dirstate: make it mandatory to provide parentfiledata in `set_clean`...
r49208 def set_clean(self, filename, parentfiledata):
dirstate: introduce a `set_clean` method...
r48504 """record that the current state of the file on disk is known to be clean"""
self._dirty = True
dirstate: introduce a `set_clean` method on dirstate's map and items...
r48788 if not self._map[filename].tracked:
self._check_new_tracked_filename(filename)
dirstate: make it mandatory to provide parentfiledata in `set_clean`...
r49208 (mode, size, mtime) = parentfiledata
dirstate: introduce a `set_clean` method on dirstate's map and items...
r48788 self._map.set_clean(filename, mode, size, mtime)
dirstate: introduce a `set_clean` method...
r48504
dirstate: enforce context set_clean and set_possibly_dirty...
r51047 @requires_changing_files_or_status
dirstate: add a `set_possibly_dirty` method...
r48520 def set_possibly_dirty(self, filename):
"""record that the current state of the file on disk is unknown"""
self._dirty = True
self._map.set_possibly_dirty(filename)
dirstate: rename `@requires_parents_change` to `@requires_changing_parents`...
r50857 @requires_changing_parents
dirstate: rename `update_file_reference` to `update_file_p1`...
r48493 def update_file_p1(
dirstate: add a function to update tracking status while "moving" parents...
r48392 self,
filename,
p1_tracked,
):
"""Set a file as tracked in the parent (or not)
This is to be called when adjust the dirstate to a new parent after an history
rewriting operation.
It should not be called during a merge (p2 != nullid) and only within
dirstate: rename parentchange to changing_parents...
r50855 a `with dirstate.changing_parents(repo):` context.
dirstate: add a function to update tracking status while "moving" parents...
r48392 """
if self.in_merge:
Matt Harbison
dirstate: stringify a few exception messages...
r52612 msg = 'update_file_reference should not be called when merging'
dirstate: add a function to update tracking status while "moving" parents...
r48392 raise error.ProgrammingError(msg)
entry = self._map.get(filename)
if entry is None:
wc_tracked = False
else:
wc_tracked = entry.tracked
dirstate: align the dirstatemap's API to the data change...
r48952 if not (p1_tracked or wc_tracked):
dirstate: add a function to update tracking status while "moving" parents...
r48392 # the file is no longer relevant to anyone
dirstate: use `reset_state` to drop file in `update_file_p1`...
r48813 if self._map.get(filename) is not None:
self._map.reset_state(filename)
dirstate: inline the last two `_drop` usage...
r48802 self._dirty = True
dirstate: add a function to update tracking status while "moving" parents...
r48392 elif (not p1_tracked) and wc_tracked:
dirstate: use `reset_state` in `update_file_p1`...
r48494 if entry is not None and entry.added:
return # avoid dropping copy information (maybe?)
dirstate: add a function to update tracking status while "moving" parents...
r48392
dirstate: use `reset_state` in `update_file_p1`...
r48494 self._map.reset_state(
filename,
wc_tracked,
p1_tracked,
dirstate: align the dirstatemap's API to the data change...
r48952 # the underlying reference might have changed, we will have to
# check it.
has_meaningful_mtime=False,
dirstate: use `reset_state` in `update_file_p1`...
r48494 )
dirstate: rename `@requires_parents_change` to `@requires_changing_parents`...
r50857 @requires_changing_parents
dirstate: add a `update_file` function...
r48411 def update_file(
self,
filename,
wc_tracked,
p1_tracked,
dirstate: align the dirstate's API to the lower level ones...
r48956 p2_info=False,
dirstate: add a `update_file` function...
r48411 possibly_dirty=False,
dirstate: replace `update_parent_file_data` with simpler `update_parent` call...
r48491 parentfiledata=None,
dirstate: add a `update_file` function...
r48411 ):
"""update the information about a file in the dirstate
This is to be called when the direstates parent changes to keep track
of what is the file situation in regards to the working copy and its parent.
dirstate: rename parentchange to changing_parents...
r50855 This function must be called within a `dirstate.changing_parents` context.
dirstate: add a `update_file` function...
r48411
Augie Fackler
dirstate: fix typo in docstring...
r48570 note: the API is at an early stage and we might need to adjust it
dirstate: add a `update_file` function...
r48411 depending of what information ends up being relevant and useful to
other processing.
"""
dirstate: introduce a `hacky_extension_update_file` method...
r50906 self._update_file(
filename=filename,
wc_tracked=wc_tracked,
p1_tracked=p1_tracked,
p2_info=p2_info,
possibly_dirty=possibly_dirty,
parentfiledata=parentfiledata,
)
def hacky_extension_update_file(self, *args, **kwargs):
"""NEVER USE THIS, YOU DO NOT NEED IT
This function is a variant of "update_file" to be called by a small set
of extensions, it also adjust the internal state of file, but can be
called outside an `changing_parents` context.
A very small number of extension meddle with the working copy content
in a way that requires to adjust the dirstate accordingly. At the time
this command is written they are :
- keyword,
- largefile,
PLEASE DO NOT GROW THIS LIST ANY FURTHER.
This function could probably be replaced by more semantic one (like
"adjust expected size" or "always revalidate file content", etc)
however at the time where this is writen, this is too much of a detour
to be considered.
"""
dirstate: enforce change context for hacky_extension_update_file...
r51049 if not (self._changing_level > 0 or self._running_status > 0):
msg = "requires a changes context"
raise error.ProgrammingError(msg)
dirstate: introduce a `hacky_extension_update_file` method...
r50906 self._update_file(
*args,
**kwargs,
)
def _update_file(
self,
filename,
wc_tracked,
p1_tracked,
p2_info=False,
possibly_dirty=False,
parentfiledata=None,
):
dirstate-map: move most of `dirstate.update_file` logic in the dsmap...
r48492 # note: I do not think we need to double check name clash here since we
# are in a update/merge case that should already have taken care of
# this. The test agrees
self._dirty = True
dirstate: introduce a "tracked-key" feature...
r49533 old_entry = self._map.get(filename)
if old_entry is None:
prev_tracked = False
else:
prev_tracked = old_entry.tracked
if prev_tracked != wc_tracked:
self._dirty_tracked_set = True
dirstate-map: move most of `dirstate.update_file` logic in the dsmap...
r48492
self._map.reset_state(
filename,
wc_tracked,
p1_tracked,
dirstate: align the dirstate's API to the lower level ones...
r48956 p2_info=p2_info,
dirstate: align the dirstatemap's API to the data change...
r48952 has_meaningful_mtime=not possibly_dirty,
dirstate-map: move most of `dirstate.update_file` logic in the dsmap...
r48492 parentfiledata=parentfiledata,
)
dirstate: add a `update_file` function...
r48411
dirstate: extract the logic to check file/dirname collision when adding a file...
r48787 def _check_new_tracked_filename(self, filename):
scmutil.checkfilename(filename)
if self._map.hastrackeddir(filename):
msg = _(b'directory %r already in dirstate')
msg %= pycompat.bytestr(filename)
raise error.Abort(msg)
# shadows
for d in pathutil.finddirs(filename):
if self._map.hastrackeddir(d):
break
entry = self._map.get(d)
if entry is not None and not entry.removed:
msg = _(b'file %r in dirstate clashes with %r')
msg %= (pycompat.bytestr(d), pycompat.bytestr(filename))
raise error.Abort(msg)
sparse: directly inline the `set_tracked` and `copy` wrapping...
r50255 self._check_sparse(filename)
def _check_sparse(self, filename):
"""Check that a filename is inside the sparse profile"""
sparsematch = self._sparsematcher
if sparsematch is not None and not sparsematch.always():
if not sparsematch(filename):
msg = _(b"cannot add '%s' - it is outside the sparse checkout")
hint = _(
b'include file with `hg debugsparse --include <pattern>` or use '
b'`hg add -s <file>` to include file directory while adding'
)
raise error.Abort(msg % filename, hint=hint)
dirstate: extract the logic to check file/dirname collision when adding a file...
r48787
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
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def normalize(
self, path: bytes, isknown: bool = False, ignoremissing: bool = False
) -> bytes:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
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
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Matt Mackall
dirstate: introduce a public case normalizing method
r13717
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
dirstate: add a comment about the semantic of `dirstate.clear`...
r51009 # XXX this method is barely used, as a result:
# - its semantic is unclear
# - do we really needs it ?
dirstate: mark `clear` and `rebuild` as `require_changing_parents`...
r51010 @requires_changing_parents
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def clear(self) -> None:
Durham Goode
dirstate: move clear onto dirstatemap class...
r34934 self._map.clear()
Alexis S. L. Carvalho
merge with crew-stable
r5123 self._dirty = True
Alexis S. L. Carvalho
dirstate: fix rebuild; add a test...
r5065
dirstate: mark `clear` and `rebuild` as `require_changing_parents`...
r51010 @requires_changing_parents
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def rebuild(
self,
parent: bytes,
allfiles: Iterable[bytes], # TODO: more than iterable? (uses len())
changedfiles: Optional[Iterable[bytes]] = None,
) -> None:
sparse: directly inline the `rebuild` wrapping...
r50252 matcher = self._sparsematcher
if matcher is not None and not matcher.always():
# should not add non-matching files
allfiles = [f for f in allfiles if matcher(f)]
if changedfiles:
changedfiles = [f for f in changedfiles if matcher(f)]
if changedfiles is not None:
# these files will be deleted from the dirstate when they are
# not found to be in allfiles
dirstatefilestoremove = {f for f in self if not matcher(f)}
changedfiles = dirstatefilestoremove.union(changedfiles)
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 self.clear()
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
Joerg Sonnenberger
node: replace nullid and friends with nodeconstants class...
r47771 self._map.setparents(parent, self._nodeconstants.nullid)
Kyle Lippincott
dirstate: when calling rebuild(), avoid some N^2 codepaths...
r44343
for f in to_lookup:
dirstate: replace the use of `_normallookup` in `rebuild`...
r48806 if self.in_merge:
self.set_tracked(f)
else:
self._map.reset_state(
f,
wc_tracked=True,
p1_tracked=True,
)
Kyle Lippincott
dirstate: when calling rebuild(), avoid some N^2 codepaths...
r44343 for f in to_drop:
dirstate: use `reset_state` in `rebuild` instead of `dropfile`...
r48814 self._map.reset_state(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
dirstate: factor the transaction abort logic...
r51150 def _setup_tr_abort(self, tr):
"""make sure we invalidate the current change on abort"""
if tr is None:
return
def on_abort(tr):
self._attached_to_a_transaction = False
self.invalidate()
tr.addabort(
b'dirstate-invalidate%s' % self._tr_key_suffix,
on_abort,
)
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def write(self, tr: Optional[intdirstate.TransactionT]) -> None:
Matt Mackall
dirstate: simplify dirty handling
r4612 if not self._dirty:
Benoit Boissinot
only write the dirstate when something changed
r1794 return
dirstate: add small asserts for double security...
r51016 # make sure we don't request a write of invalidated content
# XXX move before the dirty check once `unlock` stop calling `write`
assert not self._invalidated_context
FUJIWARA Katsunori
dirstate: delay writing out to ensure timestamp of each entries explicitly...
r21931
tracked-key: remove the dual write and rename to tracked-hint...
r49644 write_key = self._use_tracked_hint and self._dirty_tracked_set
Pierre-Yves David
deprecation: enforce thew 'tr' argument of 'dirstate.write' (API)...
r29673 if tr:
dirstate: factor the transaction abort logic...
r51150 self._setup_tr_abort(tr)
dirstate: track that changes are pending in a transaction...
r51017 self._attached_to_a_transaction = True
def on_success(f):
self._attached_to_a_transaction = False
self._writedirstate(tr, f),
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(
dirstate: distinct transaction callback from largefile...
r51018 b'dirstate-1-main%s' % self._tr_key_suffix,
Augie Fackler
formatting: blacken the codebase...
r43346 (self._filename,),
dirstate: track that changes are pending in a transaction...
r51017 on_success,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 location=b'plain',
transaction: do not rely on a global variable to post_finalize file...
r49534 post_finalize=True,
Augie Fackler
formatting: blacken the codebase...
r43346 )
dirstate: introduce a "tracked-key" feature...
r49533 if write_key:
tr.addfilegenerator(
dirstate: distinct transaction callback from largefile...
r51018 b'dirstate-2-key-post%s' % self._tr_key_suffix,
tracked-key: remove the dual write and rename to tracked-hint...
r49644 (self._filename_th,),
lambda f: self._write_tracked_hint(tr, f),
dirstate: introduce a "tracked-key" feature...
r49533 location=b'plain',
transaction: do not rely on a global variable to post_finalize file...
r49534 post_finalize=True,
dirstate: introduce a "tracked-key" feature...
r49533 )
FUJIWARA Katsunori
dirstate: make writing in-memory changes aware of transaction activity...
r26634 return
dirstate: use a context manager when writing the dirstate...
r49531 file = lambda f: self._opener(f, b"w", atomictemp=True, checkambig=True)
with file(self._filename) as f:
self._writedirstate(tr, f)
dirstate: introduce a "tracked-key" feature...
r49533 if write_key:
# we update the key-file after writing to make sure reader have a
# key that match the newly written content
tracked-key: remove the dual write and rename to tracked-hint...
r49644 with file(self._filename_th) as f:
self._write_tracked_hint(tr, f)
FUJIWARA Katsunori
dirstate: split write to write changes into files other than .hg/dirstate...
r26521
tracked-key: remove the dual write and rename to tracked-hint...
r49644 def delete_tracked_hint(self):
"""remove the tracked_hint file
tracked-key: make it possible to upgrade to and downgrade from the feature...
r49641
To be used by format downgrades operation"""
tracked-key: remove the dual write and rename to tracked-hint...
r49644 self._opener.unlink(self._filename_th)
self._use_tracked_hint = False
tracked-key: make it possible to upgrade to and downgrade from the feature...
r49641
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def addparentchangecallback(
self, category: bytes, callback: intdirstate.AddParentChangeCallbackT
) -> None:
Mateusz Kwapich
dirstate: add callback to notify extensions about wd parent change...
r29772 """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
dirstate: cleanup remaining of "now" during write...
r49222 def _writedirstate(self, tr, st):
dirstate: add small asserts for double security...
r51016 # make sure we don't write invalidated content
assert not self._invalidated_context
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
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for c, callback in sorted(self._plchangecallbacks.items()):
Mateusz Kwapich
dirstate: add callback to notify extensions about wd parent change...
r29772 callback(self, self._origpl, self._pl)
self._origpl = None
dirstate: cleanup remaining of "now" during write...
r49222 self._map.write(tr, st)
Durham Goode
dirstate: move write into dirstatemap...
r34674 self._dirty = False
dirstate: introduce a "tracked-key" feature...
r49533 self._dirty_tracked_set = False
tracked-key: remove the dual write and rename to tracked-hint...
r49644 def _write_tracked_hint(self, tr, f):
dirstate: introduce a "tracked-key" feature...
r49533 key = node.hex(uuid.uuid4().bytes)
f.write(b"1\n%s\n" % key) # 1 is the format version
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
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def _ignorefiles(self) -> List[bytes]:
Laurent Charignon
dirstate: extract logic to compute the list of ignorefiles...
r27594 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
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def _ignorefileandline(self, f: bytes) -> intdirstate.IgnoreFileAndLineT:
Laurent Charignon
dirstate: add a way to get the ignore file/line matching an ignored file...
r27670 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):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """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
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 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
Raphaël Gomès
black: format the codebase with 23.3.0...
r52596 except OSError as inst:
dirstate: rename _parentwriters to _changing_level...
r50916 # nf not found on disk - it is dirstate only
Augie Fackler
formatting: blacken the codebase...
r43346 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
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for f, st in results.items():
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
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for norm, paths in normed.items():
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
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def walk(
self,
match: matchmod.basematcher,
subrepos: Any,
unknown: bool,
ignored: bool,
full: bool = True,
) -> intdirstate.WalkReturnT:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
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
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
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
sparse: directly inline the `walk` wrapping...
r50251 if self._sparsematchfn is not None:
em = matchmod.exact(match.files())
sm = matchmod.unionmatcher([self._sparsematcher, em])
match = matchmod.intersectmatchers(match, sm)
Siddharth Agarwal
dirstate.walk: refactor explicit walk into separate function...
r19173 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)
Manuel Jacob
py3: catch specific OSError subclasses instead of checking errno...
r50205 except (PermissionError, FileNotFoundError) as inst:
match.bad(
self.pathto(nd), encoding.strtolocal(inst.strerror)
)
continue
Siddharth Agarwal
dirstate.walk: factor out directory traversal...
r24559 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
rust-status: use bare hg status fastpath from Python...
r45017 def _rust_status(self, matcher, list_clean, list_ignored, list_unknown):
sparse: use the rust code even when sparse is present...
r50256 if self._sparsematchfn is not None:
em = matchmod.exact(matcher.files())
sm = matchmod.unionmatcher([self._sparsematcher, em])
matcher = matchmod.intersectmatchers(matcher, sm)
Raphaël Gomès
dirstate: move rust fast-path calling code to its own method...
r44537 # 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,
Raphaël Gomès
rust-status: use bare hg status fastpath from Python...
r45017 clean,
ignored,
Raphaël Gomès
dirstate: move rust fast-path calling code to its own method...
r44537 unknown,
Raphaël Gomès
rust-status: use bare hg status fastpath from Python...
r45017 warnings,
bad,
Raphaël Gomès
status: also support for `traversedir` callback in the Rust fast-path...
r45355 traversed,
Simon Sapin
dirstate-v2: Write .hg/dirstate back to disk on directory cache changes...
r48139 dirty,
Raphaël Gomès
dirstate: move rust fast-path calling code to its own method...
r44537 ) = rustmod.status(
dirstatemap: rename `_rustmap` to `_map`...
r48933 self._map._map,
Raphaël Gomès
dirstate: move rust fast-path calling code to its own method...
r44537 matcher,
self._rootdir,
Raphaël Gomès
rust-status: use bare hg status fastpath from Python...
r45017 self._ignorefiles(),
self._checkexec,
bool(list_clean),
bool(list_ignored),
bool(list_unknown),
Raphaël Gomès
status: also support for `traversedir` callback in the Rust fast-path...
r45355 bool(matcher.traversedir),
Raphaël Gomès
dirstate: move rust fast-path calling code to its own method...
r44537 )
Raphaël Gomès
status: also support for `traversedir` callback in the Rust fast-path...
r45355
Simon Sapin
dirstate-v2: Write .hg/dirstate back to disk on directory cache changes...
r48139 self._dirty |= dirty
Raphaël Gomès
status: also support for `traversedir` callback in the Rust fast-path...
r45355 if matcher.traversedir:
for dir in traversed:
matcher.traversedir(dir)
Raphaël Gomès
rust-status: use bare hg status fastpath from Python...
r45017 if self._ui.warn:
for item in warnings:
if isinstance(item, tuple):
file_path, syntax = item
msg = _(b"%s: ignoring invalid syntax '%s'\n") % (
file_path,
syntax,
)
self._ui.warn(msg)
else:
msg = _(b"skipping unreadable pattern file '%s': %s\n")
self._ui.warn(
msg
% (
pathutil.canonpath(
self._rootdir, self._rootdir, item
),
b"No such file or directory",
)
)
Raphaël Gomès
rust-status: sort the failed matches when printing them...
r52522 for fn, message in sorted(bad):
Raphaël Gomès
rust-status: use bare hg status fastpath from Python...
r45017 matcher.bad(fn, encoding.strtolocal(message))
Raphaël Gomès
dirstate: move rust fast-path calling code to its own method...
r44537
status = scmutil.status(
modified=modified,
added=added,
removed=removed,
deleted=deleted,
unknown=unknown,
Raphaël Gomès
rust-status: use bare hg status fastpath from Python...
r45017 ignored=ignored,
Raphaël Gomès
dirstate: move rust fast-path calling code to its own method...
r44537 clean=clean,
)
return (lookup, status)
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def status(
self,
match: matchmod.basematcher,
subrepos: bool,
ignored: bool,
clean: bool,
unknown: bool,
) -> intdirstate.StatusReturnT:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """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
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
dirstate: enforce `running_status` context for calling `status`...
r51044 if not self._running_status:
msg = "Calling `status` outside a `running_status` context"
raise error.ProgrammingError(msg)
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
Raphaël Gomès
rust-dirstate-status: add call to rust-fast path for `dirstate.status`...
r43568 if rustmod is None:
use_rust = False
Raphaël Gomès
rust-status: use bare hg status fastpath from Python...
r45017 elif self._checkcase:
# Case-insensitive filesystems are not handled yet
use_rust = False
Raphaël Gomès
rust-dirstate-status: add call to rust-fast path for `dirstate.status`...
r43568 elif subrepos:
use_rust = False
status: use filesystem time boundary to invalidate racy mtime...
r49213 # Get the time from the filesystem so we can disambiguate files that
# appear modified in the present or future.
try:
mtime_boundary = timestamp.get_fs_now(self._opener)
except OSError:
# In largefiles or readonly context
mtime_boundary = None
Raphaël Gomès
rust-dirstate-status: add call to rust-fast path for `dirstate.status`...
r43568 if use_rust:
Raphaël Gomès
rust-status: use bare hg status fastpath from Python...
r45017 try:
status: use filesystem time boundary to invalidate racy mtime...
r49213 res = self._rust_status(
Raphaël Gomès
rust-status: use bare hg status fastpath from Python...
r45017 match, listclean, listignored, listunknown
)
status: use filesystem time boundary to invalidate racy mtime...
r49213 return res + (mtime_boundary,)
Raphaël Gomès
rust-status: use bare hg status fastpath from Python...
r45017 except rustmod.FallbackError:
pass
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
dirstate: make sure that status does not overlook the fallback flags...
r49112 checklink = self._checklink
Durham Goode
dirstate: move _copymap to dirstatemap...
r34337 copymap = self._map.copymap
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
dirstate: remove pycompat.iteritems()...
r49777 for fn, st in self.walk(
match, subrepos, listunknown, listignored, full=full
).items():
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
Durham Goode
dirstate: remove excess attribute lookups for dirstate.status (issue5714)...
r34936 t = dget(fn)
dirstate-entry: add a `mode` property...
r48325 mode = t.mode
dirstate-entry: add a `size` property...
r48326 size = t.size
Matt Mackall
dirstate: minor status cleanups
r6591
dirstate-entry: add a `tracked` property...
r48320 if not st and t.tracked:
Matt Mackall
dirstate.walk: eliminate src from yield...
r6818 dadd(fn)
dirstate-item: use the `p2_info` property to replace more verbose call...
r48960 elif t.p2_info:
dirstate: reorder "state" checking conditional...
r48322 madd(fn)
elif t.added:
aadd(fn)
elif t.removed:
radd(fn)
dirstate: drop last explicite `state` usage in status...
r48323 elif t.tracked:
dirstate: make sure that status does not overlook the fallback flags...
r49112 if not checklink and t.has_fallback_symlink:
# If the file system does not support symlink, the mode
# might not be correctly stored in the dirstate, so do not
# trust it.
ladd(fn)
elif not checkexec and t.has_fallback_exec:
# If the file system does not support exec bits, the mode
# might not be correctly stored in the dirstate, so do not
# trust it.
ladd(fn)
elif (
Augie Fackler
formatting: blacken the codebase...
r43346 size >= 0
and (
(size != st.st_size and size != st.st_size & _rangemask)
or ((mode ^ st.st_mode) & 0o100 and checkexec)
)
or fn in copymap
):
Raphaël Gomès
formatting: fix redundant parentheses...
r47530 if stat.S_ISLNK(st.st_mode) and size != st.st_size:
Corey Schuhen
enclink: check contents of symlinks not just size in case of fcrypt...
r47436 # issue6456: Size returned may be longer due to
# encryption on EXT-4 fscrypt, undecided.
ladd(fn)
else:
madd(fn)
Raphaël Gomès
merge: improve working-copy mtime race handling...
r52952 else:
reliable = None
if mtime_boundary is not None:
reliable = timestamp.reliable_mtime_of(
st, mtime_boundary
)
elif t.mtime_likely_equal_to(timestamp.mtime_of(st)):
# We can't compute the current fs time, so we're in
# a readonly fs or a LFS context.
cadd(fn)
continue
if reliable is None or not t.mtime_likely_equal_to(
reliable
):
# There might be a change in the future if for example
# the internal clock is off, but this is a case where
# the issues the user would face would be a lot worse
# and there is nothing we can really do.
ladd(fn)
elif listclean:
cadd(fn)
Raphaël Gomès
rust-status: use bare hg status fastpath from Python...
r45017 status = scmutil.status(
modified, added, removed, deleted, unknown, ignored, clean
Augie Fackler
formatting: blacken the codebase...
r43346 )
status: use filesystem time boundary to invalidate racy mtime...
r49213 return (lookup, status, mtime_boundary)
Siddharth Agarwal
dirstate: add a method to efficiently filter by match...
r21984
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def matches(self, match: matchmod.basematcher) -> Iterable[bytes]:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Siddharth Agarwal
dirstate: add a method to efficiently filter by match...
r21984 return files in the dirstate (in whatever state) filtered by match
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Siddharth Agarwal
dirstate: add a method to efficiently filter by match...
r21984 dmap = self._map
Raphaël Gomès
rust-dirstatemap: remove additional lookup in dirstate.matches...
r44833 if rustmod is not None:
dirstatemap: rename `_rustmap` to `_map`...
r48933 dmap = self._map._map
Raphaël Gomès
rust-dirstatemap: remove additional lookup in dirstate.matches...
r44833
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
localrepo: "blindly" do a dirstate backup at the end of the transaction...
r50979 def all_file_names(self):
"""list all filename currently used by this dirstate
FUJIWARA Katsunori
dirstate: make functions for backup aware of transaction activity...
r26633
localrepo: "blindly" do a dirstate backup at the end of the transaction...
r50979 This is only used to do `hg rollback` related backup in the transaction
"""
transaction: remove the `branch` backup for transaction...
r51162 files = [b'branch']
if self._opener.exists(self._filename):
files.append(self._filename)
if self._use_dirstate_v2:
files.append(self._map.docket.data_filename())
return tuple(files)
FUJIWARA Katsunori
dirstate: make functions for backup aware of transaction activity...
r26633
Matt Harbison
typing: add type annotations to the dirstate classes...
r52822 def verify(
self, m1, m2, p1: bytes, narrow_matcher: Optional[Any] = None
) -> Iterator[bytes]:
Raphaël Gomès
dirstate: update messages in verify to not use the old `state` API
r50718 """
check the dirstate contents against the parent manifest and yield errors
"""
missing_from_p1 = _(
Raphaël Gomès
verify: print short `p1` node in relevant dirstate messages...
r50722 b"%s marked as tracked in p1 (%s) but not in manifest1\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
Raphaël Gomès
dirstate: update messages in verify to not use the old `state` API
r50718 unexpected_in_p1 = _(b"%s marked as added, but also in manifest1\n")
missing_from_ps = _(
b"%s marked as modified, but not in either manifest\n"
)
missing_from_ds = _(
Raphaël Gomès
verify: print short `p1` node in relevant dirstate messages...
r50722 b"%s in manifest1, but not marked as tracked in p1 (%s)\n"
Raphaël Gomès
dirstate: update messages in verify to not use the old `state` API
r50718 )
dirstate: move verification code within the dirstate itself...
r48901 for f, entry in self.items():
Raphaël Gomès
dirstate: stop using `entry.state()` for logic in `verify`...
r50716 if entry.p1_tracked:
if entry.modified and f not in m1 and f not in m2:
Raphaël Gomès
verify: format messages directly at the source
r50719 yield missing_from_ps % f
Raphaël Gomès
dirstate: stop using `entry.state()` for logic in `verify`...
r50716 elif f not in m1:
Raphaël Gomès
verify: print short `p1` node in relevant dirstate messages...
r50722 yield missing_from_p1 % (f, node.short(p1))
Raphaël Gomès
dirstate: stop using `entry.state()` for logic in `verify`...
r50716 if entry.added and f in m1:
Raphaël Gomès
verify: format messages directly at the source
r50719 yield unexpected_in_p1 % f
dirstate: move verification code within the dirstate itself...
r48901 for f in m1:
Raphaël Gomès
dirstate: add narrow support to `verify`...
r50717 if narrow_matcher is not None and not narrow_matcher(f):
continue
Raphaël Gomès
dirstate: stop using `entry.state()` for logic in `verify`...
r50716 entry = self.get_entry(f)
if not entry.p1_tracked:
Raphaël Gomès
verify: print short `p1` node in relevant dirstate messages...
r50722 yield missing_from_ds % (f, node.short(p1))