Mercurial > hg
changeset 8564:6b9ec23b09fc
named branches: improve pre-push logic (issue736)
Each named branch is considered separately, and the push is allowed if
no new branch heads are created for any named branch to be pushed.
Due to some tests's use of --debug, their output will change after this
addition. This has been fixed as well.
Co-contributor: Henrik Stuart <henrik.stuart@edlund.dk>
author | Sune Foldager <cryo@cyanite.org> |
---|---|
date | Sat, 23 May 2009 17:04:31 +0200 |
parents | f8ff65a83169 |
children | 268d16b2ec25 |
files | mercurial/localrepo.py tests/test-acl.out |
diffstat | 2 files changed, 84 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/localrepo.py Sat May 23 17:03:51 2009 +0200 +++ b/mercurial/localrepo.py Sat May 23 17:04:31 2009 +0200 @@ -1429,42 +1429,97 @@ else: bases, heads = update, self.changelog.heads() + def checkbranch(lheads, rheads, updatelh): + ''' + check whether there are more local heads than remote heads on + a specific branch. + + lheads: local branch heads + rheads: remote branch heads + updatelh: outgoing local branch heads + ''' + + warn = 0 + + if not revs and len(lheads) > len(rheads): + warn = 1 + else: + updatelheads = [self.changelog.heads(x, lheads) + for x in updatelh] + newheads = set(sum(updatelheads, [])) & set(lheads) + + if not newheads: + return True + + for r in rheads: + if r in self.changelog.nodemap: + desc = self.changelog.heads(r, heads) + l = [h for h in heads if h in desc] + if not l: + newheads.add(r) + else: + newheads.add(r) + if len(newheads) > len(rheads): + warn = 1 + + if warn: + if not rheads: # new branch requires --force + self.ui.warn(_("abort: push creates new" + " remote branch '%s'!\n" % + self[updatelh[0]].branch())) + 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")) + return False + return True + if not bases: self.ui.status(_("no changes found\n")) return None, 1 elif not force: - # check if we're creating new remote heads - # to be a remote head after push, node must be either + # Check for each named branch if we're creating new remote heads. + # To be a remote head after push, node must be either: # - unknown locally # - a local outgoing head descended from update # - a remote head that's known locally and not # ancestral to an outgoing head + # + # New named branches cannot be created without --force. - warn = 0 + if remote_heads != [nullid]: + if remote.capable('branchmap'): + localhds = {} + if not revs: + localhds = self.branchmap() + else: + for n in heads: + branch = self[n].branch() + if branch in localhds: + localhds[branch].append(n) + else: + localhds[branch] = [n] + + remotehds = remote.branchmap() - if remote_heads == [nullid]: - warn = 0 - elif not revs and len(heads) > len(remote_heads): - warn = 1 - else: - newheads = list(heads) - for r in remote_heads: - if r in self.changelog.nodemap: - desc = self.changelog.heads(r, heads) - l = [h for h in heads if h in desc] - if not l: - newheads.append(r) - else: - newheads.append(r) - if len(newheads) > len(remote_heads): - warn = 1 + for lh in localhds: + if lh in remotehds: + rheads = remotehds[lh] + else: + rheads = [] + lheads = localhds[lh] + updatelh = [upd for upd in update + if self[upd].branch() == lh] + if not updatelh: + continue + if not checkbranch(lheads, rheads, updatelh): + return None, 0 + else: + if not checkbranch(heads, remote_heads, update): + return None, 0 - if warn: - self.ui.warn(_("abort: push creates new remote heads!\n")) - self.ui.status(_("(did you forget to merge?" - " use push -f to force)\n")) - return None, 0 - elif inc: + if inc: self.ui.warn(_("note: unsynced remote changes!\n"))
--- a/tests/test-acl.out Sat May 23 17:03:51 2009 +0200 +++ b/tests/test-acl.out Sat May 23 17:04:31 2009 +0200 @@ -42,6 +42,7 @@ pushing to ../b searching for changes common changesets up to 6675d58eff77 +invalidating branch cache (tip differs) 3 changesets found list of changesets: ef1ea85a6374b77d6da9dcda9541f498f2d17df7 @@ -74,6 +75,7 @@ pushing to ../b searching for changes common changesets up to 6675d58eff77 +invalidating branch cache (tip differs) 3 changesets found list of changesets: ef1ea85a6374b77d6da9dcda9541f498f2d17df7 @@ -111,6 +113,7 @@ pushing to ../b searching for changes common changesets up to 6675d58eff77 +invalidating branch cache (tip differs) 3 changesets found list of changesets: ef1ea85a6374b77d6da9dcda9541f498f2d17df7 @@ -408,6 +411,7 @@ pushing to ../b searching for changes common changesets up to 6675d58eff77 +invalidating branch cache (tip differs) 3 changesets found list of changesets: ef1ea85a6374b77d6da9dcda9541f498f2d17df7