Now that we have named attributes, let's convert the code base to use
them. We also add deprecation warnings so legacy consumers are aware
of their transgressions.
`stats.unresolvedcount is much easier to read than stats[3]`,
don't you think?
( )
durin42 | |
martinvonz | |
pulkit |
hg-reviewers |
Now that we have named attributes, let's convert the code base to use
them. We also add deprecation warnings so legacy consumers are aware
of their transgressions.
`stats.unresolvedcount is much easier to read than stats[3]`,
don't you think?
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
This one failed to apply, probably because of my changes to rebase.py. I have to leave now, but I'll try again later tonight, whether or not you've gotten a chance to update it.
Path | Packages | |||
---|---|---|---|---|
M | hgext/histedit.py (2 lines) | |||
M | hgext/rebase.py (2 lines) | |||
M | mercurial/commands.py (4 lines) | |||
M | mercurial/hg.py (12 lines) | |||
M | mercurial/merge.py (11 lines) |
"""Applies the changes from this action's rulectx onto the current | """Applies the changes from this action's rulectx onto the current | ||||
parentctx, but does not commit them.""" | parentctx, but does not commit them.""" | ||||
repo = self.repo | repo = self.repo | ||||
rulectx = repo[self.node] | rulectx = repo[self.node] | ||||
repo.ui.pushbuffer(error=True, labeled=True) | repo.ui.pushbuffer(error=True, labeled=True) | ||||
hg.update(repo, self.state.parentctxnode, quietempty=True) | hg.update(repo, self.state.parentctxnode, quietempty=True) | ||||
stats = applychanges(repo.ui, repo, rulectx, {}) | stats = applychanges(repo.ui, repo, rulectx, {}) | ||||
repo.dirstate.setbranch(rulectx.branch()) | repo.dirstate.setbranch(rulectx.branch()) | ||||
if stats and stats[3] > 0: | if stats.unresolvedcount: | ||||
buf = repo.ui.popbuffer() | buf = repo.ui.popbuffer() | ||||
repo.ui.write(buf) | repo.ui.write(buf) | ||||
raise error.InterventionRequired( | raise error.InterventionRequired( | ||||
_('Fix up the change (%s %s)') % | _('Fix up the change (%s %s)') % | ||||
(self.verb, node.short(self.node)), | (self.verb, node.short(self.node)), | ||||
hint=_('hg histedit --continue to resume')) | hint=_('hg histedit --continue to resume')) | ||||
else: | else: | ||||
repo.ui.popbuffer() | repo.ui.popbuffer() |
self.obsoletenotrebased) | self.obsoletenotrebased) | ||||
if len(repo[None].parents()) == 2: | if len(repo[None].parents()) == 2: | ||||
repo.ui.debug('resuming interrupted rebase\n') | repo.ui.debug('resuming interrupted rebase\n') | ||||
else: | else: | ||||
overrides = {('ui', 'forcemerge'): opts.get('tool', '')} | overrides = {('ui', 'forcemerge'): opts.get('tool', '')} | ||||
with ui.configoverride(overrides, 'rebase'): | with ui.configoverride(overrides, 'rebase'): | ||||
stats = rebasenode(repo, rev, p1, base, self.collapsef, | stats = rebasenode(repo, rev, p1, base, self.collapsef, | ||||
dest, wctx=self.wctx) | dest, wctx=self.wctx) | ||||
if stats[3] > 0: | if stats.unresolvedcount > 0: | ||||
if self.inmemory: | if self.inmemory: | ||||
raise error.InMemoryMergeConflictsError() | raise error.InMemoryMergeConflictsError() | ||||
else: | else: | ||||
raise error.InterventionRequired( | raise error.InterventionRequired( | ||||
_('unresolved conflicts (see hg ' | _('unresolved conflicts (see hg ' | ||||
'resolve, then hg rebase --continue)')) | 'resolve, then hg rebase --continue)')) | ||||
if not self.collapsef: | if not self.collapsef: | ||||
merging = p2 != nullrev | merging = p2 != nullrev |
dsguard = dirstateguard.dirstateguard(repo, 'backout') | dsguard = dirstateguard.dirstateguard(repo, 'backout') | ||||
try: | try: | ||||
ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), | ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), | ||||
'backout') | 'backout') | ||||
stats = mergemod.update(repo, parent, True, True, node, False) | stats = mergemod.update(repo, parent, True, True, node, False) | ||||
repo.setparents(op1, op2) | repo.setparents(op1, op2) | ||||
dsguard.close() | dsguard.close() | ||||
hg._showstats(repo, stats) | hg._showstats(repo, stats) | ||||
if stats[3]: | if stats.unresolvedcount: | ||||
repo.ui.status(_("use 'hg resolve' to retry unresolved " | repo.ui.status(_("use 'hg resolve' to retry unresolved " | ||||
"file merges\n")) | "file merges\n")) | ||||
return 1 | return 1 | ||||
finally: | finally: | ||||
ui.setconfig('ui', 'forcemerge', '', '') | ui.setconfig('ui', 'forcemerge', '', '') | ||||
lockmod.release(dsguard) | lockmod.release(dsguard) | ||||
else: | else: | ||||
hg.clean(repo, node, show_stats=False) | hg.clean(repo, node, show_stats=False) | ||||
# ui.forcemerge is an internal variable, do not document | # ui.forcemerge is an internal variable, do not document | ||||
repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), | repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), | ||||
'graft') | 'graft') | ||||
stats = mergemod.graft(repo, ctx, ctx.p1(), | stats = mergemod.graft(repo, ctx, ctx.p1(), | ||||
['local', 'graft']) | ['local', 'graft']) | ||||
finally: | finally: | ||||
repo.ui.setconfig('ui', 'forcemerge', '', 'graft') | repo.ui.setconfig('ui', 'forcemerge', '', 'graft') | ||||
# report any conflicts | # report any conflicts | ||||
if stats[3] > 0: | if stats.unresolvedcount > 0: | ||||
# write out state for --continue | # write out state for --continue | ||||
nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]] | nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]] | ||||
repo.vfs.write('graftstate', ''.join(nodelines)) | repo.vfs.write('graftstate', ''.join(nodelines)) | ||||
extra = '' | extra = '' | ||||
if opts.get('user'): | if opts.get('user'): | ||||
extra += ' --user %s' % procutil.shellquote(opts['user']) | extra += ' --user %s' % procutil.shellquote(opts['user']) | ||||
if opts.get('date'): | if opts.get('date'): | ||||
extra += ' --date %s' % procutil.shellquote(opts['date']) | extra += ' --date %s' % procutil.shellquote(opts['date']) |
release(srclock, destlock) | release(srclock, destlock) | ||||
if cleandir is not None: | if cleandir is not None: | ||||
shutil.rmtree(cleandir, True) | shutil.rmtree(cleandir, True) | ||||
if srcpeer is not None: | if srcpeer is not None: | ||||
srcpeer.close() | srcpeer.close() | ||||
return srcpeer, destpeer | return srcpeer, destpeer | ||||
def _showstats(repo, stats, quietempty=False): | def _showstats(repo, stats, quietempty=False): | ||||
if quietempty and not any(stats): | if quietempty and stats.isempty(): | ||||
return | return | ||||
repo.ui.status(_("%d files updated, %d files merged, " | repo.ui.status(_("%d files updated, %d files merged, " | ||||
"%d files removed, %d files unresolved\n") % ( | "%d files removed, %d files unresolved\n") % ( | ||||
stats.updatedcount, stats.mergedcount, | stats.updatedcount, stats.mergedcount, | ||||
stats.removedcount, stats.unresolvedcount)) | stats.removedcount, stats.unresolvedcount)) | ||||
def updaterepo(repo, node, overwrite, updatecheck=None): | def updaterepo(repo, node, overwrite, updatecheck=None): | ||||
"""Update the working directory to node. | """Update the working directory to node. | ||||
When overwrite is set, changes are clobbered, merged else | When overwrite is set, changes are clobbered, merged else | ||||
returns stats (see pydoc mercurial.merge.applyupdates)""" | returns stats (see pydoc mercurial.merge.applyupdates)""" | ||||
return mergemod.update(repo, node, False, overwrite, | return mergemod.update(repo, node, False, overwrite, | ||||
labels=['working copy', 'destination'], | labels=['working copy', 'destination'], | ||||
updatecheck=updatecheck) | updatecheck=updatecheck) | ||||
def update(repo, node, quietempty=False, updatecheck=None): | def update(repo, node, quietempty=False, updatecheck=None): | ||||
"""update the working directory to node""" | """update the working directory to node""" | ||||
stats = updaterepo(repo, node, False, updatecheck=updatecheck) | stats = updaterepo(repo, node, False, updatecheck=updatecheck) | ||||
_showstats(repo, stats, quietempty) | _showstats(repo, stats, quietempty) | ||||
if stats[3]: | if stats.unresolvedcount: | ||||
repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n")) | repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n")) | ||||
return stats[3] > 0 | return stats.unresolvedcount > 0 | ||||
# naming conflict in clone() | # naming conflict in clone() | ||||
_update = update | _update = update | ||||
def clean(repo, node, show_stats=True, quietempty=False): | def clean(repo, node, show_stats=True, quietempty=False): | ||||
"""forcibly switch the working directory to node, clobbering changes""" | """forcibly switch the working directory to node, clobbering changes""" | ||||
stats = updaterepo(repo, node, True) | stats = updaterepo(repo, node, True) | ||||
repo.vfs.unlinkpath('graftstate', ignoremissing=True) | repo.vfs.unlinkpath('graftstate', ignoremissing=True) | ||||
if show_stats: | if show_stats: | ||||
_showstats(repo, stats, quietempty) | _showstats(repo, stats, quietempty) | ||||
return stats[3] > 0 | return stats.unresolvedcount > 0 | ||||
# naming conflict in updatetotally() | # naming conflict in updatetotally() | ||||
_clean = clean | _clean = clean | ||||
def updatetotally(ui, repo, checkout, brev, clean=False, updatecheck=None): | def updatetotally(ui, repo, checkout, brev, clean=False, updatecheck=None): | ||||
"""Update the working directory with extra care for non-file components | """Update the working directory with extra care for non-file components | ||||
This takes care of non-file components below: | This takes care of non-file components below: | ||||
node = repo['.'].hex() | node = repo['.'].hex() | ||||
repo.ui.status(_("aborting the merge, updating back to" | repo.ui.status(_("aborting the merge, updating back to" | ||||
" %s\n") % node[:12]) | " %s\n") % node[:12]) | ||||
stats = mergemod.update(repo, node, branchmerge=False, force=True, | stats = mergemod.update(repo, node, branchmerge=False, force=True, | ||||
labels=labels) | labels=labels) | ||||
_showstats(repo, stats) | _showstats(repo, stats) | ||||
if stats[3]: | if stats.unresolvedcount: | ||||
repo.ui.status(_("use 'hg resolve' to retry unresolved file merges " | repo.ui.status(_("use 'hg resolve' to retry unresolved file merges " | ||||
"or 'hg merge --abort' to abandon\n")) | "or 'hg merge --abort' to abandon\n")) | ||||
elif remind and not abort: | elif remind and not abort: | ||||
repo.ui.status(_("(branch merge, don't forget to commit)\n")) | repo.ui.status(_("(branch merge, don't forget to commit)\n")) | ||||
return stats[3] > 0 | return stats.unresolvedcount > 0 | ||||
def _incoming(displaychlist, subreporecurse, ui, repo, source, | def _incoming(displaychlist, subreporecurse, ui, repo, source, | ||||
opts, buffered=False): | opts, buffered=False): | ||||
""" | """ | ||||
Helper for incoming / gincoming. | Helper for incoming / gincoming. | ||||
displaychlist gets called with | displaychlist gets called with | ||||
(remoterepo, incomingchangesetlist, displayer) parameters, | (remoterepo, incomingchangesetlist, displayer) parameters, | ||||
and is supposed to contain only code that can't be unified. | and is supposed to contain only code that can't be unified. |
@attr.s(frozen=True) | @attr.s(frozen=True) | ||||
class updateresult(object): | class updateresult(object): | ||||
updatedcount = attr.ib() | updatedcount = attr.ib() | ||||
mergedcount = attr.ib() | mergedcount = attr.ib() | ||||
removedcount = attr.ib() | removedcount = attr.ib() | ||||
unresolvedcount = attr.ib() | unresolvedcount = attr.ib() | ||||
def isempty(self): | |||||
return (not self.updatedcount and not self.mergedcount | |||||
and not self.removedcount and not self.unresolvedcount) | |||||
# TODO remove container emulation once consumers switch to new API. | # TODO remove container emulation once consumers switch to new API. | ||||
def __getitem__(self, x): | def __getitem__(self, x): | ||||
util.nouideprecwarn('access merge.update() results by name instead of ' | |||||
'index', '4.6', 2) | |||||
if x == 0: | if x == 0: | ||||
return self.updatedcount | return self.updatedcount | ||||
elif x == 1: | elif x == 1: | ||||
return self.mergedcount | return self.mergedcount | ||||
elif x == 2: | elif x == 2: | ||||
return self.removedcount | return self.removedcount | ||||
elif x == 3: | elif x == 3: | ||||
return self.unresolvedcount | return self.unresolvedcount | ||||
else: | else: | ||||
raise IndexError('can only access items 0-3') | raise IndexError('can only access items 0-3') | ||||
def __len__(self): | def __len__(self): | ||||
util.nouideprecwarn('access merge.update() results by name instead of ' | |||||
'index', '4.6', 2) | |||||
return 4 | return 4 | ||||
def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None): | def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None): | ||||
"""apply the merge action list to the working directory | """apply the merge action list to the working directory | ||||
wctx is the working copy context | wctx is the working copy context | ||||
mctx is the context to be merged into the working copy | mctx is the context to be merged into the working copy | ||||
repo.dirstate.setbranch(p2.branch()) | repo.dirstate.setbranch(p2.branch()) | ||||
# If we're updating to a location, clean up any stale temporary includes | # If we're updating to a location, clean up any stale temporary includes | ||||
# (ex: this happens during hg rebase --abort). | # (ex: this happens during hg rebase --abort). | ||||
if not branchmerge: | if not branchmerge: | ||||
sparse.prunetemporaryincludes(repo) | sparse.prunetemporaryincludes(repo) | ||||
if not partial: | if not partial: | ||||
repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3]) | repo.hook('update', parent1=xp1, parent2=xp2, | ||||
error=stats.unresolvedcount) | |||||
return stats | return stats | ||||
def graft(repo, ctx, pctx, labels, keepparent=False): | def graft(repo, ctx, pctx, labels, keepparent=False): | ||||
"""Do a graft-like merge. | """Do a graft-like merge. | ||||
This is a merge where the merge ancestor is chosen such that one | This is a merge where the merge ancestor is chosen such that one | ||||
or more changesets are grafted onto the current changeset. In | or more changesets are grafted onto the current changeset. In | ||||
addition to the merge, this fixes up the dirstate to include only | addition to the merge, this fixes up the dirstate to include only |