mercurial/commands.py
changeset 21979 c2863cfe8a8a
parent 21959 dccbf52ffe9f
child 21980 f4e5753745e9
equal deleted inserted replaced
21978:c21c1c8c2017 21979:c2863cfe8a8a
  3052     'graft',
  3052     'graft',
  3053     [('r', 'rev', [], _('revisions to graft'), _('REV')),
  3053     [('r', 'rev', [], _('revisions to graft'), _('REV')),
  3054      ('c', 'continue', False, _('resume interrupted graft')),
  3054      ('c', 'continue', False, _('resume interrupted graft')),
  3055      ('e', 'edit', False, _('invoke editor on commit messages')),
  3055      ('e', 'edit', False, _('invoke editor on commit messages')),
  3056      ('', 'log', None, _('append graft info to log message')),
  3056      ('', 'log', None, _('append graft info to log message')),
       
  3057      ('f', 'force', False, _('force graft')),
  3057      ('D', 'currentdate', False,
  3058      ('D', 'currentdate', False,
  3058       _('record the current date as commit date')),
  3059       _('record the current date as commit date')),
  3059      ('U', 'currentuser', False,
  3060      ('U', 'currentuser', False,
  3060       _('record the current user as committer'), _('DATE'))]
  3061       _('record the current user as committer'), _('DATE'))]
  3061     + commitopts2 + mergetoolopts  + dryrunopts,
  3062     + commitopts2 + mergetoolopts  + dryrunopts,
  3074 
  3075 
  3075     If --log is specified, log messages will have a comment appended
  3076     If --log is specified, log messages will have a comment appended
  3076     of the form::
  3077     of the form::
  3077 
  3078 
  3078       (grafted from CHANGESETHASH)
  3079       (grafted from CHANGESETHASH)
       
  3080 
       
  3081     If --force is specified, revisions will be grafted even if they
       
  3082     are already ancestors of or have been grafted to the destination.
       
  3083     This is useful when the revisions have since been backed out.
  3079 
  3084 
  3080     If a graft merge results in conflicts, the graft process is
  3085     If a graft merge results in conflicts, the graft process is
  3081     interrupted so that the current merge can be manually resolved.
  3086     interrupted so that the current merge can be manually resolved.
  3082     Once all conflicts are addressed, the graft process can be
  3087     Once all conflicts are addressed, the graft process can be
  3083     continued with the -c/--continue option.
  3088     continued with the -c/--continue option.
  3149         revs.remove(rev)
  3154         revs.remove(rev)
  3150     if not revs:
  3155     if not revs:
  3151         return -1
  3156         return -1
  3152 
  3157 
  3153     # check for ancestors of dest branch
  3158     # check for ancestors of dest branch
  3154     crev = repo['.'].rev()
  3159     if not opts.get('force'):
  3155     ancestors = repo.changelog.ancestors([crev], inclusive=True)
  3160         crev = repo['.'].rev()
  3156     # Cannot use x.remove(y) on smart set, this has to be a list.
  3161         ancestors = repo.changelog.ancestors([crev], inclusive=True)
  3157     # XXX make this lazy in the future
  3162         # Cannot use x.remove(y) on smart set, this has to be a list.
  3158     revs = list(revs)
  3163         # XXX make this lazy in the future
  3159     # don't mutate while iterating, create a copy
  3164         revs = list(revs)
  3160     for rev in list(revs):
  3165         # don't mutate while iterating, create a copy
  3161         if rev in ancestors:
  3166         for rev in list(revs):
  3162             ui.warn(_('skipping ancestor revision %s\n') % rev)
  3167             if rev in ancestors:
  3163             # XXX remove on list is slow
  3168                 ui.warn(_('skipping ancestor revision %s\n') % rev)
  3164             revs.remove(rev)
  3169                 # XXX remove on list is slow
  3165     if not revs:
  3170                 revs.remove(rev)
  3166         return -1
  3171         if not revs:
  3167 
  3172             return -1
  3168     # analyze revs for earlier grafts
  3173 
  3169     ids = {}
  3174         # analyze revs for earlier grafts
  3170     for ctx in repo.set("%ld", revs):
  3175         ids = {}
  3171         ids[ctx.hex()] = ctx.rev()
  3176         for ctx in repo.set("%ld", revs):
  3172         n = ctx.extra().get('source')
  3177             ids[ctx.hex()] = ctx.rev()
  3173         if n:
  3178             n = ctx.extra().get('source')
  3174             ids[n] = ctx.rev()
  3179             if n:
  3175 
  3180                 ids[n] = ctx.rev()
  3176     # check ancestors for earlier grafts
  3181 
  3177     ui.debug('scanning for duplicate grafts\n')
  3182         # check ancestors for earlier grafts
  3178 
  3183         ui.debug('scanning for duplicate grafts\n')
  3179     for rev in repo.changelog.findmissingrevs(revs, [crev]):
  3184 
  3180         ctx = repo[rev]
  3185         for rev in repo.changelog.findmissingrevs(revs, [crev]):
  3181         n = ctx.extra().get('source')
  3186             ctx = repo[rev]
  3182         if n in ids:
  3187             n = ctx.extra().get('source')
  3183             r = repo[n].rev()
  3188             if n in ids:
  3184             if r in revs:
  3189                 r = repo[n].rev()
  3185                 ui.warn(_('skipping revision %s (already grafted to %s)\n')
  3190                 if r in revs:
  3186                         % (r, rev))
  3191                     ui.warn(_('skipping revision %s (already grafted to %s)\n')
       
  3192                             % (r, rev))
       
  3193                     revs.remove(r)
       
  3194                 elif ids[n] in revs:
       
  3195                     ui.warn(_('skipping already grafted revision %s '
       
  3196                                 '(%s also has origin %d)\n') % (ids[n], rev, r))
       
  3197                     revs.remove(ids[n])
       
  3198             elif ctx.hex() in ids:
       
  3199                 r = ids[ctx.hex()]
       
  3200                 ui.warn(_('skipping already grafted revision %s '
       
  3201                                 '(was grafted from %d)\n') % (r, rev))
  3187                 revs.remove(r)
  3202                 revs.remove(r)
  3188             elif ids[n] in revs:
  3203         if not revs:
  3189                 ui.warn(_('skipping already grafted revision %s '
  3204             return -1
  3190                             '(%s also has origin %d)\n') % (ids[n], rev, r))
       
  3191                 revs.remove(ids[n])
       
  3192         elif ctx.hex() in ids:
       
  3193             r = ids[ctx.hex()]
       
  3194             ui.warn(_('skipping already grafted revision %s '
       
  3195                             '(was grafted from %d)\n') % (r, rev))
       
  3196             revs.remove(r)
       
  3197     if not revs:
       
  3198         return -1
       
  3199 
  3205 
  3200     wlock = repo.wlock()
  3206     wlock = repo.wlock()
  3201     try:
  3207     try:
  3202         current = repo['.']
  3208         current = repo['.']
  3203         for pos, ctx in enumerate(repo.set("%ld", revs)):
  3209         for pos, ctx in enumerate(repo.set("%ld", revs)):