comparison mercurial/localrepo.py @ 11211:e43c23d189a5

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@edlund.dk> Sune Foldager <cryo@cyanite.org>
author Sune Foldager <cryo@cyanite.org>
date Fri, 21 May 2010 15:22:29 +0200
parents 6a64813276ed
children 5cdac5c35e68
comparison
equal deleted inserted replaced
11210:0c0088881562 11211:e43c23d189a5
1505 cg = remote.changegroupsubset(fetch, heads, 'pull') 1505 cg = remote.changegroupsubset(fetch, heads, 'pull')
1506 return self.addchangegroup(cg, 'pull', remote.url()) 1506 return self.addchangegroup(cg, 'pull', remote.url())
1507 finally: 1507 finally:
1508 lock.release() 1508 lock.release()
1509 1509
1510 def push(self, remote, force=False, revs=None): 1510 def push(self, remote, force=False, revs=None, newbranch=False):
1511 '''Push outgoing changesets (limited by revs) from the current 1511 '''Push outgoing changesets (limited by revs) from the current
1512 repository to remote. Return an integer: 1512 repository to remote. Return an integer:
1513 - 0 means HTTP error *or* nothing to push 1513 - 0 means HTTP error *or* nothing to push
1514 - 1 means we pushed and remote head count is unchanged *or* 1514 - 1 means we pushed and remote head count is unchanged *or*
1515 we have outgoing changesets but refused to push 1515 we have outgoing changesets but refused to push
1522 # 1522 #
1523 # unbundle assumes local user cannot lock remote repo (new ssh 1523 # unbundle assumes local user cannot lock remote repo (new ssh
1524 # servers, http servers). 1524 # servers, http servers).
1525 1525
1526 if remote.capable('unbundle'): 1526 if remote.capable('unbundle'):
1527 return self.push_unbundle(remote, force, revs) 1527 return self.push_unbundle(remote, force, revs, newbranch)
1528 return self.push_addchangegroup(remote, force, revs) 1528 return self.push_addchangegroup(remote, force, revs, newbranch)
1529 1529
1530 def prepush(self, remote, force, revs): 1530 def prepush(self, remote, force, revs, newbranch):
1531 '''Analyze the local and remote repositories and determine which 1531 '''Analyze the local and remote repositories and determine which
1532 changesets need to be pushed to the remote. Return value depends 1532 changesets need to be pushed to the remote. Return value depends
1533 on circumstances: 1533 on circumstances:
1534 1534
1535 If we are not going to push anything, return a tuple (None, 1535 If we are not going to push anything, return a tuple (None,
1584 branches = set(self[n].branch() for n in outg) 1584 branches = set(self[n].branch() for n in outg)
1585 1585
1586 # 2. Check for new branches on the remote. 1586 # 2. Check for new branches on the remote.
1587 remotemap = remote.branchmap() 1587 remotemap = remote.branchmap()
1588 newbranches = branches - set(remotemap) 1588 newbranches = branches - set(remotemap)
1589 if newbranches: # new branch requires --force 1589 if newbranches and not newbranch: # new branch requires --new-branch
1590 branchnames = ', '.join("%s" % b for b in newbranches) 1590 branchnames = ', '.join("%s" % b for b in newbranches)
1591 self.ui.warn(_("abort: push creates " 1591 self.ui.warn(_("abort: push creates "
1592 "new remote branches: %s!\n") 1592 "new remote branches: %s!\n")
1593 % branchnames) 1593 % branchnames)
1594 self.ui.status(_("(use 'hg push -f' to force)\n")) 1594 self.ui.status(_("(use 'hg push --new-branch' to create new "
1595 "remote branches)\n"))
1595 return None, 0 1596 return None, 0
1597 branches.difference_update(newbranches)
1596 1598
1597 # 3. Construct the initial oldmap and newmap dicts. 1599 # 3. Construct the initial oldmap and newmap dicts.
1598 # They contain information about the remote heads before and 1600 # They contain information about the remote heads before and
1599 # after the push, respectively. 1601 # after the push, respectively.
1600 # Heads not found locally are not included in either dict, 1602 # Heads not found locally are not included in either dict,
1652 cg = self._changegroup(nodes, 'push') 1654 cg = self._changegroup(nodes, 'push')
1653 else: 1655 else:
1654 cg = self.changegroupsubset(update, revs, 'push') 1656 cg = self.changegroupsubset(update, revs, 'push')
1655 return cg, remote_heads 1657 return cg, remote_heads
1656 1658
1657 def push_addchangegroup(self, remote, force, revs): 1659 def push_addchangegroup(self, remote, force, revs, newbranch):
1658 '''Push a changegroup by locking the remote and sending the 1660 '''Push a changegroup by locking the remote and sending the
1659 addchangegroup command to it. Used for local and old SSH repos. 1661 addchangegroup command to it. Used for local and old SSH repos.
1660 Return an integer: see push(). 1662 Return an integer: see push().
1661 ''' 1663 '''
1662 lock = remote.lock() 1664 lock = remote.lock()
1663 try: 1665 try:
1664 ret = self.prepush(remote, force, revs) 1666 ret = self.prepush(remote, force, revs, newbranch)
1665 if ret[0] is not None: 1667 if ret[0] is not None:
1666 cg, remote_heads = ret 1668 cg, remote_heads = ret
1667 # here, we return an integer indicating remote head count change 1669 # here, we return an integer indicating remote head count change
1668 return remote.addchangegroup(cg, 'push', self.url()) 1670 return remote.addchangegroup(cg, 'push', self.url())
1669 # and here we return 0 for "nothing to push" or 1 for 1671 # and here we return 0 for "nothing to push" or 1 for
1670 # "something to push but I refuse" 1672 # "something to push but I refuse"
1671 return ret[1] 1673 return ret[1]
1672 finally: 1674 finally:
1673 lock.release() 1675 lock.release()
1674 1676
1675 def push_unbundle(self, remote, force, revs): 1677 def push_unbundle(self, remote, force, revs, newbranch):
1676 '''Push a changegroup by unbundling it on the remote. Used for new 1678 '''Push a changegroup by unbundling it on the remote. Used for new
1677 SSH and HTTP repos. Return an integer: see push().''' 1679 SSH and HTTP repos. Return an integer: see push().'''
1678 # local repo finds heads on server, finds out what revs it 1680 # local repo finds heads on server, finds out what revs it
1679 # must push. once revs transferred, if server finds it has 1681 # must push. once revs transferred, if server finds it has
1680 # different heads (someone else won commit/push race), server 1682 # different heads (someone else won commit/push race), server
1681 # aborts. 1683 # aborts.
1682 1684
1683 ret = self.prepush(remote, force, revs) 1685 ret = self.prepush(remote, force, revs, newbranch)
1684 if ret[0] is not None: 1686 if ret[0] is not None:
1685 cg, remote_heads = ret 1687 cg, remote_heads = ret
1686 if force: 1688 if force:
1687 remote_heads = ['force'] 1689 remote_heads = ['force']
1688 # ssh: return remote's addchangegroup() 1690 # ssh: return remote's addchangegroup()