narrowcommands.py
471 lines
| 19.1 KiB
| text/x-python
|
PythonLexer
Augie Fackler
|
r36096 | # narrowcommands.py - command modifications for narrowhg extension | ||
# | ||||
# Copyright 2017 Google, Inc. | ||||
# | ||||
# This software may be used and distributed according to the terms of the | ||||
# GNU General Public License version 2 or any later version. | ||||
from __future__ import absolute_import | ||||
import itertools | ||||
Pulkit Goyal
|
r39283 | import os | ||
Augie Fackler
|
r36096 | |||
from mercurial.i18n import _ | ||||
from mercurial import ( | ||||
Pulkit Goyal
|
r40106 | bundle2, | ||
Augie Fackler
|
r36096 | cmdutil, | ||
commands, | ||||
discovery, | ||||
Pulkit Goyal
|
r39471 | encoding, | ||
Augie Fackler
|
r36096 | error, | ||
exchange, | ||||
extensions, | ||||
hg, | ||||
merge, | ||||
Gregory Szorc
|
r36178 | narrowspec, | ||
Augie Fackler
|
r36096 | node, | ||
Augie Fackler
|
r36172 | pycompat, | ||
Augie Fackler
|
r36096 | registrar, | ||
repair, | ||||
Martin von Zweigbergk
|
r38871 | repository, | ||
Augie Fackler
|
r36096 | repoview, | ||
Pulkit Goyal
|
r39283 | sparse, | ||
Augie Fackler
|
r36096 | util, | ||
Pulkit Goyal
|
r40110 | wireprototypes, | ||
Augie Fackler
|
r36096 | ) | ||
table = {} | ||||
command = registrar.command(table) | ||||
def setup(): | ||||
"""Wraps user-facing mercurial commands with narrow-aware versions.""" | ||||
entry = extensions.wrapcommand(commands.table, 'clone', clonenarrowcmd) | ||||
entry[1].append(('', 'narrow', None, | ||||
_("create a narrow clone of select files"))) | ||||
entry[1].append(('', 'depth', '', | ||||
_("limit the history fetched by distance from heads"))) | ||||
Pulkit Goyal
|
r39283 | entry[1].append(('', 'narrowspec', '', | ||
_("read narrowspecs from file"))) | ||||
Augie Fackler
|
r36096 | # TODO(durin42): unify sparse/narrow --include/--exclude logic a bit | ||
if 'sparse' not in extensions.enabled(): | ||||
entry[1].append(('', 'include', [], | ||||
_("specifically fetch this file/directory"))) | ||||
entry[1].append( | ||||
('', 'exclude', [], | ||||
_("do not fetch this file/directory, even if included"))) | ||||
entry = extensions.wrapcommand(commands.table, 'pull', pullnarrowcmd) | ||||
entry[1].append(('', 'depth', '', | ||||
_("limit the history fetched by distance from heads"))) | ||||
extensions.wrapcommand(commands.table, 'archive', archivenarrowcmd) | ||||
def clonenarrowcmd(orig, ui, repo, *args, **opts): | ||||
"""Wraps clone command, so 'hg clone' first wraps localrepo.clone().""" | ||||
Augie Fackler
|
r36172 | opts = pycompat.byteskwargs(opts) | ||
Augie Fackler
|
r36096 | wrappedextraprepare = util.nullcontextmanager() | ||
Pulkit Goyal
|
r39283 | narrowspecfile = opts['narrowspec'] | ||
if narrowspecfile: | ||||
Matt Harbison
|
r39843 | filepath = os.path.join(encoding.getcwd(), narrowspecfile) | ||
Pulkit Goyal
|
r39283 | ui.status(_("reading narrowspec from '%s'\n") % filepath) | ||
try: | ||||
Pulkit Goyal
|
r39501 | fdata = util.readfile(filepath) | ||
except IOError as inst: | ||||
raise error.Abort(_("cannot read narrowspecs from '%s': %s") % | ||||
(filepath, encoding.strtolocal(inst.strerror))) | ||||
Pulkit Goyal
|
r39283 | |||
Pulkit Goyal
|
r39501 | includes, excludes, profiles = sparse.parseconfig(ui, fdata, 'narrow') | ||
Pulkit Goyal
|
r39283 | if profiles: | ||
raise error.Abort(_("cannot specify other files using '%include' in" | ||||
" narrowspec")) | ||||
Gregory Szorc
|
r39577 | narrowspec.validatepatterns(includes) | ||
narrowspec.validatepatterns(excludes) | ||||
Pulkit Goyal
|
r39283 | # narrowspec is passed so we should assume that user wants narrow clone | ||
Gregory Szorc
|
r39582 | opts['narrow'] = True | ||
Pulkit Goyal
|
r39283 | opts['include'].extend(includes) | ||
opts['exclude'].extend(excludes) | ||||
Gregory Szorc
|
r39582 | if opts['narrow']: | ||
Augie Fackler
|
r36096 | def pullbundle2extraprepare_widen(orig, pullop, kwargs): | ||
orig(pullop, kwargs) | ||||
if opts.get('depth'): | ||||
kwargs['depth'] = opts['depth'] | ||||
wrappedextraprepare = extensions.wrappedfunction(exchange, | ||||
'_pullbundle2extraprepare', pullbundle2extraprepare_widen) | ||||
Gregory Szorc
|
r39590 | with wrappedextraprepare: | ||
Augie Fackler
|
r36172 | return orig(ui, repo, *args, **pycompat.strkwargs(opts)) | ||
Augie Fackler
|
r36096 | |||
def pullnarrowcmd(orig, ui, repo, *args, **opts): | ||||
"""Wraps pull command to allow modifying narrow spec.""" | ||||
wrappedextraprepare = util.nullcontextmanager() | ||||
Martin von Zweigbergk
|
r38871 | if repository.NARROW_REQUIREMENT in repo.requirements: | ||
Augie Fackler
|
r36096 | |||
def pullbundle2extraprepare_widen(orig, pullop, kwargs): | ||||
orig(pullop, kwargs) | ||||
Pulkit Goyal
|
r36474 | if opts.get(r'depth'): | ||
kwargs['depth'] = opts[r'depth'] | ||||
Augie Fackler
|
r36096 | wrappedextraprepare = extensions.wrappedfunction(exchange, | ||
'_pullbundle2extraprepare', pullbundle2extraprepare_widen) | ||||
with wrappedextraprepare: | ||||
return orig(ui, repo, *args, **opts) | ||||
def archivenarrowcmd(orig, ui, repo, *args, **opts): | ||||
"""Wraps archive command to narrow the default includes.""" | ||||
Martin von Zweigbergk
|
r38871 | if repository.NARROW_REQUIREMENT in repo.requirements: | ||
Augie Fackler
|
r36096 | repo_includes, repo_excludes = repo.narrowpats | ||
Augie Fackler
|
r36370 | includes = set(opts.get(r'include', [])) | ||
excludes = set(opts.get(r'exclude', [])) | ||||
Augie Fackler
|
r36117 | includes, excludes, unused_invalid = narrowspec.restrictpatterns( | ||
Augie Fackler
|
r36096 | includes, excludes, repo_includes, repo_excludes) | ||
if includes: | ||||
Augie Fackler
|
r36370 | opts[r'include'] = includes | ||
Augie Fackler
|
r36096 | if excludes: | ||
Augie Fackler
|
r36370 | opts[r'exclude'] = excludes | ||
Augie Fackler
|
r36096 | return orig(ui, repo, *args, **opts) | ||
def pullbundle2extraprepare(orig, pullop, kwargs): | ||||
repo = pullop.repo | ||||
Martin von Zweigbergk
|
r38871 | if repository.NARROW_REQUIREMENT not in repo.requirements: | ||
Augie Fackler
|
r36096 | return orig(pullop, kwargs) | ||
Pulkit Goyal
|
r40110 | if wireprototypes.NARROWCAP not in pullop.remote.capabilities(): | ||
Pulkit Goyal
|
r40000 | raise error.Abort(_("server does not support narrow clones")) | ||
Augie Fackler
|
r36096 | orig(pullop, kwargs) | ||
kwargs['narrow'] = True | ||||
include, exclude = repo.narrowpats | ||||
kwargs['oldincludepats'] = include | ||||
kwargs['oldexcludepats'] = exclude | ||||
Pulkit Goyal
|
r40528 | if include: | ||
kwargs['includepats'] = include | ||||
if exclude: | ||||
kwargs['excludepats'] = exclude | ||||
Pulkit Goyal
|
r39560 | # calculate known nodes only in ellipses cases because in non-ellipses cases | ||
# we have all the nodes | ||||
Pulkit Goyal
|
r40110 | if wireprototypes.ELLIPSESCAP in pullop.remote.capabilities(): | ||
Pulkit Goyal
|
r39560 | kwargs['known'] = [node.hex(ctx.node()) for ctx in | ||
repo.set('::%ln', pullop.common) | ||||
if ctx.node() != node.nullid] | ||||
if not kwargs['known']: | ||||
# Mercurial serializes an empty list as '' and deserializes it as | ||||
# [''], so delete it instead to avoid handling the empty string on | ||||
# the server. | ||||
del kwargs['known'] | ||||
Augie Fackler
|
r36096 | |||
extensions.wrapfunction(exchange,'_pullbundle2extraprepare', | ||||
pullbundle2extraprepare) | ||||
Kyle Lippincott
|
r39770 | # This is an extension point for filesystems that need to do something other | ||
# than just blindly unlink the files. It's not clear what arguments would be | ||||
# useful, so we're passing in a fair number of them, some of them redundant. | ||||
def _narrowcleanupwdir(repo, oldincludes, oldexcludes, newincludes, newexcludes, | ||||
oldmatch, newmatch): | ||||
for f in repo.dirstate: | ||||
if not newmatch(f): | ||||
repo.dirstate.drop(f) | ||||
repo.wvfs.unlinkpath(f) | ||||
Augie Fackler
|
r36096 | def _narrow(ui, repo, remote, commoninc, oldincludes, oldexcludes, | ||
newincludes, newexcludes, force): | ||||
oldmatch = narrowspec.match(repo.root, oldincludes, oldexcludes) | ||||
newmatch = narrowspec.match(repo.root, newincludes, newexcludes) | ||||
# This is essentially doing "hg outgoing" to find all local-only | ||||
# commits. We will then check that the local-only commits don't | ||||
# have any changes to files that will be untracked. | ||||
unfi = repo.unfiltered() | ||||
outgoing = discovery.findcommonoutgoing(unfi, remote, | ||||
commoninc=commoninc) | ||||
ui.status(_('looking for local changes to affected paths\n')) | ||||
localnodes = [] | ||||
for n in itertools.chain(outgoing.missing, outgoing.excluded): | ||||
if any(oldmatch(f) and not newmatch(f) for f in unfi[n].files()): | ||||
localnodes.append(n) | ||||
revstostrip = unfi.revs('descendants(%ln)', localnodes) | ||||
hiddenrevs = repoview.filterrevs(repo, 'visible') | ||||
visibletostrip = list(repo.changelog.node(r) | ||||
for r in (revstostrip - hiddenrevs)) | ||||
if visibletostrip: | ||||
ui.status(_('The following changeset(s) or their ancestors have ' | ||||
'local changes not on the remote:\n')) | ||||
maxnodes = 10 | ||||
if ui.verbose or len(visibletostrip) <= maxnodes: | ||||
for n in visibletostrip: | ||||
ui.status('%s\n' % node.short(n)) | ||||
else: | ||||
for n in visibletostrip[:maxnodes]: | ||||
ui.status('%s\n' % node.short(n)) | ||||
ui.status(_('...and %d more, use --verbose to list all\n') % | ||||
(len(visibletostrip) - maxnodes)) | ||||
if not force: | ||||
raise error.Abort(_('local changes found'), | ||||
hint=_('use --force-delete-local-changes to ' | ||||
'ignore')) | ||||
Augie Fackler
|
r38547 | with ui.uninterruptable(): | ||
if revstostrip: | ||||
tostrip = [unfi.changelog.node(r) for r in revstostrip] | ||||
if repo['.'].node() in tostrip: | ||||
# stripping working copy, so move to a different commit first | ||||
urev = max(repo.revs('(::%n) - %ln + null', | ||||
repo['.'].node(), visibletostrip)) | ||||
hg.clean(repo, urev) | ||||
repair.strip(ui, unfi, tostrip, topic='narrow') | ||||
Augie Fackler
|
r36096 | |||
Augie Fackler
|
r38547 | todelete = [] | ||
for f, f2, size in repo.store.datafiles(): | ||||
if f.startswith('data/'): | ||||
file = f[5:-2] | ||||
if not newmatch(file): | ||||
todelete.append(f) | ||||
elif f.startswith('meta/'): | ||||
dir = f[5:-13] | ||||
dirs = ['.'] + sorted(util.dirs({dir})) + [dir] | ||||
include = True | ||||
for d in dirs: | ||||
visit = newmatch.visitdir(d) | ||||
if not visit: | ||||
include = False | ||||
break | ||||
if visit == 'all': | ||||
break | ||||
if not include: | ||||
todelete.append(f) | ||||
Augie Fackler
|
r36096 | |||
Augie Fackler
|
r38547 | repo.destroying() | ||
Augie Fackler
|
r36096 | |||
Augie Fackler
|
r38547 | with repo.transaction("narrowing"): | ||
for f in todelete: | ||||
ui.status(_('deleting %s\n') % f) | ||||
util.unlinkpath(repo.svfs.join(f)) | ||||
repo.store.markremoved(f) | ||||
Augie Fackler
|
r36096 | |||
Kyle Lippincott
|
r39770 | _narrowcleanupwdir(repo, oldincludes, oldexcludes, newincludes, | ||
newexcludes, oldmatch, newmatch) | ||||
Augie Fackler
|
r38547 | repo.setnarrowpats(newincludes, newexcludes) | ||
Augie Fackler
|
r36096 | |||
Augie Fackler
|
r38547 | repo.destroyed() | ||
Augie Fackler
|
r36096 | |||
Pulkit Goyal
|
r40001 | def _widen(ui, repo, remote, commoninc, oldincludes, oldexcludes, | ||
newincludes, newexcludes): | ||||
Augie Fackler
|
r36096 | newmatch = narrowspec.match(repo.root, newincludes, newexcludes) | ||
Pulkit Goyal
|
r39999 | # for now we assume that if a server has ellipses enabled, we will be | ||
# exchanging ellipses nodes. In future we should add ellipses as a client | ||||
# side requirement (maybe) to distinguish a client is shallow or not and | ||||
# then send that information to server whether we want ellipses or not. | ||||
# Theoretically a non-ellipses repo should be able to use narrow | ||||
# functionality from an ellipses enabled server | ||||
Pulkit Goyal
|
r40110 | ellipsesremote = wireprototypes.ELLIPSESCAP in remote.capabilities() | ||
Pulkit Goyal
|
r39999 | |||
Augie Fackler
|
r36096 | def pullbundle2extraprepare_widen(orig, pullop, kwargs): | ||
orig(pullop, kwargs) | ||||
# The old{in,ex}cludepats have already been set by orig() | ||||
kwargs['includepats'] = newincludes | ||||
kwargs['excludepats'] = newexcludes | ||||
wrappedextraprepare = extensions.wrappedfunction(exchange, | ||||
'_pullbundle2extraprepare', pullbundle2extraprepare_widen) | ||||
# define a function that narrowbundle2 can call after creating the | ||||
# backup bundle, but before applying the bundle from the server | ||||
def setnewnarrowpats(): | ||||
repo.setnarrowpats(newincludes, newexcludes) | ||||
repo.setnewnarrowpats = setnewnarrowpats | ||||
Pulkit Goyal
|
r39709 | # silence the devel-warning of applying an empty changegroup | ||
overrides = {('devel', 'all-warnings'): False} | ||||
Augie Fackler
|
r36096 | |||
Augie Fackler
|
r38547 | with ui.uninterruptable(): | ||
common = commoninc[0] | ||||
Pulkit Goyal
|
r39999 | if ellipsesremote: | ||
ds = repo.dirstate | ||||
p1, p2 = ds.p1(), ds.p2() | ||||
with ds.parentchange(): | ||||
ds.setparents(node.nullid, node.nullid) | ||||
with wrappedextraprepare,\ | ||||
repo.ui.configoverride(overrides, 'widen'): | ||||
exchange.pull(repo, remote, heads=common) | ||||
with ds.parentchange(): | ||||
ds.setparents(p1, p2) | ||||
else: | ||||
Pulkit Goyal
|
r40106 | with remote.commandexecutor() as e: | ||
bundle = e.callcommand('narrow_widen', { | ||||
'oldincludes': oldincludes, | ||||
'oldexcludes': oldexcludes, | ||||
'newincludes': newincludes, | ||||
'newexcludes': newexcludes, | ||||
'cgversion': '03', | ||||
'commonheads': common, | ||||
'known': [], | ||||
'ellipses': False, | ||||
}).result() | ||||
with repo.transaction('widening') as tr,\ | ||||
Pulkit Goyal
|
r39999 | repo.ui.configoverride(overrides, 'widen'): | ||
Pulkit Goyal
|
r40106 | tgetter = lambda: tr | ||
bundle2.processbundle(repo, bundle, | ||||
transactiongetter=tgetter) | ||||
Augie Fackler
|
r36096 | |||
Pulkit Goyal
|
r39393 | repo.setnewnarrowpats() | ||
Augie Fackler
|
r38547 | actions = {k: [] for k in 'a am f g cd dc r dm dg m e k p pr'.split()} | ||
addgaction = actions['g'].append | ||||
Augie Fackler
|
r36096 | |||
Augie Fackler
|
r38547 | mf = repo['.'].manifest().matches(newmatch) | ||
for f, fn in mf.iteritems(): | ||||
if f not in repo.dirstate: | ||||
addgaction((f, (mf.flags(f), False), | ||||
"add from widened narrow clone")) | ||||
Augie Fackler
|
r36096 | |||
Augie Fackler
|
r38547 | merge.applyupdates(repo, actions, wctx=repo[None], | ||
mctx=repo['.'], overwrite=False) | ||||
merge.recordupdates(repo, actions, branchmerge=False) | ||||
Augie Fackler
|
r36096 | |||
# TODO(rdamazio): Make new matcher format and update description | ||||
@command('tracked', | ||||
[('', 'addinclude', [], _('new paths to include')), | ||||
('', 'removeinclude', [], _('old paths to no longer include')), | ||||
('', 'addexclude', [], _('new paths to exclude')), | ||||
Pulkit Goyal
|
r39471 | ('', 'import-rules', '', _('import narrowspecs from a file')), | ||
Augie Fackler
|
r36096 | ('', 'removeexclude', [], _('old paths to no longer exclude')), | ||
('', 'clear', False, _('whether to replace the existing narrowspec')), | ||||
('', 'force-delete-local-changes', False, | ||||
_('forces deletion of local changes when narrowing')), | ||||
] + commands.remoteopts, | ||||
_('[OPTIONS]... [REMOTE]'), | ||||
inferrepo=True) | ||||
def trackedcmd(ui, repo, remotepath=None, *pats, **opts): | ||||
"""show or change the current narrowspec | ||||
With no argument, shows the current narrowspec entries, one per line. Each | ||||
line will be prefixed with 'I' or 'X' for included or excluded patterns, | ||||
respectively. | ||||
The narrowspec is comprised of expressions to match remote files and/or | ||||
directories that should be pulled into your client. | ||||
The narrowspec has *include* and *exclude* expressions, with excludes always | ||||
trumping includes: that is, if a file matches an exclude expression, it will | ||||
be excluded even if it also matches an include expression. | ||||
Excluding files that were never included has no effect. | ||||
Each included or excluded entry is in the format described by | ||||
'hg help patterns'. | ||||
The options allow you to add or remove included and excluded expressions. | ||||
If --clear is specified, then all previous includes and excludes are DROPPED | ||||
and replaced by the new ones specified to --addinclude and --addexclude. | ||||
If --clear is specified without any further options, the narrowspec will be | ||||
empty and will not match any files. | ||||
""" | ||||
Augie Fackler
|
r36184 | opts = pycompat.byteskwargs(opts) | ||
Martin von Zweigbergk
|
r38871 | if repository.NARROW_REQUIREMENT not in repo.requirements: | ||
Augie Fackler
|
r36096 | ui.warn(_('The narrow command is only supported on respositories cloned' | ||
' with --narrow.\n')) | ||||
return 1 | ||||
# Before supporting, decide whether it "hg tracked --clear" should mean | ||||
# tracking no paths or all paths. | ||||
if opts['clear']: | ||||
ui.warn(_('The --clear option is not yet supported.\n')) | ||||
return 1 | ||||
Pulkit Goyal
|
r39471 | # import rules from a file | ||
newrules = opts.get('import_rules') | ||||
if newrules: | ||||
try: | ||||
Matt Harbison
|
r39843 | filepath = os.path.join(encoding.getcwd(), newrules) | ||
Pulkit Goyal
|
r39471 | fdata = util.readfile(filepath) | ||
except IOError as inst: | ||||
raise error.Abort(_("cannot read narrowspecs from '%s': %s") % | ||||
(filepath, encoding.strtolocal(inst.strerror))) | ||||
includepats, excludepats, profiles = sparse.parseconfig(ui, fdata, | ||||
'narrow') | ||||
if profiles: | ||||
raise error.Abort(_("including other spec files using '%include' " | ||||
"is not supported in narrowspec")) | ||||
opts['addinclude'].extend(includepats) | ||||
opts['addexclude'].extend(excludepats) | ||||
Augie Fackler
|
r36096 | addedincludes = narrowspec.parsepatterns(opts['addinclude']) | ||
removedincludes = narrowspec.parsepatterns(opts['removeinclude']) | ||||
addedexcludes = narrowspec.parsepatterns(opts['addexclude']) | ||||
removedexcludes = narrowspec.parsepatterns(opts['removeexclude']) | ||||
Pulkit Goyal
|
r40462 | |||
only_show = not (addedincludes or removedincludes or addedexcludes or | ||||
removedexcludes or newrules) | ||||
oldincludes, oldexcludes = repo.narrowpats | ||||
# filter the user passed additions and deletions into actual additions and | ||||
# deletions of excludes and includes | ||||
Martin von Zweigbergk
|
r40465 | addedincludes -= oldincludes | ||
removedincludes &= oldincludes | ||||
addedexcludes -= oldexcludes | ||||
removedexcludes &= oldexcludes | ||||
Pulkit Goyal
|
r40462 | |||
Augie Fackler
|
r36096 | widening = addedincludes or removedexcludes | ||
narrowing = removedincludes or addedexcludes | ||||
# Only print the current narrowspec. | ||||
if only_show: | ||||
include, exclude = repo.narrowpats | ||||
ui.pager('tracked') | ||||
fm = ui.formatter('narrow', opts) | ||||
for i in sorted(include): | ||||
fm.startitem() | ||||
fm.write('status', '%s ', 'I', label='narrow.included') | ||||
fm.write('pat', '%s\n', i, label='narrow.included') | ||||
for i in sorted(exclude): | ||||
fm.startitem() | ||||
fm.write('status', '%s ', 'X', label='narrow.excluded') | ||||
fm.write('pat', '%s\n', i, label='narrow.excluded') | ||||
fm.end() | ||||
return 0 | ||||
Pulkit Goyal
|
r40462 | if not widening and not narrowing: | ||
ui.status(_("nothing to widen or narrow\n")) | ||||
return 0 | ||||
Augie Fackler
|
r36096 | with repo.wlock(), repo.lock(): | ||
cmdutil.bailifchanged(repo) | ||||
# Find the revisions we have in common with the remote. These will | ||||
# be used for finding local-only changes for narrowing. They will | ||||
# also define the set of revisions to update for widening. | ||||
remotepath = ui.expandpath(remotepath or 'default') | ||||
url, branches = hg.parseurl(remotepath) | ||||
ui.status(_('comparing with %s\n') % util.hidepassword(url)) | ||||
remote = hg.peer(repo, opts, url) | ||||
Pulkit Goyal
|
r40000 | |||
# check narrow support before doing anything if widening needs to be | ||||
# performed. In future we should also abort if client is ellipses and | ||||
# server does not support ellipses | ||||
Pulkit Goyal
|
r40110 | if widening and wireprototypes.NARROWCAP not in remote.capabilities(): | ||
Pulkit Goyal
|
r40000 | raise error.Abort(_("server does not support narrow clones")) | ||
Augie Fackler
|
r36096 | commoninc = discovery.findcommonincoming(repo, remote) | ||
if narrowing: | ||||
newincludes = oldincludes - removedincludes | ||||
newexcludes = oldexcludes | addedexcludes | ||||
_narrow(ui, repo, remote, commoninc, oldincludes, oldexcludes, | ||||
newincludes, newexcludes, | ||||
opts['force_delete_local_changes']) | ||||
# _narrow() updated the narrowspec and _widen() below needs to | ||||
# use the updated values as its base (otherwise removed includes | ||||
# and addedexcludes will be lost in the resulting narrowspec) | ||||
oldincludes = newincludes | ||||
oldexcludes = newexcludes | ||||
if widening: | ||||
newincludes = oldincludes | addedincludes | ||||
newexcludes = oldexcludes - removedexcludes | ||||
Pulkit Goyal
|
r40001 | _widen(ui, repo, remote, commoninc, oldincludes, oldexcludes, | ||
newincludes, newexcludes) | ||||
Augie Fackler
|
r36096 | |||
return 0 | ||||