[PATCH 08 of 10 sparse V2] sparse: move working directory refreshing into core
Gregory Szorc
gregory.szorc at gmail.com
Thu Jul 6 23:36:24 UTC 2017
# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1499377988 25200
# Thu Jul 06 14:53:08 2017 -0700
# Node ID 58a6344171e1ac0632885017b9de6ce11eb522f9
# Parent 62b386782cce6101da26d7a62dc0decf6a77cb83
sparse: move working directory refreshing into core
This is a pretty straightforward move of the code.
I converted the "force" argument to a keyword argument.
Like other recent changes, this code is tightly coupled with
working directory update code in merge.py. I suspect the code
will become more tightly coupled over time, possibly even moved
to merge.py. For now, let's get the code in core.
diff --git a/hgext/sparse.py b/hgext/sparse.py
--- a/hgext/sparse.py
+++ b/hgext/sparse.py
@@ -85,7 +85,6 @@ from mercurial import (
extensions,
hg,
localrepo,
- merge as mergemod,
registrar,
sparse,
util,
@@ -156,7 +155,7 @@ def _setupcommit(ui):
if set(profiles) & set(ctx.files()):
origstatus = repo.status()
origsparsematch = sparse.matcher(repo)
- _refresh(repo.ui, repo, origstatus, origsparsematch, True)
+ sparse.refreshwdir(repo, origstatus, origsparsematch, force=True)
sparse.prunetemporaryincludes(repo)
@@ -405,7 +404,8 @@ def debugsparse(ui, repo, *pats, **opts)
wlock = repo.wlock()
fcounts = map(
len,
- _refresh(ui, repo, repo.status(), sparse.matcher(repo), force))
+ sparse.refreshwdir(repo, repo.status(), sparse.matcher(repo),
+ force=force))
_verbose_output(ui, opts, 0, 0, 0, *fcounts)
finally:
wlock.release()
@@ -459,7 +459,9 @@ def _config(ui, repo, pats, opts, includ
sparse.writeconfig(repo, newinclude, newexclude, newprofiles)
fcounts = map(
- len, _refresh(ui, repo, oldstatus, oldsparsematch, force))
+ len,
+ sparse.refreshwdir(repo, oldstatus, oldsparsematch,
+ force=force))
profilecount = (len(newprofiles - oldprofiles) -
len(oldprofiles - newprofiles))
@@ -523,7 +525,9 @@ def _import(ui, repo, files, opts, force
try:
fcounts = map(
- len, _refresh(ui, repo, oldstatus, oldsparsematch, force))
+ len,
+ sparse.refreshwdir(repo, oldstatus, oldsparsematch,
+ force=force))
except Exception:
sparse.writeconfig(repo, oincludes, oexcludes, oprofiles)
raise
@@ -540,101 +544,7 @@ def _clear(ui, repo, files, force=False)
oldstatus = repo.status()
oldsparsematch = sparse.matcher(repo)
sparse.writeconfig(repo, set(), set(), profiles)
- _refresh(ui, repo, oldstatus, oldsparsematch, force)
-
-def _refresh(ui, repo, origstatus, origsparsematch, force):
- """Refreshes which files are on disk by comparing the old status and
- sparsematch with the new sparsematch.
-
- Will raise an exception if a file with pending changes is being excluded
- or included (unless force=True).
- """
- modified, added, removed, deleted, unknown, ignored, clean = origstatus
-
- # Verify there are no pending changes
- pending = set()
- pending.update(modified)
- pending.update(added)
- pending.update(removed)
- sparsematch = sparse.matcher(repo)
- abort = False
- for file in pending:
- if not sparsematch(file):
- ui.warn(_("pending changes to '%s'\n") % file)
- abort = not force
- if abort:
- raise error.Abort(_("could not update sparseness due to " +
- "pending changes"))
-
- # Calculate actions
- dirstate = repo.dirstate
- ctx = repo['.']
- added = []
- lookup = []
- dropped = []
- mf = ctx.manifest()
- files = set(mf)
-
- actions = {}
-
- for file in files:
- old = origsparsematch(file)
- new = sparsematch(file)
- # Add files that are newly included, or that don't exist in
- # the dirstate yet.
- if (new and not old) or (old and new and not file in dirstate):
- fl = mf.flags(file)
- if repo.wvfs.exists(file):
- actions[file] = ('e', (fl,), '')
- lookup.append(file)
- else:
- actions[file] = ('g', (fl, False), '')
- added.append(file)
- # Drop files that are newly excluded, or that still exist in
- # the dirstate.
- elif (old and not new) or (not old and not new and file in dirstate):
- dropped.append(file)
- if file not in pending:
- actions[file] = ('r', [], '')
-
- # Verify there are no pending changes in newly included files
- abort = False
- for file in lookup:
- ui.warn(_("pending changes to '%s'\n") % file)
- abort = not force
- if abort:
- raise error.Abort(_("cannot change sparseness due to " +
- "pending changes (delete the files or use --force " +
- "to bring them back dirty)"))
-
- # Check for files that were only in the dirstate.
- for file, state in dirstate.iteritems():
- if not file in files:
- old = origsparsematch(file)
- new = sparsematch(file)
- if old and not new:
- dropped.append(file)
-
- # Apply changes to disk
- typeactions = dict((m, []) for m in 'a f g am cd dc r dm dg m e k'.split())
- for f, (m, args, msg) in actions.iteritems():
- if m not in typeactions:
- typeactions[m] = []
- typeactions[m].append((f, args, msg))
- mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], False)
-
- # Fix dirstate
- for file in added:
- dirstate.normal(file)
-
- for file in dropped:
- dirstate.drop(file)
-
- for file in lookup:
- # File exists on disk, and we're bringing it back in an unknown state.
- dirstate.normallookup(file)
-
- return added, dropped, lookup
+ sparse.refreshwdir(repo, oldstatus, oldsparsematch, force)
def _verbose_output(ui, opts, profilecount, includecount, excludecount, added,
dropped, lookup):
diff --git a/mercurial/sparse.py b/mercurial/sparse.py
--- a/mercurial/sparse.py
+++ b/mercurial/sparse.py
@@ -463,3 +463,102 @@ def filterupdatesactions(repo, wctx, mct
prunedactions[file] = ('r', [], '')
return prunedactions
+
+def refreshwdir(repo, origstatus, origsparsematch, force=False):
+ """Refreshes working directory by taking sparse config into account.
+
+ The old status and sparse matcher is compared against the current sparse
+ matcher.
+
+ Will abort if a file with pending changes is being excluded or included
+ unless ``force`` is True.
+ """
+ modified, added, removed, deleted, unknown, ignored, clean = origstatus
+
+ # Verify there are no pending changes
+ pending = set()
+ pending.update(modified)
+ pending.update(added)
+ pending.update(removed)
+ sparsematch = matcher(repo)
+ abort = False
+
+ for f in pending:
+ if not sparsematch(f):
+ repo.ui.warn(_("pending changes to '%s'\n") % f)
+ abort = not force
+
+ if abort:
+ raise error.Abort(_('could not update sparseness due to pending '
+ 'changes'))
+
+ # Calculate actions
+ dirstate = repo.dirstate
+ ctx = repo['.']
+ added = []
+ lookup = []
+ dropped = []
+ mf = ctx.manifest()
+ files = set(mf)
+
+ actions = {}
+
+ for file in files:
+ old = origsparsematch(file)
+ new = sparsematch(file)
+ # Add files that are newly included, or that don't exist in
+ # the dirstate yet.
+ if (new and not old) or (old and new and not file in dirstate):
+ fl = mf.flags(file)
+ if repo.wvfs.exists(file):
+ actions[file] = ('e', (fl,), '')
+ lookup.append(file)
+ else:
+ actions[file] = ('g', (fl, False), '')
+ added.append(file)
+ # Drop files that are newly excluded, or that still exist in
+ # the dirstate.
+ elif (old and not new) or (not old and not new and file in dirstate):
+ dropped.append(file)
+ if file not in pending:
+ actions[file] = ('r', [], '')
+
+ # Verify there are no pending changes in newly included files
+ abort = False
+ for file in lookup:
+ repo.ui.warn(_("pending changes to '%s'\n") % file)
+ abort = not force
+ if abort:
+ raise error.Abort(_('cannot change sparseness due to pending '
+ 'changes (delete the files or use '
+ '--force to bring them back dirty)'))
+
+ # Check for files that were only in the dirstate.
+ for file, state in dirstate.iteritems():
+ if not file in files:
+ old = origsparsematch(file)
+ new = sparsematch(file)
+ if old and not new:
+ dropped.append(file)
+
+ # Apply changes to disk
+ typeactions = dict((m, []) for m in 'a f g am cd dc r dm dg m e k'.split())
+ for f, (m, args, msg) in actions.iteritems():
+ if m not in typeactions:
+ typeactions[m] = []
+ typeactions[m].append((f, args, msg))
+
+ mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], False)
+
+ # Fix dirstate
+ for file in added:
+ dirstate.normal(file)
+
+ for file in dropped:
+ dirstate.drop(file)
+
+ for file in lookup:
+ # File exists on disk, and we're bringing it back in an unknown state.
+ dirstate.normallookup(file)
+
+ return added, dropped, lookup
diff --git a/tests/test-sparse-import.t b/tests/test-sparse-import.t
--- a/tests/test-sparse-import.t
+++ b/tests/test-sparse-import.t
@@ -147,16 +147,11 @@ Same tests, with -Tjson enabled to outpu
If importing results in no new rules being added, no refresh should take place!
$ cat > $TESTTMP/trap_sparse_refresh.py <<EOF
- > from mercurial import error, extensions
+ > from mercurial import error, sparse
> def extsetup(ui):
- > def abort_refresh(ui, *args):
+ > def abort_refresh(*args, **kwargs):
> raise error.Abort('sparse._refresh called!')
- > def sparseloaded(loaded):
- > if not loaded:
- > return
- > sparse = extensions.find('sparse')
- > sparse._refresh = abort_refresh
- > extensions.afterloaded('sparse', sparseloaded)
+ > sparse.refreshwdir = abort_refresh
> EOF
$ cat >> $HGRCPATH <<EOF
> [extensions]
More information about the Mercurial-devel
mailing list