Mercurial > hg
comparison mercurial/cmdutil.py @ 35745:3bd8ab4c80a5
branch: add a --rev flag to change branch name of given revisions
This patch adds a new --rev flag to hg branch which can be used to change branch
of revisions. This is motivated from topic extension where you can change topic
on revisions but this one has few restrictions which are:
1) You cannot change branch name in between the stack
2) You cannot change branch name and set it to an existing name
3) You cannot change branch of non-linear set of commits
4) You cannot change branch of merge commits.
Tests are added for the same.
.. feature::
An experimental flag `--rev` to `hg branch` which can be used to change
branch of changesets.
Differential Revision: https://phab.mercurial-scm.org/D1074
author | Pulkit Goyal <7895pulkit@gmail.com> |
---|---|
date | Sun, 15 Oct 2017 23:08:45 +0530 |
parents | 3c2a6246fd63 |
children | e5b6ba786d83 |
comparison
equal
deleted
inserted
replaced
35744:8685192a8733 | 35745:3bd8ab4c80a5 |
---|---|
40 pycompat, | 40 pycompat, |
41 registrar, | 41 registrar, |
42 revlog, | 42 revlog, |
43 revset, | 43 revset, |
44 revsetlang, | 44 revsetlang, |
45 rewriteutil, | |
45 scmutil, | 46 scmutil, |
46 smartset, | 47 smartset, |
47 templatekw, | 48 templatekw, |
48 templater, | 49 templater, |
49 util, | 50 util, |
710 | 711 |
711 if choice: | 712 if choice: |
712 return list(choice.values())[0] | 713 return list(choice.values())[0] |
713 | 714 |
714 raise error.UnknownCommand(cmd, allcmds) | 715 raise error.UnknownCommand(cmd, allcmds) |
716 | |
717 def changebranch(ui, repo, revs, label): | |
718 """ Change the branch name of given revs to label """ | |
719 | |
720 with repo.wlock(), repo.lock(), repo.transaction('branches'): | |
721 # abort in case of uncommitted merge or dirty wdir | |
722 bailifchanged(repo) | |
723 revs = scmutil.revrange(repo, revs) | |
724 if not revs: | |
725 raise error.Abort("empty revision set") | |
726 roots = repo.revs('roots(%ld)', revs) | |
727 if len(roots) > 1: | |
728 raise error.Abort(_("cannot change branch of non-linear revisions")) | |
729 rewriteutil.precheck(repo, revs, 'change branch of') | |
730 if repo.revs('merge() and %ld', revs): | |
731 raise error.Abort(_("cannot change branch of a merge commit")) | |
732 if repo.revs('obsolete() and %ld', revs): | |
733 raise error.Abort(_("cannot change branch of a obsolete changeset")) | |
734 | |
735 # make sure only topological heads | |
736 if repo.revs('heads(%ld) - head()', revs): | |
737 raise error.Abort(_("cannot change branch in middle of a stack")) | |
738 | |
739 replacements = {} | |
740 # avoid import cycle mercurial.cmdutil -> mercurial.context -> | |
741 # mercurial.subrepo -> mercurial.cmdutil | |
742 from . import context | |
743 for rev in revs: | |
744 ctx = repo[rev] | |
745 oldbranch = ctx.branch() | |
746 # check if ctx has same branch | |
747 if oldbranch == label: | |
748 continue | |
749 | |
750 def filectxfn(repo, newctx, path): | |
751 try: | |
752 return ctx[path] | |
753 except error.ManifestLookupError: | |
754 return None | |
755 | |
756 ui.debug("changing branch of '%s' from '%s' to '%s'\n" | |
757 % (hex(ctx.node()), oldbranch, label)) | |
758 extra = ctx.extra() | |
759 extra['branch_change'] = hex(ctx.node()) | |
760 # While changing branch of set of linear commits, make sure that | |
761 # we base our commits on new parent rather than old parent which | |
762 # was obsoleted while changing the branch | |
763 p1 = ctx.p1().node() | |
764 p2 = ctx.p2().node() | |
765 if p1 in replacements: | |
766 p1 = replacements[p1][0] | |
767 if p2 in replacements: | |
768 p2 = replacements[p2][0] | |
769 | |
770 mc = context.memctx(repo, (p1, p2), | |
771 ctx.description(), | |
772 ctx.files(), | |
773 filectxfn, | |
774 user=ctx.user(), | |
775 date=ctx.date(), | |
776 extra=extra, | |
777 branch=label) | |
778 | |
779 commitphase = ctx.phase() | |
780 overrides = {('phases', 'new-commit'): commitphase} | |
781 with repo.ui.configoverride(overrides, 'branch-change'): | |
782 newnode = repo.commitctx(mc) | |
783 | |
784 replacements[ctx.node()] = (newnode,) | |
785 ui.debug('new node id is %s\n' % hex(newnode)) | |
786 | |
787 # create obsmarkers and move bookmarks | |
788 scmutil.cleanupnodes(repo, replacements, 'branch-change') | |
789 | |
790 # move the working copy too | |
791 wctx = repo[None] | |
792 # in-progress merge is a bit too complex for now. | |
793 if len(wctx.parents()) == 1: | |
794 newid = replacements.get(wctx.p1().node()) | |
795 if newid is not None: | |
796 # avoid import cycle mercurial.cmdutil -> mercurial.hg -> | |
797 # mercurial.cmdutil | |
798 from . import hg | |
799 hg.update(repo, newid[0], quietempty=True) | |
800 | |
801 ui.status(_("changed branch on %d changesets\n") % len(replacements)) | |
715 | 802 |
716 def findrepo(p): | 803 def findrepo(p): |
717 while not os.path.isdir(os.path.join(p, ".hg")): | 804 while not os.path.isdir(os.path.join(p, ".hg")): |
718 oldp, p = p, os.path.dirname(p) | 805 oldp, p = p, os.path.dirname(p) |
719 if p == oldp: | 806 if p == oldp: |