[PATCH 8 of 9 sparse] sparse: move update action filtering into core
Gregory Szorc
gregory.szorc at gmail.com
Thu Jul 6 21:54:24 UTC 2017
# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1499376320 25200
# Thu Jul 06 14:25:20 2017 -0700
# Node ID 61066164673a2d4213bbfedc2081377b18f2d47c
# Parent fa3cd4d3ec8273b09e684c71aa716a85dcbe9f20
sparse: move update action filtering into core
Sparse applies a filter on calculated update actions. This patch
moves the function to sparse.py and inlines the call in
merge.update() so we don't need to wrap the function.
If sparse isn't enabled, the function no-ops.
We should probably take sparse into account earlier in update().
This change preserves the existing functionality. It can be
iterated on later.
diff --git a/hgext/sparse.py b/hgext/sparse.py
--- a/hgext/sparse.py
+++ b/hgext/sparse.py
@@ -74,8 +74,6 @@ certain files::
from __future__ import absolute_import
-import collections
-
from mercurial.i18n import _
from mercurial.node import nullid
from mercurial import (
@@ -103,7 +101,6 @@ cmdtable = {}
command = registrar.command(cmdtable)
def uisetup(ui):
- _setupupdates(ui)
_setupcommit(ui)
def extsetup(ui):
@@ -145,93 +142,6 @@ def replacefilecache(cls, propname, repl
raise AttributeError(_("type '%s' has no property '%s'") % (origcls,
propname))
-def _setupupdates(ui):
- def _calculateupdates(orig, repo, wctx, mctx, ancestors, branchmerge, *arg,
- **kwargs):
- """Filter updates to only lay out files that match the sparse rules.
- """
- actions, diverge, renamedelete = orig(repo, wctx, mctx, ancestors,
- branchmerge, *arg, **kwargs)
-
- oldrevs = [pctx.rev() for pctx in wctx.parents()]
- oldsparsematch = sparse.matcher(repo, oldrevs)
-
- if oldsparsematch.always():
- return actions, diverge, renamedelete
-
- files = set()
- prunedactions = {}
-
- if branchmerge:
- # If we're merging, use the wctx filter, since we're merging into
- # the wctx.
- sparsematch = sparse.matcher(repo, [wctx.parents()[0].rev()])
- else:
- # If we're updating, use the target context's filter, since we're
- # moving to the target context.
- sparsematch = sparse.matcher(repo, [mctx.rev()])
-
- temporaryfiles = []
- for file, action in actions.iteritems():
- type, args, msg = action
- files.add(file)
- if sparsematch(file):
- prunedactions[file] = action
- elif type == 'm':
- temporaryfiles.append(file)
- prunedactions[file] = action
- elif branchmerge:
- if type != 'k':
- temporaryfiles.append(file)
- prunedactions[file] = action
- elif type == 'f':
- prunedactions[file] = action
- elif file in wctx:
- prunedactions[file] = ('r', args, msg)
-
- if len(temporaryfiles) > 0:
- ui.status(_("temporarily included %d file(s) in the sparse checkout"
- " for merging\n") % len(temporaryfiles))
- sparse.addtemporaryincludes(repo, temporaryfiles)
-
- # Add the new files to the working copy so they can be merged, etc
- actions = []
- message = 'temporarily adding to sparse checkout'
- wctxmanifest = repo[None].manifest()
- for file in temporaryfiles:
- if file in wctxmanifest:
- fctx = repo[None][file]
- actions.append((file, (fctx.flags(), False), message))
-
- typeactions = collections.defaultdict(list)
- typeactions['g'] = actions
- mergemod.applyupdates(repo, typeactions, repo[None], repo['.'],
- False)
-
- dirstate = repo.dirstate
- for file, flags, msg in actions:
- dirstate.normal(file)
-
- profiles = sparse.activeprofiles(repo)
- changedprofiles = profiles & files
- # If an active profile changed during the update, refresh the checkout.
- # Don't do this during a branch merge, since all incoming changes should
- # have been handled by the temporary includes above.
- if changedprofiles and not branchmerge:
- mf = mctx.manifest()
- for file in mf:
- old = oldsparsematch(file)
- new = sparsematch(file)
- if not old and new:
- flags = mf.flags(file)
- prunedactions[file] = ('g', (flags, False), '')
- elif old and not new:
- prunedactions[file] = ('r', [], '')
-
- return prunedactions, diverge, renamedelete
-
- extensions.wrapfunction(mergemod, 'calculateupdates', _calculateupdates)
-
def _setupcommit(ui):
def _refreshoncommit(orig, self, node):
"""Refresh the checkout when commits touch .hgsparse
diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -977,6 +977,9 @@ def calculateupdates(repo, wctx, mctx, a
acceptremote, followcopies, matcher=None,
mergeforce=False):
"Calculate the actions needed to merge mctx into wctx using ancestors"
+ # Avoid cycle.
+ from . import sparse
+
if len(ancestors) == 1: # default
actions, diverge, renamedelete = manifestmerge(
repo, wctx, mctx, ancestors[0], branchmerge, force, matcher,
@@ -1075,7 +1078,8 @@ def calculateupdates(repo, wctx, mctx, a
fractions = _forgetremoved(wctx, mctx, branchmerge)
actions.update(fractions)
- return actions, diverge, renamedelete
+ return sparse.calculateupdates(repo, wctx, mctx, branchmerge, actions,
+ diverge, renamedelete)
def batchremove(repo, wctx, actions):
"""apply removes to the working directory
diff --git a/mercurial/sparse.py b/mercurial/sparse.py
--- a/mercurial/sparse.py
+++ b/mercurial/sparse.py
@@ -371,3 +371,85 @@ def matcher(repo, revs=None, includetemp
repo._sparsematchercache[key] = result
return result
+
+def calculateupdates(repo, wctx, mctx, branchmerge, actions, diverge,
+ renamedelete):
+ """Filter updates to only lay out files that match sparse rules."""
+ if not enabled:
+ return actions, diverge, renamedelete
+
+ oldrevs = [pctx.rev() for pctx in wctx.parents()]
+ oldsparsematch = matcher(repo, oldrevs)
+
+ if oldsparsematch.always():
+ return actions, diverge, renamedelete
+
+ files = set()
+ prunedactions = {}
+
+ if branchmerge:
+ # If we're merging, use the wctx filter, since we're merging into
+ # the wctx.
+ sparsematch = matcher(repo, [wctx.parents()[0].rev()])
+ else:
+ # If we're updating, use the target context's filter, since we're
+ # moving to the target context.
+ sparsematch = matcher(repo, [mctx.rev()])
+
+ temporaryfiles = []
+ for file, action in actions.iteritems():
+ type, args, msg = action
+ files.add(file)
+ if sparsematch(file):
+ prunedactions[file] = action
+ elif type == 'm':
+ temporaryfiles.append(file)
+ prunedactions[file] = action
+ elif branchmerge:
+ if type != 'k':
+ temporaryfiles.append(file)
+ prunedactions[file] = action
+ elif type == 'f':
+ prunedactions[file] = action
+ elif file in wctx:
+ prunedactions[file] = ('r', args, msg)
+
+ if len(temporaryfiles) > 0:
+ repo.ui.status(_('temporarily included %d file(s) in the sparse '
+ 'checkout for merging\n') % len(temporaryfiles))
+ addtemporaryincludes(repo, temporaryfiles)
+
+ # Add the new files to the working copy so they can be merged, etc
+ actions = []
+ message = _('temporarily adding to sparse checkout')
+ wctxmanifest = repo[None].manifest()
+ for file in temporaryfiles:
+ if file in wctxmanifest:
+ fctx = repo[None][file]
+ actions.append((file, (fctx.flags(), False), message))
+
+ typeactions = collections.defaultdict(list)
+ typeactions['g'] = actions
+ mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], False)
+
+ dirstate = repo.dirstate
+ for file, flags, msg in actions:
+ dirstate.normal(file)
+
+ profiles = activeprofiles(repo)
+ changedprofiles = profiles & files
+ # If an active profile changed during the update, refresh the checkout.
+ # Don't do this during a branch merge, since all incoming changes should
+ # have been handled by the temporary includes above.
+ if changedprofiles and not branchmerge:
+ mf = mctx.manifest()
+ for file in mf:
+ old = oldsparsematch(file)
+ new = sparsematch(file)
+ if not old and new:
+ flags = mf.flags(file)
+ prunedactions[file] = ('g', (flags, False), '')
+ elif old and not new:
+ prunedactions[file] = ('r', [], '')
+
+ return prunedactions, diverge, renamedelete
More information about the Mercurial-devel
mailing list