403 rev = node.bin(rulehash) |
403 rev = node.bin(rulehash) |
404 except TypeError: |
404 except TypeError: |
405 raise error.ParseError("invalid changeset %s" % rulehash) |
405 raise error.ParseError("invalid changeset %s" % rulehash) |
406 return cls(state, rev) |
406 return cls(state, rev) |
407 |
407 |
408 def verify(self, prev): |
408 def verify(self, prev, expected, seen): |
409 """ Verifies semantic correctness of the rule""" |
409 """ Verifies semantic correctness of the rule""" |
410 repo = self.repo |
410 repo = self.repo |
411 ha = node.hex(self.node) |
411 ha = node.hex(self.node) |
412 try: |
412 try: |
413 self.node = repo[ha].node() |
413 self.node = repo[ha].node() |
414 except error.RepoError: |
414 except error.RepoError: |
415 raise error.ParseError(_('unknown changeset %s listed') |
415 raise error.ParseError(_('unknown changeset %s listed') |
416 % ha[:12]) |
416 % ha[:12]) |
|
417 for constraint in self.constraints: |
|
418 if constraint not in _constraints.known(): |
|
419 raise error.ParseError(_('unknown constraint "%s"') % |
|
420 constraint) |
|
421 |
|
422 if self.node is not None: |
|
423 constrs = self.constraints |
|
424 if _constraints.noother in constrs and self.node not in expected: |
|
425 raise error.ParseError( |
|
426 _('%s "%s" changeset was not a candidate') |
|
427 % (self.verb, node.short(self.node)), |
|
428 hint=_('only use listed changesets')) |
|
429 if _constraints.forceother in constrs and self.node in expected: |
|
430 raise error.ParseError( |
|
431 _('%s "%s" changeset was not an edited list candidate') |
|
432 % (self.verb, node.short(self.node)), |
|
433 hint=_('only use listed changesets')) |
|
434 if _constraints.noduplicates in constrs and self.node in seen: |
|
435 raise error.ParseError(_( |
|
436 'duplicated command for changeset %s') % |
|
437 node.short(self.node)) |
417 |
438 |
418 def torule(self): |
439 def torule(self): |
419 """build a histedit rule line for an action |
440 """build a histedit rule line for an action |
420 |
441 |
421 by default lines are in the form: |
442 by default lines are in the form: |
659 return cmdutil.getcommiteditor(edit=True, editform='histedit.edit') |
680 return cmdutil.getcommiteditor(edit=True, editform='histedit.edit') |
660 |
681 |
661 @action(['fold', 'f'], |
682 @action(['fold', 'f'], |
662 _('use commit, but combine it with the one above')) |
683 _('use commit, but combine it with the one above')) |
663 class fold(histeditaction): |
684 class fold(histeditaction): |
664 def verify(self, prev): |
685 def verify(self, prev, expected, seen): |
665 """ Verifies semantic correctness of the fold rule""" |
686 """ Verifies semantic correctness of the fold rule""" |
666 super(fold, self).verify(prev) |
687 super(fold, self).verify(prev, expected, seen) |
667 repo = self.repo |
688 repo = self.repo |
668 if not prev: |
689 if not prev: |
669 c = repo[self.node].parents()[0] |
690 c = repo[self.node].parents()[0] |
670 elif not prev.verb in ('pick', 'base'): |
691 elif not prev.verb in ('pick', 'base'): |
671 return |
692 return |
1375 """ |
1396 """ |
1376 expected = set(c.node() for c in ctxs) |
1397 expected = set(c.node() for c in ctxs) |
1377 seen = set() |
1398 seen = set() |
1378 prev = None |
1399 prev = None |
1379 for action in actions: |
1400 for action in actions: |
1380 action.verify(prev) |
1401 action.verify(prev, expected, seen) |
1381 prev = action |
1402 prev = action |
1382 constrs = action.constraints |
|
1383 for constraint in constrs: |
|
1384 if constraint not in _constraints.known(): |
|
1385 raise error.ParseError(_('unknown constraint "%s"') % |
|
1386 constraint) |
|
1387 |
|
1388 if action.node is not None: |
1403 if action.node is not None: |
1389 if _constraints.noother in constrs and action.node not in expected: |
|
1390 raise error.ParseError( |
|
1391 _('%s "%s" changeset was not a candidate') |
|
1392 % (action.verb, node.short(action.node)), |
|
1393 hint=_('only use listed changesets')) |
|
1394 if _constraints.forceother in constrs and action.node in expected: |
|
1395 raise error.ParseError( |
|
1396 _('%s "%s" changeset was not an edited list candidate') |
|
1397 % (action.verb, node.short(action.node)), |
|
1398 hint=_('only use listed changesets')) |
|
1399 if _constraints.noduplicates in constrs and action.node in seen: |
|
1400 raise error.ParseError(_( |
|
1401 'duplicated command for changeset %s') % |
|
1402 node.short(action.node)) |
|
1403 seen.add(action.node) |
1404 seen.add(action.node) |
1404 missing = sorted(expected - seen) # sort to stabilize output |
1405 missing = sorted(expected - seen) # sort to stabilize output |
1405 |
1406 |
1406 if state.repo.ui.configbool('histedit', 'dropmissing'): |
1407 if state.repo.ui.configbool('histedit', 'dropmissing'): |
1407 if len(actions) == 0: |
1408 if len(actions) == 0: |