Details
Details
- Reviewers
pulkit - Group Reviewers
hg-reviewers - Commits
- rHGfc8e29ffc380: dog-raft: work with str-keyed opts throughout
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Branch
- default
- Lint
No Linters Available - Unit
No Unit Test Coverage
pulkit |
hg-reviewers |
No Linters Available |
No Unit Test Coverage |
Path | Packages | |||
---|---|---|---|---|
M | mercurial/commands.py (95 lines) |
Commit | Parents | Author | Summary | Date |
---|---|---|---|---|
39eb1c1d2f38 | 22cc135fd71a | Martin von Zweigbergk | Jun 10 2021, 6:56 PM |
Status | Author | Revision | |
---|---|---|---|
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz |
revs = list(revs) | revs = list(revs) | ||||
revs.extend(opts.get('rev')) | revs.extend(opts.get('rev')) | ||||
# a dict of data to be stored in state file | # a dict of data to be stored in state file | ||||
statedata = {} | statedata = {} | ||||
# list of new nodes created by ongoing graft | # list of new nodes created by ongoing graft | ||||
statedata[b'newnodes'] = [] | statedata[b'newnodes'] = [] | ||||
cmdutil.resolve_commit_options(ui, opts) | cmdutil.resolve_commit_options(ui, opts) | ||||
opts = pycompat.byteskwargs(opts) | |||||
editor = cmdutil.getcommiteditor( | editor = cmdutil.getcommiteditor(editform=b'graft', **opts) | ||||
editform=b'graft', **pycompat.strkwargs(opts) | |||||
) | |||||
cmdutil.check_at_most_one_arg(opts, b'abort', b'stop', b'continue') | cmdutil.check_at_most_one_arg(opts, 'abort', 'stop', 'continue') | ||||
cont = False | cont = False | ||||
if opts.get(b'no_commit'): | if opts.get('no_commit'): | ||||
cmdutil.check_incompatible_arguments( | cmdutil.check_incompatible_arguments( | ||||
opts, | opts, | ||||
b'no_commit', | 'no_commit', | ||||
[b'edit', b'currentuser', b'currentdate', b'log'], | ['edit', 'currentuser', 'currentdate', 'log'], | ||||
) | ) | ||||
graftstate = statemod.cmdstate(repo, b'graftstate') | graftstate = statemod.cmdstate(repo, b'graftstate') | ||||
if opts.get(b'stop'): | if opts.get('stop'): | ||||
cmdutil.check_incompatible_arguments( | cmdutil.check_incompatible_arguments( | ||||
opts, | opts, | ||||
b'stop', | 'stop', | ||||
[ | [ | ||||
b'edit', | 'edit', | ||||
b'log', | 'log', | ||||
b'user', | 'user', | ||||
b'date', | 'date', | ||||
b'currentdate', | 'currentdate', | ||||
b'currentuser', | 'currentuser', | ||||
b'rev', | 'rev', | ||||
], | ], | ||||
) | ) | ||||
return _stopgraft(ui, repo, graftstate) | return _stopgraft(ui, repo, graftstate) | ||||
elif opts.get(b'abort'): | elif opts.get('abort'): | ||||
cmdutil.check_incompatible_arguments( | cmdutil.check_incompatible_arguments( | ||||
opts, | opts, | ||||
b'abort', | 'abort', | ||||
[ | [ | ||||
b'edit', | 'edit', | ||||
b'log', | 'log', | ||||
b'user', | 'user', | ||||
b'date', | 'date', | ||||
b'currentdate', | 'currentdate', | ||||
b'currentuser', | 'currentuser', | ||||
b'rev', | 'rev', | ||||
], | ], | ||||
) | ) | ||||
return cmdutil.abortgraft(ui, repo, graftstate) | return cmdutil.abortgraft(ui, repo, graftstate) | ||||
elif opts.get(b'continue'): | elif opts.get('continue'): | ||||
cont = True | cont = True | ||||
if revs: | if revs: | ||||
raise error.InputError(_(b"can't specify --continue and revisions")) | raise error.InputError(_(b"can't specify --continue and revisions")) | ||||
# read in unfinished revisions | # read in unfinished revisions | ||||
if graftstate.exists(): | if graftstate.exists(): | ||||
statedata = cmdutil.readgraftstate(repo, graftstate) | statedata = cmdutil.readgraftstate(repo, graftstate) | ||||
if statedata.get(b'date'): | if statedata.get(b'date'): | ||||
opts[b'date'] = statedata[b'date'] | opts['date'] = statedata[b'date'] | ||||
if statedata.get(b'user'): | if statedata.get(b'user'): | ||||
opts[b'user'] = statedata[b'user'] | opts['user'] = statedata[b'user'] | ||||
if statedata.get(b'log'): | if statedata.get(b'log'): | ||||
opts[b'log'] = True | opts['log'] = True | ||||
if statedata.get(b'no_commit'): | if statedata.get(b'no_commit'): | ||||
opts[b'no_commit'] = statedata.get(b'no_commit') | opts['no_commit'] = statedata.get(b'no_commit') | ||||
if statedata.get(b'base'): | if statedata.get(b'base'): | ||||
opts[b'base'] = statedata.get(b'base') | opts['base'] = statedata.get(b'base') | ||||
nodes = statedata[b'nodes'] | nodes = statedata[b'nodes'] | ||||
revs = [repo[node].rev() for node in nodes] | revs = [repo[node].rev() for node in nodes] | ||||
else: | else: | ||||
cmdutil.wrongtooltocontinue(repo, _(b'graft')) | cmdutil.wrongtooltocontinue(repo, _(b'graft')) | ||||
else: | else: | ||||
if not revs: | if not revs: | ||||
raise error.InputError(_(b'no revisions specified')) | raise error.InputError(_(b'no revisions specified')) | ||||
cmdutil.checkunfinished(repo) | cmdutil.checkunfinished(repo) | ||||
cmdutil.bailifchanged(repo) | cmdutil.bailifchanged(repo) | ||||
revs = scmutil.revrange(repo, revs) | revs = scmutil.revrange(repo, revs) | ||||
skipped = set() | skipped = set() | ||||
basectx = None | basectx = None | ||||
if opts.get(b'base'): | if opts.get('base'): | ||||
basectx = scmutil.revsingle(repo, opts[b'base'], None) | basectx = scmutil.revsingle(repo, opts['base'], None) | ||||
if basectx is None: | if basectx is None: | ||||
# check for merges | # check for merges | ||||
for rev in repo.revs(b'%ld and merge()', revs): | for rev in repo.revs(b'%ld and merge()', revs): | ||||
ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev) | ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev) | ||||
skipped.add(rev) | skipped.add(rev) | ||||
revs = [r for r in revs if r not in skipped] | revs = [r for r in revs if r not in skipped] | ||||
if not revs: | if not revs: | ||||
return -1 | return -1 | ||||
if basectx is not None and len(revs) != 1: | if basectx is not None and len(revs) != 1: | ||||
raise error.InputError(_(b'only one revision allowed with --base ')) | raise error.InputError(_(b'only one revision allowed with --base ')) | ||||
# Don't check in the --continue case, in effect retaining --force across | # Don't check in the --continue case, in effect retaining --force across | ||||
# --continues. That's because without --force, any revisions we decided to | # --continues. That's because without --force, any revisions we decided to | ||||
# skip would have been filtered out here, so they wouldn't have made their | # skip would have been filtered out here, so they wouldn't have made their | ||||
# way to the graftstate. With --force, any revisions we would have otherwise | # way to the graftstate. With --force, any revisions we would have otherwise | ||||
# skipped would not have been filtered out, and if they hadn't been applied | # skipped would not have been filtered out, and if they hadn't been applied | ||||
# already, they'd have been in the graftstate. | # already, they'd have been in the graftstate. | ||||
if not (cont or opts.get(b'force')) and basectx is None: | if not (cont or opts.get('force')) and basectx is None: | ||||
# check for ancestors of dest branch | # check for ancestors of dest branch | ||||
ancestors = repo.revs(b'%ld & (::.)', revs) | ancestors = repo.revs(b'%ld & (::.)', revs) | ||||
for rev in ancestors: | for rev in ancestors: | ||||
ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev])) | ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev])) | ||||
revs = [r for r in revs if r not in ancestors] | revs = [r for r in revs if r not in ancestors] | ||||
if not revs: | if not revs: | ||||
b'(was grafted from %d:%s)\n' | b'(was grafted from %d:%s)\n' | ||||
) | ) | ||||
% (r, repo[r], rev, ctx) | % (r, repo[r], rev, ctx) | ||||
) | ) | ||||
revs.remove(r) | revs.remove(r) | ||||
if not revs: | if not revs: | ||||
return -1 | return -1 | ||||
if opts.get(b'no_commit'): | if opts.get('no_commit'): | ||||
statedata[b'no_commit'] = True | statedata[b'no_commit'] = True | ||||
if opts.get(b'base'): | if opts.get('base'): | ||||
statedata[b'base'] = opts[b'base'] | statedata[b'base'] = opts['base'] | ||||
for pos, ctx in enumerate(repo.set(b"%ld", revs)): | for pos, ctx in enumerate(repo.set(b"%ld", revs)): | ||||
desc = b'%d:%s "%s"' % ( | desc = b'%d:%s "%s"' % ( | ||||
ctx.rev(), | ctx.rev(), | ||||
ctx, | ctx, | ||||
ctx.description().split(b'\n', 1)[0], | ctx.description().split(b'\n', 1)[0], | ||||
) | ) | ||||
names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node()) | names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node()) | ||||
if names: | if names: | ||||
desc += b' (%s)' % b' '.join(names) | desc += b' (%s)' % b' '.join(names) | ||||
ui.status(_(b'grafting %s\n') % desc) | ui.status(_(b'grafting %s\n') % desc) | ||||
if opts.get(b'dry_run'): | if opts.get('dry_run'): | ||||
continue | continue | ||||
source = ctx.extra().get(b'source') | source = ctx.extra().get(b'source') | ||||
extra = {} | extra = {} | ||||
if source: | if source: | ||||
extra[b'source'] = source | extra[b'source'] = source | ||||
extra[b'intermediate-source'] = ctx.hex() | extra[b'intermediate-source'] = ctx.hex() | ||||
else: | else: | ||||
extra[b'source'] = ctx.hex() | extra[b'source'] = ctx.hex() | ||||
user = ctx.user() | user = ctx.user() | ||||
if opts.get(b'user'): | if opts.get('user'): | ||||
user = opts[b'user'] | user = opts['user'] | ||||
statedata[b'user'] = user | statedata[b'user'] = user | ||||
date = ctx.date() | date = ctx.date() | ||||
if opts.get(b'date'): | if opts.get('date'): | ||||
date = opts[b'date'] | date = opts['date'] | ||||
statedata[b'date'] = date | statedata[b'date'] = date | ||||
message = ctx.description() | message = ctx.description() | ||||
if opts.get(b'log'): | if opts.get('log'): | ||||
message += b'\n(grafted from %s)' % ctx.hex() | message += b'\n(grafted from %s)' % ctx.hex() | ||||
statedata[b'log'] = True | statedata[b'log'] = True | ||||
# we don't merge the first commit when continuing | # we don't merge the first commit when continuing | ||||
if not cont: | if not cont: | ||||
# perform the graft merge with p1(rev) as 'ancestor' | # perform the graft merge with p1(rev) as 'ancestor' | ||||
overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')} | overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')} | ||||
base = ctx.p1() if basectx is None else basectx | base = ctx.p1() if basectx is None else basectx | ||||
with ui.configoverride(overrides, b'graft'): | with ui.configoverride(overrides, b'graft'): | ||||
stats = mergemod.graft(repo, ctx, base, [b'local', b'graft']) | stats = mergemod.graft(repo, ctx, base, [b'local', b'graft']) | ||||
# report any conflicts | # report any conflicts | ||||
if stats.unresolvedcount > 0: | if stats.unresolvedcount > 0: | ||||
# write out state for --continue | # write out state for --continue | ||||
nodes = [repo[rev].hex() for rev in revs[pos:]] | nodes = [repo[rev].hex() for rev in revs[pos:]] | ||||
statedata[b'nodes'] = nodes | statedata[b'nodes'] = nodes | ||||
stateversion = 1 | stateversion = 1 | ||||
graftstate.save(stateversion, statedata) | graftstate.save(stateversion, statedata) | ||||
ui.error(_(b"abort: unresolved conflicts, can't continue\n")) | ui.error(_(b"abort: unresolved conflicts, can't continue\n")) | ||||
ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n")) | ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n")) | ||||
return 1 | return 1 | ||||
else: | else: | ||||
cont = False | cont = False | ||||
# commit if --no-commit is false | # commit if --no-commit is false | ||||
if not opts.get(b'no_commit'): | if not opts.get('no_commit'): | ||||
node = repo.commit( | node = repo.commit( | ||||
text=message, user=user, date=date, extra=extra, editor=editor | text=message, user=user, date=date, extra=extra, editor=editor | ||||
) | ) | ||||
if node is None: | if node is None: | ||||
ui.warn( | ui.warn( | ||||
_(b'note: graft of %d:%s created no changes to commit\n') | _(b'note: graft of %d:%s created no changes to commit\n') | ||||
% (ctx.rev(), ctx) | % (ctx.rev(), ctx) | ||||
) | ) | ||||
# checking that newnodes exist because old state files won't have it | # checking that newnodes exist because old state files won't have it | ||||
elif statedata.get(b'newnodes') is not None: | elif statedata.get(b'newnodes') is not None: | ||||
nn = statedata[b'newnodes'] # type: List[bytes] | nn = statedata[b'newnodes'] # type: List[bytes] | ||||
nn.append(node) | nn.append(node) | ||||
# remove state when we complete successfully | # remove state when we complete successfully | ||||
if not opts.get(b'dry_run'): | if not opts.get('dry_run'): | ||||
graftstate.delete() | graftstate.delete() | ||||
return 0 | return 0 | ||||
def _stopgraft(ui, repo, graftstate): | def _stopgraft(ui, repo, graftstate): | ||||
"""stop the interrupted graft""" | """stop the interrupted graft""" | ||||
if not graftstate.exists(): | if not graftstate.exists(): |