##// END OF EJS Templates
tree-discovery: fix the request debug output and progress location...
marmoute -
r50300:f64f6616 stable
parent child Browse files
Show More
@@ -1,205 +1,206 b''
1 1 # discovery.py - protocol changeset discovery functions
2 2 #
3 3 # Copyright 2010 Olivia Mackall <olivia@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8
9 9 import collections
10 10
11 11 from .i18n import _
12 12 from .node import short
13 13 from . import (
14 14 error,
15 15 )
16 16
17 17
18 18 def findcommonincoming(repo, remote, heads=None, force=False, audit=None):
19 19 """Return a tuple (common, fetch, heads) used to identify the common
20 20 subset of nodes between repo and remote.
21 21
22 22 "common" is a list of (at least) the heads of the common subset.
23 23 "fetch" is a list of roots of the nodes that would be incoming, to be
24 24 supplied to changegroupsubset.
25 25 "heads" is either the supplied heads, or else the remote's heads.
26 26 """
27 27
28 28 knownnode = repo.changelog.hasnode
29 29 search = []
30 30 fetch = set()
31 31 seen = set()
32 32 seenbranch = set()
33 33 base = set()
34 34
35 35 if not heads:
36 36 with remote.commandexecutor() as e:
37 37 heads = e.callcommand(b'heads', {}).result()
38 38
39 39 if audit is not None:
40 40 audit[b'total-roundtrips'] = 1
41 41 audit[b'total-roundtrips-heads'] = 1
42 42 audit[b'total-roundtrips-branches'] = 0
43 43 audit[b'total-roundtrips-between'] = 0
44 44 audit[b'total-queries'] = 0
45 45 audit[b'total-queries-branches'] = 0
46 46 audit[b'total-queries-between'] = 0
47 47
48 48 if repo.changelog.tip() == repo.nullid:
49 49 base.add(repo.nullid)
50 50 if heads != [repo.nullid]:
51 51 return [repo.nullid], [repo.nullid], list(heads)
52 52 return [repo.nullid], [], heads
53 53
54 54 # assume we're closer to the tip than the root
55 55 # and start by examining the heads
56 56 repo.ui.status(_(b"searching for changes\n"))
57 57
58 58 unknown = []
59 59 for h in heads:
60 60 if not knownnode(h):
61 61 unknown.append(h)
62 62 else:
63 63 base.add(h)
64 64
65 65 if not unknown:
66 66 return list(base), [], list(heads)
67 67
68 68 req = set(unknown)
69 69 reqcnt = 0
70 70 progress = repo.ui.makeprogress(_(b'searching'), unit=_(b'queries'))
71 71
72 72 # search through remote branches
73 73 # a 'branch' here is a linear segment of history, with four parts:
74 74 # head, root, first parent, second parent
75 75 # (a branch always has two parents (or none) by definition)
76 76 with remote.commandexecutor() as e:
77 77 if audit is not None:
78 78 audit[b'total-queries'] += len(unknown)
79 79 audit[b'total-queries-branches'] += len(unknown)
80 80 audit[b'total-roundtrips'] += 1
81 81 audit[b'total-roundtrips-branches'] += 1
82 82 branches = e.callcommand(b'branches', {b'nodes': unknown}).result()
83 83
84 84 unknown = collections.deque(branches)
85 85 while unknown:
86 86 r = []
87 87 while unknown:
88 88 n = unknown.popleft()
89 89 if n[0] in seen:
90 90 continue
91 91
92 92 repo.ui.debug(b"examining %s:%s\n" % (short(n[0]), short(n[1])))
93 93 if n[0] == repo.nullid: # found the end of the branch
94 94 pass
95 95 elif n in seenbranch:
96 96 repo.ui.debug(b"branch already found\n")
97 97 continue
98 98 elif n[1] and knownnode(n[1]): # do we know the base?
99 99 repo.ui.debug(
100 100 b"found incomplete branch %s:%s\n"
101 101 % (short(n[0]), short(n[1]))
102 102 )
103 103 search.append(n[0:2]) # schedule branch range for scanning
104 104 seenbranch.add(n)
105 105 else:
106 106 if n[1] not in seen and n[1] not in fetch:
107 107 if knownnode(n[2]) and knownnode(n[3]):
108 108 repo.ui.debug(b"found new changeset %s\n" % short(n[1]))
109 109 fetch.add(n[1]) # earliest unknown
110 110 for p in n[2:4]:
111 111 if knownnode(p):
112 112 base.add(p) # latest known
113 113
114 114 for p in n[2:4]:
115 115 if p not in req and not knownnode(p):
116 116 r.append(p)
117 117 req.add(p)
118 118 seen.add(n[0])
119 119
120 120 if r:
121 reqcnt += 1
122 progress.increment()
123 repo.ui.debug(
124 b"request %d: %s\n" % (reqcnt, b" ".join(map(short, r)))
125 )
126 121 for p in range(0, len(r), 10):
122 reqcnt += 1
123 progress.increment()
124 if repo.ui.debugflag:
125 msg = b"request %d: %s\n"
126 msg %= (reqcnt, b" ".join(map(short, r)))
127 repo.ui.debug(msg)
127 128 with remote.commandexecutor() as e:
128 129 subset = r[p : p + 10]
129 130 if audit is not None:
130 131 audit[b'total-queries'] += len(subset)
131 132 audit[b'total-queries-branches'] += len(subset)
132 133 audit[b'total-roundtrips'] += 1
133 134 audit[b'total-roundtrips-branches'] += 1
134 135 branches = e.callcommand(
135 136 b'branches',
136 137 {
137 138 b'nodes': subset,
138 139 },
139 140 ).result()
140 141
141 142 for b in branches:
142 143 repo.ui.debug(
143 144 b"received %s:%s\n" % (short(b[0]), short(b[1]))
144 145 )
145 146 unknown.append(b)
146 147
147 148 # do binary search on the branches we found
148 149 while search:
149 150 newsearch = []
150 151 reqcnt += 1
151 152 progress.increment()
152 153
153 154 with remote.commandexecutor() as e:
154 155 if audit is not None:
155 156 audit[b'total-queries'] += len(search)
156 157 audit[b'total-queries-between'] += len(search)
157 158 audit[b'total-roundtrips'] += 1
158 159 audit[b'total-roundtrips-between'] += 1
159 160 between = e.callcommand(b'between', {b'pairs': search}).result()
160 161
161 162 for n, l in zip(search, between):
162 163 l.append(n[1])
163 164 p = n[0]
164 165 f = 1
165 166 for i in l:
166 167 repo.ui.debug(b"narrowing %d:%d %s\n" % (f, len(l), short(i)))
167 168 if knownnode(i):
168 169 if f <= 2:
169 170 repo.ui.debug(
170 171 b"found new branch changeset %s\n" % short(p)
171 172 )
172 173 fetch.add(p)
173 174 base.add(i)
174 175 else:
175 176 repo.ui.debug(
176 177 b"narrowed branch search to %s:%s\n"
177 178 % (short(p), short(i))
178 179 )
179 180 newsearch.append((p, i))
180 181 break
181 182 p, f = i, f * 2
182 183 search = newsearch
183 184
184 185 # sanity check our fetch list
185 186 for f in fetch:
186 187 if knownnode(f):
187 188 raise error.RepoError(_(b"already have changeset ") + short(f[:4]))
188 189
189 190 base = list(base)
190 191 if base == [repo.nullid]:
191 192 if force:
192 193 repo.ui.warn(_(b"warning: repository is unrelated\n"))
193 194 else:
194 195 raise error.Abort(_(b"repository is unrelated"))
195 196
196 197 repo.ui.debug(
197 198 b"found new changesets starting at "
198 199 + b" ".join([short(f) for f in fetch])
199 200 + b"\n"
200 201 )
201 202
202 203 progress.complete()
203 204 repo.ui.debug(b"%d total queries\n" % reqcnt)
204 205
205 206 return base, list(fetch), heads
General Comments 0
You need to be logged in to leave comments. Login now