[PATCH 1 of 1] push: add --new-branch option to allow intial push of new branches

Faheem Mitha faheem at email.unc.edu
Wed May 5 04:28:07 CDT 2010


Dear Everyone,

I'm following up to Sune's most excellent and undeservedly neglected
patch posting in the hope of reviving this discussion.

#mercurial gets queries from people every day asking whether they
really should be using --force. We got one just an hour ago. Can the
powers that be please advise what is blocking this patch, if
anything?

                                          Thanks and Regards, Faheem.

On Fri, 18 Sep 2009 13:12:11 +0200, Sune Foldager <cryo at cyanite.org> wrote:
> # HG changeset patch
> # User Sune Foldager <cryo at cyanite.org>
> # Date 1242062446 -7200
> # Node ID ead2e85a7793072c6a937e81c3310250e31ef4af
> # Parent  c564dbb2a6d5394c995c1ae93943a16253e7b1e5
> push: add --new-branch option to allow intial push of new branches
>
> Compare this to --force which allows anything to be pushed. With --new-branch,
> only changesets to named branches not present on the and changesets not
> introducing additional heads on existing branches are allowed.
>
> Developed by
>   Henrik Stuart <henrik.stuart at edlund.dk>
>   Sune Foldager <cryo at cyanite.org>
>
> diff --git a/hgext/mq.py b/hgext/mq.py
> --- a/hgext/mq.py
> +++ b/hgext/mq.py
> @@ -2470,10 +2470,10 @@
>              return super(mqrepo, self).commit(text, user, date, match, force,
>                                                editor, extra)
>  
> -        def push(self, remote, force=False, revs=None):
> +        def push(self, remote, force=False, revs=None, newbranch=False):
>              if self.mq.applied and not force and not revs:
>                  raise util.Abort(_('source has mq patches applied'))
> -            return super(mqrepo, self).push(remote, force, revs)
> +            return super(mqrepo, self).push(remote, force, revs, newbranch)
>  
>          def _findtags(self):
>              '''augment tags from base class with patch tags'''
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -2336,7 +2336,7 @@
>      for s in sorted(subs):
>          c.sub(s).push(opts.get('force'))
>  
> -    r = repo.push(other, opts.get('force'), revs=revs)
> +    r = repo.push(other, opts.get('force'), revs=revs, newbranch=opts.get('new_branch'))
>      return r == 0
>  
>  def recover(ui, repo):
> @@ -3452,6 +3452,7 @@
>           [('f', 'force', None, _('force push')),
>            ('r', 'rev', [],
>             _('a specific revision up to which you would like to push')),
> +          ('', 'new-branch', False, _('allows you to push a new branch')),
>           ] + remoteopts,
>           _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
>      "recover": (recover, []),
> diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
> --- a/mercurial/localrepo.py
> +++ b/mercurial/localrepo.py
> @@ -1443,7 +1443,7 @@
>          finally:
>              lock.release()
>  
> -    def push(self, remote, force=False, revs=None):
> +    def push(self, remote, force=False, revs=None, newbranch=False):
>          # there are two ways to push to remote repo:
>          #
>          # addchangegroup assumes local user can lock remote
> @@ -1453,10 +1453,10 @@
>          # servers, http servers).
>  
>          if remote.capable('unbundle'):
> -            return self.push_unbundle(remote, force, revs)
> -        return self.push_addchangegroup(remote, force, revs)
> +            return self.push_unbundle(remote, force, revs, newbranch)
> +        return self.push_addchangegroup(remote, force, revs, newbranch)
>  
> -    def prepush(self, remote, force, revs):
> +    def prepush(self, remote, force, revs, newbranch):
>          '''Analyze the local and remote repositories and determine which
>          changesets need to be pushed to the remote.  Return a tuple
>          (changegroup, remoteheads).  changegroup is a readable file-like
> @@ -1483,8 +1483,9 @@
>              updatelh: outgoing local branch heads
>              '''
>  
> +            if not rheads and newbranch:
> +                return True
>              warn = 0
> -
>              if not revs and len(lheads) > len(rheads):
>                  warn = 1
>              else:
> @@ -1507,15 +1508,14 @@
>                      warn = 1
>  
>              if warn:
> -                if not rheads: # new branch requires --force
> +                if not rheads: # new remote branch
>                      self.ui.warn(_("abort: push creates new"
>                                     " remote branch '%s'!\n") %
>                                     self[updatelh[0]].branch())
> +                    self.ui.status(_("(use push --new-branch to create new remote branch)\n"))
>                  else:
>                      self.ui.warn(_("abort: push creates new remote heads!\n"))
> -
> -                self.ui.status(_("(did you forget to merge?"
> -                                 " use push -f to force)\n"))
> +                    self.ui.status(_("(did you forget to merge? use push -f to force)\n"))
>                  return False
>              return True
>  
> @@ -1574,10 +1574,10 @@
>              cg = self.changegroupsubset(update, revs, 'push')
>          return cg, remote_heads
>  
> -    def push_addchangegroup(self, remote, force, revs):
> +    def push_addchangegroup(self, remote, force, revs, newbranch):
>          lock = remote.lock()
>          try:
> -            ret = self.prepush(remote, force, revs)
> +            ret = self.prepush(remote, force, revs, newbranch)
>              if ret[0] is not None:
>                  cg, remote_heads = ret
>                  return remote.addchangegroup(cg, 'push', self.url())
> @@ -1585,13 +1585,13 @@
>          finally:
>              lock.release()
>  
> -    def push_unbundle(self, remote, force, revs):
> +    def push_unbundle(self, remote, force, revs, newbranch):
>          # local repo finds heads on server, finds out what revs it
>          # must push.  once revs transferred, if server finds it has
>          # different heads (someone else won commit/push race), server
>          # aborts.
>  
> -        ret = self.prepush(remote, force, revs)
> +        ret = self.prepush(remote, force, revs, newbranch)
>          if ret[0] is not None:
>              cg, remote_heads = ret
>              if force: remote_heads = ['force']
> diff --git a/tests/test-debugcomplete.out b/tests/test-debugcomplete.out
> --- a/tests/test-debugcomplete.out
> +++ b/tests/test-debugcomplete.out
> @@ -174,7 +174,7 @@
>  merge: force, rev, preview
>  parents: rev, style, template
>  pull: update, force, rev, ssh, remotecmd
> -push: force, rev, ssh, remotecmd
> +push: force, rev, new-branch, ssh, remotecmd
>  remove: after, force, include, exclude
>  serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, webdir-conf, pid-file, stdio, templates, style, ipv6, certificate
>  status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, include, exclude
> diff --git a/tests/test-push-warn b/tests/test-push-warn
> --- a/tests/test-push-warn
> +++ b/tests/test-push-warn
> @@ -123,4 +123,16 @@
>  hg -q ci -d "1000000 0" -m 11
>  hg push -r 10 -r 11 ../f; echo $?
>  
> +echo % failed push of new named branch
> +echo 12 > foo
> +hg -q ci -d "1000000 0" -m 12a
> +hg -q up 11
> +echo 13 > foo
> +hg -q branch d
> +hg -q ci -d "1000000 0" -m 13d
> +hg push -r 12 -r 13 ../f; echo $?
> +
> +echo % using --new-branch to push new named branch
> +hg push --new-branch -r 12 -r 13 ../f; echo $?
> +
>  exit 0
> diff --git a/tests/test-push-warn.out b/tests/test-push-warn.out
> --- a/tests/test-push-warn.out
> +++ b/tests/test-push-warn.out
> @@ -85,7 +85,7 @@
>  pushing to ../f
>  searching for changes
>  abort: push creates new remote branch 'c'!
> -(did you forget to merge? use push -f to force)
> +(use push --new-branch to create new remote branch)
>  1
>  % fail on multiple head push
>  pushing to ../f
> @@ -124,3 +124,17 @@
>  adding file changes
>  added 2 changesets with 2 changes to 1 files
>  0
> +% failed push of new named branch
> +pushing to ../f
> +searching for changes
> +abort: push creates new remote branch 'd'!
> +(use push --new-branch to create new remote branch)
> +1
> +% using --new-branch to push new named branch
> +pushing to ../f
> +searching for changes
> +adding changesets
> +adding manifests
> +adding file changes
> +added 2 changesets with 2 changes to 1 files (+1 heads)
> +0



More information about the Mercurial-devel mailing list