Patchwork D6836: interfaces: introduce an interface for dirstate implementations

login
register
mail settings
Submitter phabricator
Date Sept. 14, 2019, 3:34 p.m.
Message ID <2d799c14cff54967f32f4584ee11d727@localhost.localdomain>
Download mbox | patch
Permalink /patch/41666/
State Not Applicable
Headers show

Comments

phabricator - Sept. 14, 2019, 3:34 p.m.
Closed by commit rHGd459cd8ea42d: interfaces: introduce an interface for dirstate implementations (authored by durin42).
This revision was automatically updated to reflect the committed changes.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6836?vs=16504&id=16537

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6836/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6836

AFFECTED FILES
  mercurial/dirstate.py
  mercurial/interfaces/dirstate.py
  tests/test-check-interfaces.py

CHANGE DETAILS




To: durin42, #hg-reviewers, indygreg, pulkit
Cc: Alphare, mercurial-devel

Patch

diff --git a/tests/test-check-interfaces.py b/tests/test-check-interfaces.py
--- a/tests/test-check-interfaces.py
+++ b/tests/test-check-interfaces.py
@@ -15,6 +15,7 @@ 
     sys.exit(80)
 
 from mercurial.interfaces import (
+    dirstate as intdirstate,
     repository,
 )
 from mercurial.thirdparty.zope import (
@@ -25,6 +26,7 @@ 
 )
 from mercurial import (
     bundlerepo,
+    dirstate,
     filelog,
     httppeer,
     localrepo,
@@ -189,6 +191,8 @@ 
     ziverify.verifyClass(repository.iverifyproblem,
                          simplestorerepo.simplefilestoreproblem)
 
+    ziverify.verifyClass(intdirstate.idirstate, dirstate.dirstate)
+
     vfs = vfsmod.vfs(b'.')
     fl = filelog.filelog(vfs, b'dummy.i')
     checkzobject(fl, allowextra=True)
diff --git a/mercurial/interfaces/dirstate.py b/mercurial/interfaces/dirstate.py
new file mode 100644
--- /dev/null
+++ b/mercurial/interfaces/dirstate.py
@@ -0,0 +1,257 @@ 
+from __future__ import absolute_import, print_function
+
+import contextlib
+
+from .. import (
+    node as nodemod,
+)
+
+from . import (
+    util as interfaceutil,
+)
+
+class idirstate(interfaceutil.Interface):
+
+    def __init__(opener, ui, root, validate, sparsematchfn):
+        '''Create a new dirstate object.
+
+        opener is an open()-like callable that can be used to open the
+        dirstate file; root is the root of the directory tracked by
+        the dirstate.
+        '''
+
+    @contextlib.contextmanager
+    def parentchange():
+        '''Context manager for handling dirstate parents.
+
+        If an exception occurs in the scope of the context manager,
+        the incoherent dirstate won't be written when wlock is
+        released.
+        '''
+
+    def pendingparentchange():
+        '''Returns true if the dirstate is in the middle of a set of changes
+        that modify the dirstate parent.
+        '''
+
+    _map = interfaceutil.Attribute(
+        """Return the dirstate contents (see documentation for dirstatemap).
+
+        TODO this should not be exposed.
+        """
+        )
+
+    def hasdir(d):
+        pass
+
+    _ignore = interfaceutil.Attribute('Matcher for ignored files.')
+
+    _checklink = interfaceutil.Attribute('Callable for checking symlinks.')
+    _checkexec = interfaceutil.Attribute('Callable for checking exec bits.')
+
+    def flagfunc(buildfallback):
+        pass
+
+    def getcwd():
+        '''Return the path from which a canonical path is calculated.
+
+        This path should be used to resolve file patterns or to convert
+        canonical paths back to file paths for display. It shouldn't be
+        used to get real file paths. Use vfs functions instead.
+        '''
+
+    def pathto(f, cwd=None):
+        pass
+
+    def __getitem__(key):
+        '''Return the current state of key (a filename) in the dirstate.
+
+        States are:
+          n  normal
+          m  needs merging
+          r  marked for removal
+          a  marked for addition
+          ?  not tracked
+        '''
+
+    def __contains__(key):
+        """Check if bytestring `key` is known to the dirstate."""
+
+    def __iter__():
+        """Iterate the dirstate's contained filenames as bytestrings."""
+
+    def items():
+        """Iterate the dirstate's entries as (filename, dirstatetuple).
+
+        As usual, filename is a bytestring.
+        """
+
+    iteritems = items
+
+    def parents():
+        pass
+
+    def p1():
+        pass
+
+    def p2():
+        pass
+
+    def branch():
+        pass
+
+    def setparents(p1, p2=nodemod.nullid):
+        """Set dirstate parents to p1 and p2.
+
+        When moving from two parents to one, 'm' merged entries a
+        adjusted to normal and previous copy records discarded and
+        returned by the call.
+
+        See localrepo.setparents()
+        """
+
+    def setbranch(branch):
+        pass
+
+    def invalidate():
+        '''Causes the next access to reread the dirstate.
+
+        This is different from localrepo.invalidatedirstate() because it always
+        rereads the dirstate. Use localrepo.invalidatedirstate() if you want to
+        check whether the dirstate has changed before rereading it.'''
+
+    def copy(source, dest):
+        """Mark dest as a copy of source. Unmark dest if source is None."""
+
+    def copied(file):
+        pass
+
+    def copies():
+        pass
+
+    def normal(f, parentfiledata=None):
+        '''Mark a file normal and clean.
+
+        parentfiledata: (mode, size, mtime) of the clean file
+
+        parentfiledata should be computed from memory (for mode,
+        size), as or close as possible from the point where we
+        determined the file was clean, to limit the risk of the
+        file having been changed by an external process between the
+        moment where the file was determined to be clean and now.'''
+        pass
+
+    def normallookup(f):
+        '''Mark a file normal, but possibly dirty.'''
+
+    def otherparent(f):
+        '''Mark as coming from the other parent, always dirty.'''
+
+    def add(f):
+        '''Mark a file added.'''
+
+    def remove(f):
+        '''Mark a file removed.'''
+
+    def merge(f):
+        '''Mark a file merged.'''
+
+    def drop(f):
+        '''Drop a file from the dirstate'''
+
+    def normalize(path, isknown=False, ignoremissing=False):
+        '''
+        normalize the case of a pathname when on a casefolding filesystem
+
+        isknown specifies whether the filename came from walking the
+        disk, to avoid extra filesystem access.
+
+        If ignoremissing is True, missing path are returned
+        unchanged. Otherwise, we try harder to normalize possibly
+        existing path components.
+
+        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
+        '''
+
+    def clear():
+        pass
+
+    def rebuild(parent, allfiles, changedfiles=None):
+        pass
+
+    def identity():
+        '''Return identity of dirstate it to detect changing in storage
+
+        If identity of previous dirstate is equal to this, writing
+        changes based on the former dirstate out can keep consistency.
+        '''
+
+    def write(tr):
+        pass
+
+    def addparentchangecallback(category, callback):
+        """add a callback to be called when the wd parents are changed
+
+        Callback will be called with the following arguments:
+            dirstate, (oldp1, oldp2), (newp1, newp2)
+
+        Category is a unique identifier to allow overwriting an old callback
+        with a newer callback.
+        """
+
+    def _ignorefiles():
+        """Return a list of files containing patterns to ignore.
+
+        TODO this should not be exposed."""
+
+    def _ignorefileandline(f):
+        """Given a file `f`, return the ignore file and line that ignores it.
+
+        TODO this should not be exposed."""
+
+    def walk(match, subrepos, unknown, ignored, full=True):
+        '''
+        Walk recursively through the directory tree, finding all files
+        matched by match.
+
+        If full is False, maybe skip some known-clean files.
+
+        Return a dict mapping filename to stat-like object (either
+        mercurial.osutil.stat instance or return value of os.stat()).
+
+        '''
+
+    def status(match, subrepos, ignored, clean, unknown):
+        '''Determine the status of the working copy relative to the
+        dirstate and return a pair of (unsure, status), where status is of type
+        scmutil.status and:
+
+          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)
+          status.modified:
+            files that have definitely been modified since the dirstate
+            was written (different size or mode)
+          status.clean:
+            files that have definitely not been modified since the
+            dirstate was written
+        '''
+
+    def matches(match):
+        '''
+        return files in the dirstate (in whatever state) filtered by match
+        '''
+
+    def savebackup(tr, backupname):
+        '''Save current dirstate into backup file'''
+
+    def restorebackup(tr, backupname):
+        '''Restore dirstate by backup file'''
+
+    def clearbackup(tr, backupname):
+        '''Clear backup file'''
diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -27,6 +27,11 @@ 
     util,
 )
 
+from .interfaces import (
+    dirstate as intdirstate,
+    util as interfaceutil,
+)
+
 parsers = policy.importmod(r'parsers')
 rustmod = policy.importrust(r'dirstate')
 
@@ -55,6 +60,7 @@ 
         os.close(tmpfd)
         vfs.unlink(tmpname)
 
+@interfaceutil.implementer(intdirstate.idirstate)
 class dirstate(object):
 
     def __init__(self, opener, ui, root, validate, sparsematchfn):