def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None, keepbranches=False): '''Commit the wd changes with parents p1 and p2. Reuse commit info from rev but also store useful information in extra. Return node of committed revision.''' dsguard = cmdutil.dirstateguard(repo, 'rebase') try: repo.setparents(repo[p1].node(), repo[p2].node()) ctx = repo[rev] if commitmsg is None: commitmsg = ctx.description() keepbranch = keepbranches and repo[p1].branch() != ctx.branch() extra = {'rebase_source': ctx.hex()} if extrafn: extrafn(ctx, extra) backup = repo.ui.backupconfig('phases', 'new-commit') try: targetphase = max(ctx.phase(), phases.draft) repo.ui.setconfig('phases', 'new-commit', targetphase, 'rebase') if keepbranch: repo.ui.setconfig('ui', 'allowemptycommit', True) # Commit might fail if unresolved files exist newnode = repo.commit(text=commitmsg, user=ctx.user(), date=ctx.date(), extra=extra, editor=editor) finally: repo.ui.restoreconfig(backup) repo.dirstate.setbranch(repo[newnode].branch()) dsguard.close() return newnode finally: release(dsguard)
def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None): """Commit the wd changes with parents p1 and p2. Reuse commit info from rev but also store useful information in extra. Return node of committed revision.""" dsguard = cmdutil.dirstateguard(repo, "rebase") try: repo.setparents(repo[p1].node(), repo[p2].node()) ctx = repo[rev] if commitmsg is None: commitmsg = ctx.description() extra = {"rebase_source": ctx.hex()} if extrafn: extrafn(ctx, extra) backup = repo.ui.backupconfig("phases", "new-commit") try: targetphase = max(ctx.phase(), phases.draft) repo.ui.setconfig("phases", "new-commit", targetphase, "rebase") # Commit might fail if unresolved files exist newnode = repo.commit(text=commitmsg, user=ctx.user(), date=ctx.date(), extra=extra, editor=editor) finally: repo.ui.restoreconfig(backup) repo.dirstate.setbranch(repo[newnode].branch()) dsguard.close() return newnode finally: release(dsguard)
def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None): '''Commit the wd changes with parents p1 and p2. Reuse commit info from rev but also store useful information in extra. Return node of committed revision.''' dsguard = cmdutil.dirstateguard(repo, 'rebase') try: repo.setparents(repo[p1].node(), repo[p2].node()) ctx = repo[rev] if commitmsg is None: commitmsg = ctx.description() extra = {'rebase_source': ctx.hex()} if extrafn: extrafn(ctx, extra) backup = repo.ui.backupconfig('phases', 'new-commit') try: targetphase = max(ctx.phase(), phases.draft) repo.ui.setconfig('phases', 'new-commit', targetphase, 'rebase') # Commit might fail if unresolved files exist newnode = repo.commit(text=commitmsg, user=ctx.user(), date=ctx.date(), extra=extra, editor=editor) finally: repo.ui.restoreconfig(backup) repo.dirstate.setbranch(repo[newnode].branch()) dsguard.close() return newnode finally: release(dsguard)
def apply(self, repo, source, revmap, merges, opts={}): '''apply the revisions in revmap one by one in revision order''' revs = sorted(revmap) p1, p2 = repo.dirstate.parents() pulls = [] diffopts = patch.difffeatureopts(self.ui, opts) diffopts.git = True lock = wlock = tr = dsguard = None try: wlock = repo.wlock() dsguard = cmdutil.dirstateguard(repo, 'transplant') lock = repo.lock() tr = repo.transaction('transplant') for rev in revs: node = revmap[rev] revstr = '%s:%s' % (rev, short(node)) if self.applied(repo, node, p1): self.ui.warn(_('skipping already applied revision %s\n') % revstr) continue parents = source.changelog.parents(node) if not (opts.get('filter') or opts.get('log')): # If the changeset parent is the same as the # wdir's parent, just pull it. if parents[0] == p1: pulls.append(node) p1 = node continue if pulls: if source != repo: exchange.pull(repo, source.peer(), heads=pulls) merge.update(repo, pulls[-1], False, False, None) p1, p2 = repo.dirstate.parents() pulls = [] domerge = False if node in merges: # pulling all the merge revs at once would mean we # couldn't transplant after the latest even if # transplants before them fail. domerge = True if not hasnode(repo, node): exchange.pull(repo, source.peer(), heads=[node]) skipmerge = False if parents[1] != revlog.nullid: if not opts.get('parent'): self.ui.note(_('skipping merge changeset %s:%s\n') % (rev, short(node))) skipmerge = True else: parent = source.lookup(opts['parent']) if parent not in parents: raise util.Abort(_('%s is not a parent of %s') % (short(parent), short(node))) else: parent = parents[0] if skipmerge: patchfile = None else: fd, patchfile = tempfile.mkstemp(prefix='hg-transplant-') fp = os.fdopen(fd, 'w') gen = patch.diff(source, parent, node, opts=diffopts) for chunk in gen: fp.write(chunk) fp.close() del revmap[rev] if patchfile or domerge: try: try: n = self.applyone(repo, node, source.changelog.read(node), patchfile, merge=domerge, log=opts.get('log'), filter=opts.get('filter')) except TransplantError: # Do not rollback, it is up to the user to # fix the merge or cancel everything tr.close() dsguard.close() raise if n and domerge: self.ui.status(_('%s merged at %s\n') % (revstr, short(n))) elif n: self.ui.status(_('%s transplanted to %s\n') % (short(node), short(n))) finally: if patchfile: os.unlink(patchfile) tr.close() dsguard.close() if pulls: exchange.pull(repo, source.peer(), heads=pulls) merge.update(repo, pulls[-1], False, False, None) finally: self.saveseries(revmap, merges) self.transplants.write() if tr: tr.release() if lock: lock.release() if dsguard: dsguard.release() wlock.release()
def apply(self, repo, source, revmap, merges, opts={}): '''apply the revisions in revmap one by one in revision order''' revs = sorted(revmap) p1, p2 = repo.dirstate.parents() pulls = [] diffopts = patch.difffeatureopts(self.ui, opts) diffopts.git = True lock = wlock = tr = dsguard = None try: wlock = repo.wlock() dsguard = cmdutil.dirstateguard(repo, 'transplant') lock = repo.lock() tr = repo.transaction('transplant') for rev in revs: node = revmap[rev] revstr = '%s:%s' % (rev, short(node)) if self.applied(repo, node, p1): self.ui.warn( _('skipping already applied revision %s\n') % revstr) continue parents = source.changelog.parents(node) if not (opts.get('filter') or opts.get('log')): # If the changeset parent is the same as the # wdir's parent, just pull it. if parents[0] == p1: pulls.append(node) p1 = node continue if pulls: if source != repo: exchange.pull(repo, source.peer(), heads=pulls) merge.update(repo, pulls[-1], False, False, None) p1, p2 = repo.dirstate.parents() pulls = [] domerge = False if node in merges: # pulling all the merge revs at once would mean we # couldn't transplant after the latest even if # transplants before them fail. domerge = True if not hasnode(repo, node): exchange.pull(repo, source.peer(), heads=[node]) skipmerge = False if parents[1] != revlog.nullid: if not opts.get('parent'): self.ui.note( _('skipping merge changeset %s:%s\n') % (rev, short(node))) skipmerge = True else: parent = source.lookup(opts['parent']) if parent not in parents: raise util.Abort( _('%s is not a parent of %s') % (short(parent), short(node))) else: parent = parents[0] if skipmerge: patchfile = None else: fd, patchfile = tempfile.mkstemp(prefix='hg-transplant-') fp = os.fdopen(fd, 'w') gen = patch.diff(source, parent, node, opts=diffopts) for chunk in gen: fp.write(chunk) fp.close() del revmap[rev] if patchfile or domerge: try: try: n = self.applyone(repo, node, source.changelog.read(node), patchfile, merge=domerge, log=opts.get('log'), filter=opts.get('filter')) except TransplantError: # Do not rollback, it is up to the user to # fix the merge or cancel everything tr.close() dsguard.close() raise if n and domerge: self.ui.status( _('%s merged at %s\n') % (revstr, short(n))) elif n: self.ui.status( _('%s transplanted to %s\n') % (short(node), short(n))) finally: if patchfile: os.unlink(patchfile) tr.close() dsguard.close() if pulls: exchange.pull(repo, source.peer(), heads=pulls) merge.update(repo, pulls[-1], False, False, None) finally: self.saveseries(revmap, merges) self.transplants.write() if tr: tr.release() if lock: lock.release() if dsguard: dsguard.release() wlock.release()