diff --git a/hgext/narrow/narrowmerge.py b/hgext/narrow/narrowmerge.py --- a/hgext/narrow/narrowmerge.py +++ b/hgext/narrow/narrowmerge.py @@ -7,48 +7,13 @@ from __future__ import absolute_import -from mercurial.i18n import _ from mercurial import ( copies, - error, extensions, merge, ) def setup(): - def _manifestmerge(orig, repo, wctx, p2, pa, branchmerge, *args, **kwargs): - """Filter updates to only lay out files that match the narrow spec.""" - actions, diverge, renamedelete = orig( - repo, wctx, p2, pa, branchmerge, *args, **kwargs) - - narrowmatch = repo.narrowmatch() - if narrowmatch.always(): - return actions, diverge, renamedelete - - nooptypes = set(['k']) # TODO: handle with nonconflicttypes - nonconflicttypes = set('a am c cm f g r e'.split()) - # We mutate the items in the dict during iteration, so iterate - # over a copy. - for f, action in list(actions.items()): - if narrowmatch(f): - pass - elif not branchmerge: - del actions[f] # just updating, ignore changes outside clone - elif action[0] in nooptypes: - del actions[f] # merge does not affect file - elif action[0] in nonconflicttypes: - raise error.Abort(_('merge affects file \'%s\' outside narrow, ' - 'which is not yet supported') % f, - hint=_('merging in the other direction ' - 'may work')) - else: - raise error.Abort(_('conflict in file \'%s\' is outside ' - 'narrow clone') % f) - - return actions, diverge, renamedelete - - extensions.wrapfunction(merge, 'manifestmerge', _manifestmerge) - def _checkcollision(orig, repo, wmf, actions): narrowmatch = repo.narrowmatch() if not narrowmatch.always(): diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -1072,6 +1072,33 @@ repo.ui.warn(_("%s: is both a file and a directory\n") % p) raise error.Abort(_("destination manifest contains path conflicts")) +def _filternarrowactions(narrowmatch, branchmerge, actions): + """ + Filters out actions that can ignored because the repo is narrowed. + + Raise an exception if the merge cannot be completed because the repo is + narrowed. + """ + nooptypes = set(['k']) # TODO: handle with nonconflicttypes + nonconflicttypes = set('a am c cm f g r e'.split()) + # We mutate the items in the dict during iteration, so iterate + # over a copy. + for f, action in list(actions.items()): + if narrowmatch(f): + pass + elif not branchmerge: + del actions[f] # just updating, ignore changes outside clone + elif action[0] in nooptypes: + del actions[f] # merge does not affect file + elif action[0] in nonconflicttypes: + raise error.Abort(_('merge affects file \'%s\' outside narrow, ' + 'which is not yet supported') % f, + hint=_('merging in the other direction ' + 'may work')) + else: + raise error.Abort(_('conflict in file \'%s\' is outside ' + 'narrow clone') % f) + def manifestmerge(repo, wctx, p2, pa, branchmerge, force, matcher, acceptremote, followcopies, forcefulldiff=False): """ @@ -1256,6 +1283,11 @@ # If we are merging, look for path conflicts. checkpathconflicts(repo, wctx, p2, actions) + narrowmatch = repo.narrowmatch() + if not narrowmatch.always(): + # Updates "actions" in place + _filternarrowactions(narrowmatch, branchmerge, actions) + return actions, diverge, renamedelete def _resolvetrivial(repo, wctx, mctx, ancestor, actions):