##// END OF EJS Templates
treediscovery: fix regression when run against older repos (issue2793)...
Peter Arrenbrecht -
r14199:e3dd3dcd default
parent child Browse files
Show More
@@ -0,0 +1,278
1 Tests discovery against servers without getbundle support:
2
3 $ CAP=getbundle
4 $ . "$TESTDIR/notcapable"
5 $ echo '[ui]' >>$HGRCPATH
6 $ echo 'logtemplate="{rev} {node|short}: {desc} {branches}\\n"' >>$HGRCPATH
7 $ echo '[extensions]' >>$HGRCPATH
8 $ echo 'graphlog=' >>$HGRCPATH
9
10 Setup HTTP server control:
11
12 $ export remote=http://localhost:$HGPORT/
13 $ start() {
14 > echo '[web]' > $1/.hg/hgrc
15 > echo 'push_ssl = false' >> $1/.hg/hgrc
16 > echo 'allow_push = *' >> $1/.hg/hgrc
17 > hg serve -R $1 -p $HGPORT -d --pid-file=hg.pid -E errors.log
18 > cat hg.pid >> $DAEMON_PIDS
19 > }
20 $ stop() {
21 > "$TESTDIR/killdaemons.py"
22 > }
23
24 Both are empty:
25
26 $ hg init empty1
27 $ hg init empty2
28 $ start empty2
29 $ hg incoming -R empty1 $remote
30 comparing with http://localhost:$HGPORT/
31 no changes found
32 [1]
33 $ hg outgoing -R empty1 $remote
34 comparing with http://localhost:$HGPORT/
35 no changes found
36 [1]
37 $ hg pull -R empty1 $remote
38 pulling from http://localhost:$HGPORT/
39 no changes found
40 $ hg push -R empty1 $remote
41 pushing to http://localhost:$HGPORT/
42 no changes found
43 $ stop
44
45 Base repo:
46
47 $ hg init main
48 $ cd main
49 $ hg debugbuilddag -mo '+2:tbase @name1 +3:thead1 <tbase @name2 +4:thead2 @both /thead1 +2:tmaintip'
50 $ hg glog
51 o 11 a19bfa7e7328: r11 both
52 |
53 o 10 8b6bad1512e1: r10 both
54 |
55 o 9 025829e08038: r9 both
56 |\
57 | o 8 d8f638ac69e9: r8 name2
58 | |
59 | o 7 b6b4d315a2ac: r7 name2
60 | |
61 | o 6 6c6f5d5f3c11: r6 name2
62 | |
63 | o 5 70314b29987d: r5 name2
64 | |
65 o | 4 e71dbbc70e03: r4 name1
66 | |
67 o | 3 2c8d5d5ec612: r3 name1
68 | |
69 o | 2 a7892891da29: r2 name1
70 |/
71 o 1 0019a3b924fd: r1
72 |
73 o 0 d57206cc072a: r0
74
75 $ cd ..
76 $ start main
77
78 Full clone:
79
80 $ hg clone main full
81 updating to branch default
82 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
83 $ cd full
84 $ hg incoming $remote
85 comparing with http://localhost:$HGPORT/
86 searching for changes
87 no changes found
88 [1]
89 $ hg outgoing $remote
90 comparing with http://localhost:$HGPORT/
91 searching for changes
92 no changes found
93 [1]
94 $ hg pull $remote
95 pulling from http://localhost:$HGPORT/
96 searching for changes
97 no changes found
98 $ hg push $remote
99 pushing to http://localhost:$HGPORT/
100 searching for changes
101 no changes found
102 $ cd ..
103
104 Local is empty:
105
106 $ cd empty1
107 $ hg incoming $remote
108 comparing with http://localhost:$HGPORT/
109 0 d57206cc072a: r0
110 1 0019a3b924fd: r1
111 2 a7892891da29: r2 name1
112 3 2c8d5d5ec612: r3 name1
113 4 e71dbbc70e03: r4 name1
114 5 70314b29987d: r5 name2
115 6 6c6f5d5f3c11: r6 name2
116 7 b6b4d315a2ac: r7 name2
117 8 d8f638ac69e9: r8 name2
118 9 025829e08038: r9 both
119 10 8b6bad1512e1: r10 both
120 11 a19bfa7e7328: r11 both
121 $ hg outgoing $remote
122 comparing with http://localhost:$HGPORT/
123 no changes found
124 [1]
125 $ hg push $remote
126 pushing to http://localhost:$HGPORT/
127 no changes found
128 $ hg pull $remote
129 pulling from http://localhost:$HGPORT/
130 requesting all changes
131 adding changesets
132 adding manifests
133 adding file changes
134 added 12 changesets with 24 changes to 2 files
135 (run 'hg update' to get a working copy)
136 $ hg incoming $remote
137 comparing with http://localhost:$HGPORT/
138 searching for changes
139 no changes found
140 [1]
141 $ cd ..
142
143 Local is subset:
144
145 $ hg clone main subset --rev name2 ; cd subset
146 adding changesets
147 adding manifests
148 adding file changes
149 added 6 changesets with 12 changes to 2 files
150 updating to branch name2
151 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
152 $ hg incoming $remote
153 comparing with http://localhost:$HGPORT/
154 searching for changes
155 6 a7892891da29: r2 name1
156 7 2c8d5d5ec612: r3 name1
157 8 e71dbbc70e03: r4 name1
158 9 025829e08038: r9 both
159 10 8b6bad1512e1: r10 both
160 11 a19bfa7e7328: r11 both
161 $ hg outgoing $remote
162 comparing with http://localhost:$HGPORT/
163 searching for changes
164 no changes found
165 [1]
166 $ hg push $remote
167 pushing to http://localhost:$HGPORT/
168 searching for changes
169 no changes found
170 $ hg pull $remote
171 pulling from http://localhost:$HGPORT/
172 searching for changes
173 adding changesets
174 adding manifests
175 adding file changes
176 added 6 changesets with 12 changes to 2 files
177 (run 'hg update' to get a working copy)
178 $ hg incoming $remote
179 comparing with http://localhost:$HGPORT/
180 searching for changes
181 no changes found
182 [1]
183 $ cd ..
184
185 Remote is empty:
186
187 $ stop ; start empty2
188 $ cd main
189 $ hg incoming $remote
190 comparing with http://localhost:$HGPORT/
191 searching for changes
192 no changes found
193 [1]
194 $ hg outgoing $remote
195 comparing with http://localhost:$HGPORT/
196 searching for changes
197 0 d57206cc072a: r0
198 1 0019a3b924fd: r1
199 2 a7892891da29: r2 name1
200 3 2c8d5d5ec612: r3 name1
201 4 e71dbbc70e03: r4 name1
202 5 70314b29987d: r5 name2
203 6 6c6f5d5f3c11: r6 name2
204 7 b6b4d315a2ac: r7 name2
205 8 d8f638ac69e9: r8 name2
206 9 025829e08038: r9 both
207 10 8b6bad1512e1: r10 both
208 11 a19bfa7e7328: r11 both
209 $ hg pull $remote
210 pulling from http://localhost:$HGPORT/
211 searching for changes
212 no changes found
213 $ hg push $remote
214 pushing to http://localhost:$HGPORT/
215 searching for changes
216 remote: adding changesets
217 remote: adding manifests
218 remote: adding file changes
219 remote: added 12 changesets with 24 changes to 2 files
220 $ hg outgoing $remote
221 comparing with http://localhost:$HGPORT/
222 searching for changes
223 no changes found
224 [1]
225 $ cd ..
226
227 Local is superset:
228
229 $ stop
230 $ hg clone main subset2 --rev name2
231 adding changesets
232 adding manifests
233 adding file changes
234 added 6 changesets with 12 changes to 2 files
235 updating to branch name2
236 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
237 $ start subset2
238 $ cd main
239 $ hg incoming $remote
240 comparing with http://localhost:$HGPORT/
241 searching for changes
242 no changes found
243 [1]
244 $ hg outgoing $remote
245 comparing with http://localhost:$HGPORT/
246 searching for changes
247 2 a7892891da29: r2 name1
248 3 2c8d5d5ec612: r3 name1
249 4 e71dbbc70e03: r4 name1
250 9 025829e08038: r9 both
251 10 8b6bad1512e1: r10 both
252 11 a19bfa7e7328: r11 both
253 $ hg pull $remote
254 pulling from http://localhost:$HGPORT/
255 searching for changes
256 no changes found
257 $ hg push $remote
258 pushing to http://localhost:$HGPORT/
259 searching for changes
260 abort: push creates new remote branches: both, name1!
261 (use 'hg push --new-branch' to create new remote branches)
262 [255]
263 $ hg push $remote --new-branch
264 pushing to http://localhost:$HGPORT/
265 searching for changes
266 remote: adding changesets
267 remote: adding manifests
268 remote: adding file changes
269 remote: added 6 changesets with 12 changes to 2 files
270 $ hg outgoing $remote
271 comparing with http://localhost:$HGPORT/
272 searching for changes
273 no changes found
274 [1]
275 $ cd ..
276
277 $ stop
278
@@ -1,151 +1,151
1 # discovery.py - protocol changeset discovery functions
1 # discovery.py - protocol changeset discovery functions
2 #
2 #
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import nullid, short
8 from node import nullid, short
9 from i18n import _
9 from i18n import _
10 import util, error
10 import util, error
11
11
12 def findcommonincoming(repo, remote, heads=None, force=False):
12 def findcommonincoming(repo, remote, heads=None, force=False):
13 """Return a tuple (common, fetch, heads) used to identify the common
13 """Return a tuple (common, fetch, heads) used to identify the common
14 subset of nodes between repo and remote.
14 subset of nodes between repo and remote.
15
15
16 "common" is a list of (at least) the heads of the common subset.
16 "common" is a list of (at least) the heads of the common subset.
17 "fetch" is a list of roots of the nodes that would be incoming, to be
17 "fetch" is a list of roots of the nodes that would be incoming, to be
18 supplied to changegroupsubset.
18 supplied to changegroupsubset.
19 "heads" is either the supplied heads, or else the remote's heads.
19 "heads" is either the supplied heads, or else the remote's heads.
20 """
20 """
21
21
22 m = repo.changelog.nodemap
22 m = repo.changelog.nodemap
23 search = []
23 search = []
24 fetch = set()
24 fetch = set()
25 seen = set()
25 seen = set()
26 seenbranch = set()
26 seenbranch = set()
27 base = set()
27 base = set()
28
28
29 if not heads:
29 if not heads:
30 heads = remote.heads()
30 heads = remote.heads()
31
31
32 if repo.changelog.tip() == nullid:
32 if repo.changelog.tip() == nullid:
33 base.add(nullid)
33 base.add(nullid)
34 if heads != [nullid]:
34 if heads != [nullid]:
35 return [nullid], [nullid], list(heads)
35 return [nullid], [nullid], list(heads)
36 return [nullid], [], []
36 return [nullid], [], heads
37
37
38 # assume we're closer to the tip than the root
38 # assume we're closer to the tip than the root
39 # and start by examining the heads
39 # and start by examining the heads
40 repo.ui.status(_("searching for changes\n"))
40 repo.ui.status(_("searching for changes\n"))
41
41
42 unknown = []
42 unknown = []
43 for h in heads:
43 for h in heads:
44 if h not in m:
44 if h not in m:
45 unknown.append(h)
45 unknown.append(h)
46 else:
46 else:
47 base.add(h)
47 base.add(h)
48
48
49 if not unknown:
50 return list(base), [], list(heads)
51
49 heads = unknown
52 heads = unknown
50 if not unknown:
51 return list(base), [], []
52
53 req = set(unknown)
53 req = set(unknown)
54 reqcnt = 0
54 reqcnt = 0
55
55
56 # search through remote branches
56 # search through remote branches
57 # a 'branch' here is a linear segment of history, with four parts:
57 # a 'branch' here is a linear segment of history, with four parts:
58 # head, root, first parent, second parent
58 # head, root, first parent, second parent
59 # (a branch always has two parents (or none) by definition)
59 # (a branch always has two parents (or none) by definition)
60 unknown = remote.branches(unknown)
60 unknown = remote.branches(unknown)
61 while unknown:
61 while unknown:
62 r = []
62 r = []
63 while unknown:
63 while unknown:
64 n = unknown.pop(0)
64 n = unknown.pop(0)
65 if n[0] in seen:
65 if n[0] in seen:
66 continue
66 continue
67
67
68 repo.ui.debug("examining %s:%s\n"
68 repo.ui.debug("examining %s:%s\n"
69 % (short(n[0]), short(n[1])))
69 % (short(n[0]), short(n[1])))
70 if n[0] == nullid: # found the end of the branch
70 if n[0] == nullid: # found the end of the branch
71 pass
71 pass
72 elif n in seenbranch:
72 elif n in seenbranch:
73 repo.ui.debug("branch already found\n")
73 repo.ui.debug("branch already found\n")
74 continue
74 continue
75 elif n[1] and n[1] in m: # do we know the base?
75 elif n[1] and n[1] in m: # do we know the base?
76 repo.ui.debug("found incomplete branch %s:%s\n"
76 repo.ui.debug("found incomplete branch %s:%s\n"
77 % (short(n[0]), short(n[1])))
77 % (short(n[0]), short(n[1])))
78 search.append(n[0:2]) # schedule branch range for scanning
78 search.append(n[0:2]) # schedule branch range for scanning
79 seenbranch.add(n)
79 seenbranch.add(n)
80 else:
80 else:
81 if n[1] not in seen and n[1] not in fetch:
81 if n[1] not in seen and n[1] not in fetch:
82 if n[2] in m and n[3] in m:
82 if n[2] in m and n[3] in m:
83 repo.ui.debug("found new changeset %s\n" %
83 repo.ui.debug("found new changeset %s\n" %
84 short(n[1]))
84 short(n[1]))
85 fetch.add(n[1]) # earliest unknown
85 fetch.add(n[1]) # earliest unknown
86 for p in n[2:4]:
86 for p in n[2:4]:
87 if p in m:
87 if p in m:
88 base.add(p) # latest known
88 base.add(p) # latest known
89
89
90 for p in n[2:4]:
90 for p in n[2:4]:
91 if p not in req and p not in m:
91 if p not in req and p not in m:
92 r.append(p)
92 r.append(p)
93 req.add(p)
93 req.add(p)
94 seen.add(n[0])
94 seen.add(n[0])
95
95
96 if r:
96 if r:
97 reqcnt += 1
97 reqcnt += 1
98 repo.ui.progress(_('searching'), reqcnt, unit=_('queries'))
98 repo.ui.progress(_('searching'), reqcnt, unit=_('queries'))
99 repo.ui.debug("request %d: %s\n" %
99 repo.ui.debug("request %d: %s\n" %
100 (reqcnt, " ".join(map(short, r))))
100 (reqcnt, " ".join(map(short, r))))
101 for p in xrange(0, len(r), 10):
101 for p in xrange(0, len(r), 10):
102 for b in remote.branches(r[p:p + 10]):
102 for b in remote.branches(r[p:p + 10]):
103 repo.ui.debug("received %s:%s\n" %
103 repo.ui.debug("received %s:%s\n" %
104 (short(b[0]), short(b[1])))
104 (short(b[0]), short(b[1])))
105 unknown.append(b)
105 unknown.append(b)
106
106
107 # do binary search on the branches we found
107 # do binary search on the branches we found
108 while search:
108 while search:
109 newsearch = []
109 newsearch = []
110 reqcnt += 1
110 reqcnt += 1
111 repo.ui.progress(_('searching'), reqcnt, unit=_('queries'))
111 repo.ui.progress(_('searching'), reqcnt, unit=_('queries'))
112 for n, l in zip(search, remote.between(search)):
112 for n, l in zip(search, remote.between(search)):
113 l.append(n[1])
113 l.append(n[1])
114 p = n[0]
114 p = n[0]
115 f = 1
115 f = 1
116 for i in l:
116 for i in l:
117 repo.ui.debug("narrowing %d:%d %s\n" % (f, len(l), short(i)))
117 repo.ui.debug("narrowing %d:%d %s\n" % (f, len(l), short(i)))
118 if i in m:
118 if i in m:
119 if f <= 2:
119 if f <= 2:
120 repo.ui.debug("found new branch changeset %s\n" %
120 repo.ui.debug("found new branch changeset %s\n" %
121 short(p))
121 short(p))
122 fetch.add(p)
122 fetch.add(p)
123 base.add(i)
123 base.add(i)
124 else:
124 else:
125 repo.ui.debug("narrowed branch search to %s:%s\n"
125 repo.ui.debug("narrowed branch search to %s:%s\n"
126 % (short(p), short(i)))
126 % (short(p), short(i)))
127 newsearch.append((p, i))
127 newsearch.append((p, i))
128 break
128 break
129 p, f = i, f * 2
129 p, f = i, f * 2
130 search = newsearch
130 search = newsearch
131
131
132 # sanity check our fetch list
132 # sanity check our fetch list
133 for f in fetch:
133 for f in fetch:
134 if f in m:
134 if f in m:
135 raise error.RepoError(_("already have changeset ")
135 raise error.RepoError(_("already have changeset ")
136 + short(f[:4]))
136 + short(f[:4]))
137
137
138 base = list(base)
138 base = list(base)
139 if base == [nullid]:
139 if base == [nullid]:
140 if force:
140 if force:
141 repo.ui.warn(_("warning: repository is unrelated\n"))
141 repo.ui.warn(_("warning: repository is unrelated\n"))
142 else:
142 else:
143 raise util.Abort(_("repository is unrelated"))
143 raise util.Abort(_("repository is unrelated"))
144
144
145 repo.ui.debug("found new changesets starting at " +
145 repo.ui.debug("found new changesets starting at " +
146 " ".join([short(f) for f in fetch]) + "\n")
146 " ".join([short(f) for f in fetch]) + "\n")
147
147
148 repo.ui.progress(_('searching'), None)
148 repo.ui.progress(_('searching'), None)
149 repo.ui.debug("%d total queries\n" % reqcnt)
149 repo.ui.debug("%d total queries\n" % reqcnt)
150
150
151 return base, list(fetch), heads
151 return base, list(fetch), heads
General Comments 0
You need to be logged in to leave comments. Login now