hgext/fix.py
branchstable
changeset 44129 84a0102c05c7
parent 44048 61881b170140
parent 44092 833210fbd900
child 44271 c791ed6a2154
equal deleted inserted replaced
44048:61881b170140 44129:84a0102c05c7
   142     copies,
   142     copies,
   143     error,
   143     error,
   144     match as matchmod,
   144     match as matchmod,
   145     mdiff,
   145     mdiff,
   146     merge,
   146     merge,
   147     obsolete,
       
   148     pycompat,
   147     pycompat,
   149     registrar,
   148     registrar,
       
   149     rewriteutil,
   150     scmutil,
   150     scmutil,
   151     util,
   151     util,
   152     worker,
   152     worker,
   153 )
   153 )
   154 
   154 
   247     set of revisions being fixed is considered, so that fixes to earlier
   247     set of revisions being fixed is considered, so that fixes to earlier
   248     revisions are not forgotten in later ones. The --base flag can be used to
   248     revisions are not forgotten in later ones. The --base flag can be used to
   249     override this default behavior, though it is not usually desirable to do so.
   249     override this default behavior, though it is not usually desirable to do so.
   250     """
   250     """
   251     opts = pycompat.byteskwargs(opts)
   251     opts = pycompat.byteskwargs(opts)
       
   252     cmdutil.check_at_most_one_arg(opts, b'all', b'rev')
   252     if opts[b'all']:
   253     if opts[b'all']:
   253         if opts[b'rev']:
       
   254             raise error.Abort(_(b'cannot specify both "--rev" and "--all"'))
       
   255         opts[b'rev'] = [b'not public() and not obsolete()']
   254         opts[b'rev'] = [b'not public() and not obsolete()']
   256         opts[b'working_dir'] = True
   255         opts[b'working_dir'] = True
   257     with repo.wlock(), repo.lock(), repo.transaction(b'fix'):
   256     with repo.wlock(), repo.lock(), repo.transaction(b'fix'):
   258         revstofix = getrevstofix(ui, repo, opts)
   257         revstofix = getrevstofix(ui, repo, opts)
   259         basectxs = getbasectxs(repo, opts, revstofix)
   258         basectxs = getbasectxs(repo, opts, revstofix)
   402     revs = set(scmutil.revrange(repo, opts[b'rev']))
   401     revs = set(scmutil.revrange(repo, opts[b'rev']))
   403     for rev in revs:
   402     for rev in revs:
   404         checkfixablectx(ui, repo, repo[rev])
   403         checkfixablectx(ui, repo, repo[rev])
   405     if revs:
   404     if revs:
   406         cmdutil.checkunfinished(repo)
   405         cmdutil.checkunfinished(repo)
   407         checknodescendants(repo, revs)
   406         rewriteutil.precheck(repo, revs, b'fix')
   408     if opts.get(b'working_dir'):
   407     if opts.get(b'working_dir'):
   409         revs.add(wdirrev)
   408         revs.add(wdirrev)
   410         if list(merge.mergestate.read(repo).unresolved()):
   409         if list(merge.mergestate.read(repo).unresolved()):
   411             raise error.Abort(b'unresolved conflicts', hint=b"use 'hg resolve'")
   410             raise error.Abort(b'unresolved conflicts', hint=b"use 'hg resolve'")
   412     if not revs:
   411     if not revs:
   414             b'no changesets specified', hint=b'use --rev or --working-dir'
   413             b'no changesets specified', hint=b'use --rev or --working-dir'
   415         )
   414         )
   416     return revs
   415     return revs
   417 
   416 
   418 
   417 
   419 def checknodescendants(repo, revs):
       
   420     if not obsolete.isenabled(repo, obsolete.allowunstableopt) and repo.revs(
       
   421         b'(%ld::) - (%ld)', revs, revs
       
   422     ):
       
   423         raise error.Abort(
       
   424             _(b'can only fix a changeset together with all its descendants')
       
   425         )
       
   426 
       
   427 
       
   428 def checkfixablectx(ui, repo, ctx):
   418 def checkfixablectx(ui, repo, ctx):
   429     """Aborts if the revision shouldn't be replaced with a fixed one."""
   419     """Aborts if the revision shouldn't be replaced with a fixed one."""
   430     if not ctx.mutable():
       
   431         raise error.Abort(
       
   432             b'can\'t fix immutable changeset %s'
       
   433             % (scmutil.formatchangeid(ctx),)
       
   434         )
       
   435     if ctx.obsolete():
   420     if ctx.obsolete():
   436         # It would be better to actually check if the revision has a successor.
   421         # It would be better to actually check if the revision has a successor.
   437         allowdivergence = ui.configbool(
   422         allowdivergence = ui.configbool(
   438             b'experimental', b'evolution.allowdivergence'
   423             b'experimental', b'evolution.allowdivergence'
   439         )
   424         )
   679         if line:
   664         if line:
   680             ui.warn(b'[')
   665             ui.warn(b'[')
   681             if rev is None:
   666             if rev is None:
   682                 ui.warn(_(b'wdir'), label=b'evolve.rev')
   667                 ui.warn(_(b'wdir'), label=b'evolve.rev')
   683             else:
   668             else:
   684                 ui.warn((str(rev)), label=b'evolve.rev')
   669                 ui.warn(b'%d' % rev, label=b'evolve.rev')
   685             ui.warn(b'] %s: %s\n' % (fixername, line))
   670             ui.warn(b'] %s: %s\n' % (fixername, line))
   686 
   671 
   687 
   672 
   688 def writeworkingdir(repo, ctx, filedata, replacements):
   673 def writeworkingdir(repo, ctx, filedata, replacements):
   689     """Write new content to the working copy and check out the new p1 if any
   674     """Write new content to the working copy and check out the new p1 if any
   743         and p1ctx.node() not in replacements
   728         and p1ctx.node() not in replacements
   744         and p2ctx.node() not in replacements
   729         and p2ctx.node() not in replacements
   745     ):
   730     ):
   746         return
   731         return
   747 
   732 
   748     def filectxfn(repo, memctx, path):
   733     extra = ctx.extra().copy()
   749         if path not in ctx:
   734     extra[b'fix_source'] = ctx.hex()
   750             return None
   735 
       
   736     wctx = context.overlayworkingctx(repo)
       
   737     wctx.setbase(repo[newp1node])
       
   738     merge.update(
       
   739         repo,
       
   740         ctx.rev(),
       
   741         branchmerge=False,
       
   742         force=True,
       
   743         ancestor=p1rev,
       
   744         mergeancestor=False,
       
   745         wc=wctx,
       
   746     )
       
   747     copies.graftcopies(wctx, ctx, ctx.p1())
       
   748 
       
   749     for path in filedata.keys():
   751         fctx = ctx[path]
   750         fctx = ctx[path]
   752         copysource = fctx.copysource()
   751         copysource = fctx.copysource()
   753         return context.memfilectx(
   752         wctx.write(path, filedata[path], flags=fctx.flags())
   754             repo,
   753         if copysource:
   755             memctx,
   754             wctx.markcopied(path, copysource)
   756             path=fctx.path(),
   755 
   757             data=filedata.get(path, fctx.data()),
   756     memctx = wctx.tomemctx(
   758             islink=fctx.islink(),
   757         text=ctx.description(),
   759             isexec=fctx.isexec(),
   758         branch=ctx.branch(),
   760             copysource=copysource,
   759         extra=extra,
   761         )
   760         date=ctx.date(),
   762 
       
   763     extra = ctx.extra().copy()
       
   764     extra[b'fix_source'] = ctx.hex()
       
   765 
       
   766     memctx = context.memctx(
       
   767         repo,
       
   768         parents=(newp1node, newp2node),
   761         parents=(newp1node, newp2node),
   769         text=ctx.description(),
       
   770         files=set(ctx.files()) | set(filedata.keys()),
       
   771         filectxfn=filectxfn,
       
   772         user=ctx.user(),
   762         user=ctx.user(),
   773         date=ctx.date(),
       
   774         extra=extra,
       
   775         branch=ctx.branch(),
       
   776         editor=None,
       
   777     )
   763     )
       
   764 
   778     sucnode = memctx.commit()
   765     sucnode = memctx.commit()
   779     prenode = ctx.node()
   766     prenode = ctx.node()
   780     if prenode == sucnode:
   767     if prenode == sucnode:
   781         ui.debug(b'node %s already existed\n' % (ctx.hex()))
   768         ui.debug(b'node %s already existed\n' % (ctx.hex()))
   782     else:
   769     else: