def metarewrite(repo, old, newbases, commitopts, copypreds=None): """Return (nodeid, created) where nodeid is the identifier of the changeset generated by the rewrite process, and created is True if nodeid was actually created. If created is False, nodeid references a changeset existing before the rewrite call. """ wlock = lock = tr = None try: wlock = repo.wlock() lock = repo.lock() tr = repo.transaction("rewrite") updatebookmarks = bookmarksupdater(repo, old.node()) message = cmdutil.logmessage(repo, commitopts) if not message: message = old.description() user = commitopts.get("user") or old.user() date = commitopts.get("date") or None # old.date() extra = dict(commitopts.get("extra", old.extra())) extra["branch"] = old.branch() preds = [old.node()] mutop = "metaedit" if copypreds: preds.extend(copypreds) mutop = "metaedit-copy" mutinfo = mutation.record(repo, extra, preds, mutop) loginfo = {"predecessors": old.hex(), "mutation": mutop} new = context.metadataonlyctx( repo, old, parents=newbases, text=message, user=user, date=date, extra=extra, loginfo=loginfo, mutinfo=mutinfo, ) if commitopts.get("edit"): new._text = cmdutil.commitforceeditor(repo, new, []) revcount = len(repo) newid = repo.commitctx(new) new = repo[newid] created = len(repo) != revcount updatebookmarks(newid) tr.close() return newid, created finally: lockmod.release(tr, lock, wlock)
def rewrite(repo, old, updates, head, newbases, commitopts, mutop=None): """Return (nodeid, created) where nodeid is the identifier of the changeset generated by the rewrite process, and created is True if nodeid was actually created. If created is False, nodeid references a changeset existing before the rewrite call. """ wlock = lock = tr = None try: wlock = repo.wlock() lock = repo.lock() tr = repo.transaction("rewrite") if len(old.parents()) > 1: # XXX remove this unnecessary limitation. raise error.Abort(_("cannot amend merge changesets")) base = old.p1() updatebookmarks = bookmarksupdater(repo, [old.node()] + [u.node() for u in updates]) # commit a new version of the old changeset, including the update # collect all files which might be affected files = set(old.files()) for u in updates: files.update(u.files()) # Recompute copies (avoid recording a -> b -> a) copied = copies.pathcopies(base, head) # prune files which were reverted by the updates def samefile(f): if f in head.manifest(): a = head.filectx(f) if f in base.manifest(): b = base.filectx(f) return a.data() == b.data() and a.flags() == b.flags() else: return False else: return f not in base.manifest() files = [f for f in files if not samefile(f)] # commit version of these files as defined by head headmf = head.manifest() def filectxfn(repo, ctx, path): if path in headmf: fctx = head[path] flags = fctx.flags() mctx = context.memfilectx( repo, ctx, fctx.path(), fctx.data(), islink="l" in flags, isexec="x" in flags, copied=copied.get(path), ) return mctx return None message = cmdutil.logmessage(repo, commitopts) if not message: message = old.description() user = commitopts.get("user") or old.user() # TODO: In case not date is given, we should take the old commit date # if we are working one one changeset or mimic the fold behavior about # date date = commitopts.get("date") or None extra = dict(commitopts.get("extra", old.extra())) extra["branch"] = head.branch() mutation.record(repo, extra, [c.node() for c in updates], mutop) loginfo = { "predecessors": " ".join(c.hex() for c in updates), "mutation": mutop, } new = context.memctx( repo, parents=newbases, text=message, files=files, filectxfn=filectxfn, user=user, date=date, extra=extra, loginfo=loginfo, ) if commitopts.get("edit"): new._text = cmdutil.commitforceeditor(repo, new, []) revcount = len(repo) newid = repo.commitctx(new) new = repo[newid] created = len(repo) != revcount updatebookmarks(newid) tr.close() return newid, created finally: lockmod.release(tr, lock, wlock)