# HG changeset patch # User Benoit Boissinot # Date 1148373880 -7200 # Node ID 11422943cf72a7cd908c24b37271874e2581e8bf # Parent 3f24bc5dee81e35fd9bc7816bbf3b9af6daf7e9a document and fix findincoming - add documentation about what the function does, notably the fact that it updates 'base' - transform the workflow to a more simple 'if elif elif else' - do not call remote.branches if not necessary - some nodes where missing in 'base' (from what I understand, if the root of a branch is missing but one parent is present, the parent should be in 'base') - add a testcase for an incorrect outgoing that is fixed by this cset - add a testcase for an empty group bug, it needs fixing diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -899,6 +899,21 @@ class localrepository(object): return r def findincoming(self, remote, base=None, heads=None, force=False): + """Return list of roots of the subsets of missing nodes from remote + + If base dict is specified, assume that these nodes and their parents + exist on the remote side and that no child of a node of base exists + in both remote and self. + Furthermore base will be updated to include the nodes that exists + in self and remote but no children exists in self and remote. + If a list of heads is specified, return only nodes which are heads + or ancestors of these heads. + + All the ancestors of base are in self and in remote. + All the descendants of the list returned are missing in self. + (and so we know that the rest of the nodes are missing in remote, see + outgoing) + """ m = self.changelog.nodemap search = [] fetch = {} @@ -911,6 +926,7 @@ class localrepository(object): heads = remote.heads() if self.changelog.tip() == nullid: + base[nullid] = 1 if heads != [nullid]: return [nullid] return [] @@ -929,7 +945,7 @@ class localrepository(object): if not unknown: return [] - rep = {} + req = dict.fromkeys(unknown) reqcnt = 0 # search through remote branches @@ -946,12 +962,12 @@ class localrepository(object): self.ui.debug(_("examining %s:%s\n") % (short(n[0]), short(n[1]))) - if n[0] == nullid: - break - if n in seenbranch: + if n[0] == nullid: # found the end of the branch + pass + elif n in seenbranch: self.ui.debug(_("branch already found\n")) continue - if n[1] and n[1] in m: # do we know the base? + elif n[1] and n[1] in m: # do we know the base? self.ui.debug(_("found incomplete branch %s:%s\n") % (short(n[0]), short(n[1]))) search.append(n) # schedule branch range for scanning @@ -962,14 +978,14 @@ class localrepository(object): self.ui.debug(_("found new changeset %s\n") % short(n[1])) fetch[n[1]] = 1 # earliest unknown - base[n[2]] = 1 # latest known - continue + for p in n[2:4]: + if p in m: + base[p] = 1 # latest known - for a in n[2:4]: - if a not in rep: - r.append(a) - rep[a] = 1 - + for p in n[2:4]: + if p not in req and p not in m: + r.append(p) + req[p] = 1 seen[n[0]] = 1 if r: @@ -980,12 +996,7 @@ class localrepository(object): for b in remote.branches(r[p:p+10]): self.ui.debug(_("received %s:%s\n") % (short(b[0]), short(b[1]))) - if b[0] in m: - self.ui.debug(_("found base node %s\n") - % short(b[0])) - base[b[0]] = 1 - elif b[0] not in seen: - unknown.append(b) + unknown.append(b) # do binary search on the branches we found while search: diff --git a/tests/test-empty-group b/tests/test-empty-group new file mode 100755 --- /dev/null +++ b/tests/test-empty-group @@ -0,0 +1,49 @@ +#!/bin/sh +# +# A B +# +# 3 4 3 +# |\/| |\ +# |/\| | \ +# 1 2 1 2 +# \ / \ / +# 0 0 +# +# if the result of the merge of 1 and 2 +# is the same in 3 and 4, no new manifest +# will be created and the manifest group +# will be empty during the pull +# +# (plus we test a failure where outgoing +# wrongly reported the number of csets) +# + +hg init a +cd a +touch init +hg ci -A -m 0 -d "1000000 0" +touch x y +hg ci -A -m 1 -d "1000000 0" +hg update 0 +touch x y +hg ci -A -m 2 -d "1000000 0" +hg merge 1 +hg ci -A -m m1 -d "1000000 0" +#hg log +#hg debugindex .hg/00manifest.i +hg update -C 1 +hg merge 2 +hg ci -A -m m2 -d "1000000 0" +#hg log +#hg debugindex .hg/00manifest.i + +cd .. +hg clone -r 3 a b +hg clone -r 4 a c +hg -R a outgoing b +hg -R a outgoing c +hg -R b outgoing c +hg -R c outgoing b + +hg -R b pull a +hg -R c pull a diff --git a/tests/test-empty-group.out b/tests/test-empty-group.out new file mode 100644 --- /dev/null +++ b/tests/test-empty-group.out @@ -0,0 +1,72 @@ +adding init +adding x +adding y +0 files updated, 0 files merged, 2 files removed, 0 files unresolved +adding x +adding y +0 files updated, 0 files merged, 0 files removed, 0 files unresolved +(branch merge, don't forget to commit) +0 files updated, 0 files merged, 0 files removed, 0 files unresolved +0 files updated, 0 files merged, 0 files removed, 0 files unresolved +(branch merge, don't forget to commit) +requesting all changes +adding changesets +adding manifests +adding file changes +added 4 changesets with 3 changes to 3 files +3 files updated, 0 files merged, 0 files removed, 0 files unresolved +requesting all changes +adding changesets +adding manifests +adding file changes +added 4 changesets with 3 changes to 3 files +3 files updated, 0 files merged, 0 files removed, 0 files unresolved +searching for changes +changeset: 4:fdb3c546e859 +tag: tip +parent: 1:1f703b3fcbc6 +parent: 2:de997049e034 +user: test +date: Mon Jan 12 13:46:40 1970 +0000 +summary: m2 + +searching for changes +changeset: 3:f40f830c0024 +parent: 2:de997049e034 +parent: 1:1f703b3fcbc6 +user: test +date: Mon Jan 12 13:46:40 1970 +0000 +summary: m1 + +searching for changes +changeset: 3:f40f830c0024 +tag: tip +parent: 2:de997049e034 +parent: 1:1f703b3fcbc6 +user: test +date: Mon Jan 12 13:46:40 1970 +0000 +summary: m1 + +searching for changes +changeset: 3:fdb3c546e859 +tag: tip +parent: 1:1f703b3fcbc6 +parent: 2:de997049e034 +user: test +date: Mon Jan 12 13:46:40 1970 +0000 +summary: m2 + +pulling from a +searching for changes +adding changesets +adding manifests +adding file changes +added 1 changesets with 0 changes to 0 files (+1 heads) +(run 'hg heads' to see heads, 'hg merge' to merge) +pulling from a +searching for changes +adding changesets +adding manifests +adding file changes +added 1 changesets with 0 changes to 0 files (+1 heads) +(run 'hg heads' to see heads, 'hg merge' to merge)