comparison hgext/histedit.py @ 19020:12c06686d371

histedit: move all arguments checks to the beginning of the command This changeset move all checks and raises related to arguments validation to the top of the file. This gathers all the logic in one place and clarifies the code doing actual work. This paves the way for splitting this gigantic function in separated functions. A `goal` variable is introduced in the process. It holds the action to be done by this invocation (new, continue or abort). An invalid invocation is found in the process (the new code is a bit stricter).
author Pierre-Yves David <pierre-yves.david@logilab.fr>
date Tue, 16 Apr 2013 21:17:13 +0200
parents 730614b9b352
children 26b41a902195
comparison
equal deleted inserted replaced
19019:53060cc1b601 19020:12c06686d371
426 ('o', 'outgoing', False, _('changesets not found in destination')), 426 ('o', 'outgoing', False, _('changesets not found in destination')),
427 ('f', 'force', False, 427 ('f', 'force', False,
428 _('force outgoing even for unrelated repositories')), 428 _('force outgoing even for unrelated repositories')),
429 ('r', 'rev', [], _('first revision to be edited'))], 429 ('r', 'rev', [], _('first revision to be edited'))],
430 _("[PARENT]")) 430 _("[PARENT]"))
431 def histedit(ui, repo, *parent, **opts): 431 def histedit(ui, repo, *freeargs, **opts):
432 """interactively edit changeset history 432 """interactively edit changeset history
433 """ 433 """
434 # TODO only abort if we try and histedit mq patches, not just 434 # TODO only abort if we try and histedit mq patches, not just
435 # blanket if mq patches are applied somewhere 435 # blanket if mq patches are applied somewhere
436 mq = getattr(repo, 'mq', None) 436 mq = getattr(repo, 'mq', None)
437 if mq and mq.applied: 437 if mq and mq.applied:
438 raise util.Abort(_('source has mq patches applied')) 438 raise util.Abort(_('source has mq patches applied'))
439 439
440 parent = list(parent) + opts.get('rev', []) 440 # basic argument incompatibility processing
441 outg = opts.get('outgoing')
442 cont = opts.get('continue')
443 abort = opts.get('abort')
444 force = opts.get('force')
445 rules = opts.get('commands', '')
446 revs = opts.get('rev', [])
447 goal = 'new' # This invocation goal, in new, continue, abort
448 if force and not outg:
449 raise util.Abort(_('--force only allowed with --outgoing'))
450 if cont:
451 if util.any((outg, abort, revs, freeargs, rules)):
452 raise util.Abort(_('no arguments allowed with --continue'))
453 goal = 'continue'
454 elif abort:
455 if util.any((outg, revs, freeargs, rules)):
456 raise util.Abort(_('no arguments allowed with --abort'))
457 goal = 'abort'
458 else:
459 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
460 raise util.Abort(_('history edit already in progress, try '
461 '--continue or --abort'))
462 if outg:
463 if revs:
464 raise util.Abort(_('no revisions allowed with --outgoing'))
465 if len(freeargs) > 1:
466 raise util.Abort(
467 _('only one repo argument allowed with --outgoing'))
468 else:
469 parent = list(freeargs) + opts.get('rev', [])
470 if len(parent) != 1:
471 raise util.Abort(
472 _('histedit requires exactly one parent revision'))
473
441 if opts.get('outgoing'): 474 if opts.get('outgoing'):
442 if len(parent) > 1: 475 if freeargs:
443 raise util.Abort( 476 parent = freeargs[0]
444 _('only one repo argument allowed with --outgoing'))
445 elif parent:
446 parent = parent[0]
447 477
448 dest = ui.expandpath(parent or 'default-push', parent or 'default') 478 dest = ui.expandpath(parent or 'default-push', parent or 'default')
449 dest, revs = hg.parseurl(dest, None)[:2] 479 dest, revs = hg.parseurl(dest, None)[:2]
450 ui.status(_('comparing with %s\n') % util.hidepassword(dest)) 480 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
451 481
458 # hexlify nodes from outgoing, because we're going to parse 488 # hexlify nodes from outgoing, because we're going to parse
459 # parent[0] using revsingle below, and if the binary hash 489 # parent[0] using revsingle below, and if the binary hash
460 # contains special revset characters like ":" the revset 490 # contains special revset characters like ":" the revset
461 # parser can choke. 491 # parser can choke.
462 parent = [node.hex(n) for n in discovery.findcommonoutgoing( 492 parent = [node.hex(n) for n in discovery.findcommonoutgoing(
463 repo, other, revs, force=opts.get('force')).missing[0:1]] 493 repo, other, revs, force=force).missing[0:1]]
464 else: 494 if not parent:
465 if opts.get('force'): 495 raise util.Abort(_('no outgoing ancestors'))
466 raise util.Abort(_('--force only allowed with --outgoing')) 496
467 497 if goal == 'continue':
468 if opts.get('continue', False):
469 if len(parent) != 0:
470 raise util.Abort(_('no arguments allowed with --continue'))
471 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo) 498 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
472 currentparent, wantnull = repo.dirstate.parents() 499 currentparent, wantnull = repo.dirstate.parents()
473 parentctx = repo[parentctxnode] 500 parentctx = repo[parentctxnode]
474 parentctx, repl = bootstrapcontinue(ui, repo, parentctx, rules, opts) 501 parentctx, repl = bootstrapcontinue(ui, repo, parentctx, rules, opts)
475 replacements.extend(repl) 502 replacements.extend(repl)
476 elif opts.get('abort', False): 503 elif goal == 'abort':
477 if len(parent) != 0:
478 raise util.Abort(_('no arguments allowed with --abort'))
479 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo) 504 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
480 mapping, tmpnodes, leafs, _ntm = processreplacement(repo, replacements) 505 mapping, tmpnodes, leafs, _ntm = processreplacement(repo, replacements)
481 ui.debug('restore wc to old parent %s\n' % node.short(topmost)) 506 ui.debug('restore wc to old parent %s\n' % node.short(topmost))
482 hg.clean(repo, topmost) 507 hg.clean(repo, topmost)
483 cleanupnode(ui, repo, 'created', tmpnodes) 508 cleanupnode(ui, repo, 'created', tmpnodes)
484 cleanupnode(ui, repo, 'temp', leafs) 509 cleanupnode(ui, repo, 'temp', leafs)
485 os.unlink(os.path.join(repo.path, 'histedit-state')) 510 os.unlink(os.path.join(repo.path, 'histedit-state'))
486 return 511 return
487 else: 512 else:
488 cmdutil.bailifchanged(repo) 513 cmdutil.bailifchanged(repo)
489 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
490 raise util.Abort(_('history edit already in progress, try '
491 '--continue or --abort'))
492 514
493 topmost, empty = repo.dirstate.parents() 515 topmost, empty = repo.dirstate.parents()
494 516
495 if len(parent) != 1:
496 raise util.Abort(_('histedit requires exactly one parent revision'))
497 parent = scmutil.revsingle(repo, parent[0]).node() 517 parent = scmutil.revsingle(repo, parent[0]).node()
498 518
499 keep = opts.get('keep', False) 519 keep = opts.get('keep', False)
500 revs = between(repo, parent, topmost, keep) 520 revs = between(repo, parent, topmost, keep)
501 if not revs: 521 if not revs:
502 raise util.Abort(_('%s is not an ancestor of working directory') % 522 raise util.Abort(_('%s is not an ancestor of working directory') %
503 node.short(parent)) 523 node.short(parent))
504 524
505 ctxs = [repo[r] for r in revs] 525 ctxs = [repo[r] for r in revs]
506 rules = opts.get('commands', '')
507 if not rules: 526 if not rules:
508 rules = '\n'.join([makedesc(c) for c in ctxs]) 527 rules = '\n'.join([makedesc(c) for c in ctxs])
509 rules += '\n\n' 528 rules += '\n\n'
510 rules += editcomment % (node.short(parent), node.short(topmost)) 529 rules += editcomment % (node.short(parent), node.short(topmost))
511 rules = ui.edit(rules, ui.username()) 530 rules = ui.edit(rules, ui.username())