Mercurial > hg
comparison mercurial/discovery.py @ 17211:4f321eecbf8d
checkheads: simplify the structure build by preprocessing
All useful data are now gathered in a single dictionnary.
`branchmapsummary` is renamed to `headssummary` and its return value
is greatly simplified.
author | Pierre-Yves David <pierre-yves.david@logilab.fr> |
---|---|
date | Tue, 17 Jul 2012 16:30:42 +0200 |
parents | 5cd3e526ac37 |
children | 246131d670c2 |
comparison
equal
deleted
inserted
replaced
17210:ec80ae982689 | 17211:4f321eecbf8d |
---|---|
147 commonheads = set(og.commonheads) | 147 commonheads = set(og.commonheads) |
148 og.missingheads = [h for h in og.missingheads if h not in commonheads] | 148 og.missingheads = [h for h in og.missingheads if h not in commonheads] |
149 | 149 |
150 return og | 150 return og |
151 | 151 |
152 def _branchmapsummary(repo, remote, outgoing): | 152 def _headssummary(repo, remote, outgoing): |
153 """compute a summary of branch and heads status before and after push | 153 """compute a summary of branch and heads status before and after push |
154 | 154 |
155 - oldmap: {'branch': [heads]} mapping for remote | 155 return {'branch': ([remoteheads], [newheads], [unsyncedheads])} mapping |
156 - newmap: {'branch': [heads]} mapping for local | 156 |
157 - unsynced: set of branch that have unsynced remote changes | 157 - branch: the branch name |
158 - branches: set of all common branch pushed | 158 - remoteheads: the list of remote heads known locally |
159 - newbranches: list of plain new pushed branch | 159 None is the branch is new |
160 - newheads: the new remote heads (known locally) with outgoing pushed | |
161 - unsyncedheads: the list of remote heads unknown locally. | |
160 """ | 162 """ |
161 cl = repo.changelog | 163 cl = repo.changelog |
162 | 164 headssum = {} |
163 # A. Create set of branches involved in the push. | 165 # A. Create set of branches involved in the push. |
164 branches = set(repo[n].branch() for n in outgoing.missing) | 166 branches = set(repo[n].branch() for n in outgoing.missing) |
165 remotemap = remote.branchmap() | 167 remotemap = remote.branchmap() |
166 newbranches = branches - set(remotemap) | 168 newbranches = branches - set(remotemap) |
167 branches.difference_update(newbranches) | 169 branches.difference_update(newbranches) |
168 | 170 |
169 # B. Construct the initial oldmap and newmap dicts. | 171 # A. register remote heads |
170 # They contain information about the remote heads before and | 172 remotebranches = set() |
171 # after the push, respectively. | 173 for branch, heads in remote.branchmap().iteritems(): |
172 # Heads not found locally are not included in either dict, | 174 remotebranches.add(branch) |
173 # since they won't be affected by the push. | 175 known = [] |
174 # unsynced contains all branches with incoming changesets. | 176 unsynced = [] |
175 oldmap = {} | 177 for h in heads: |
176 newmap = {} | 178 if h in cl.nodemap: |
177 unsynced = set() | 179 known.append(h) |
178 for branch in branches: | 180 else: |
179 remotebrheads = remotemap[branch] | 181 unsynced.append(h) |
180 | 182 headssum[branch] = (known, list(known), unsynced) |
181 prunedbrheads = [h for h in remotebrheads if h in cl.nodemap] | 183 # B. add new branch data |
182 oldmap[branch] = prunedbrheads | 184 missingctx = list(repo[n] for n in outgoing.missing) |
183 newmap[branch] = list(prunedbrheads) | 185 touchedbranches = set() |
184 if len(remotebrheads) > len(prunedbrheads): | 186 for ctx in missingctx: |
185 unsynced.add(branch) | 187 branch = ctx.branch() |
186 | 188 touchedbranches.add(branch) |
187 # C. Update newmap with outgoing changes. | 189 if branch not in headssum: |
190 headssum[branch] = (None, [], []) | |
191 | |
192 # C drop data about untouched branches: | |
193 for branch in remotebranches - touchedbranches: | |
194 del headssum[branch] | |
195 | |
196 # D. Update newmap with outgoing changes. | |
188 # This will possibly add new heads and remove existing ones. | 197 # This will possibly add new heads and remove existing ones. |
189 ctxgen = (repo[n] for n in outgoing.missing) | 198 newmap = dict((branch, heads[1]) for branch, heads in headssum.iteritems() |
190 repo._updatebranchcache(newmap, ctxgen) | 199 if heads[0] is not None) |
191 return oldmap, newmap, unsynced, branches, newbranches | 200 repo._updatebranchcache(newmap, missingctx) |
192 | 201 for branch, newheads in newmap.iteritems(): |
193 def _oldbranchmapsummary(repo, remoteheads, outgoing, inc=False): | 202 headssum[branch][1][:] = newheads |
203 return headssum | |
204 | |
205 def _oldheadssummary(repo, remoteheads, outgoing, inc=False): | |
194 """Compute branchmapsummary for repo without branchmap support""" | 206 """Compute branchmapsummary for repo without branchmap support""" |
195 | 207 |
196 cl = repo.changelog | 208 cl = repo.changelog |
197 # 1-4b. old servers: Check for new topological heads. | 209 # 1-4b. old servers: Check for new topological heads. |
198 # Construct {old,new}map with branch = None (topological branch). | 210 # Construct {old,new}map with branch = None (topological branch). |
202 # - an element of oldheads | 214 # - an element of oldheads |
203 # - another element of outgoing.missing | 215 # - another element of outgoing.missing |
204 # - nullrev | 216 # - nullrev |
205 # This explains why the new head are very simple to compute. | 217 # This explains why the new head are very simple to compute. |
206 r = repo.set('heads(%ln + %ln)', oldheads, outgoing.missing) | 218 r = repo.set('heads(%ln + %ln)', oldheads, outgoing.missing) |
207 branches = set([None]) | 219 newheads = list(c.node() for c in r) |
208 newmap = {None: list(c.node() for c in r)} | 220 unsynced = inc and set([None]) or set() |
209 oldmap = {None: oldheads} | 221 return {None: (oldheads, newheads, unsynced)} |
210 unsynced = inc and branches or set() | |
211 return oldmap, newmap, unsynced, branches, set() | |
212 | 222 |
213 def checkheads(repo, remote, outgoing, remoteheads, newbranch=False, inc=False): | 223 def checkheads(repo, remote, outgoing, remoteheads, newbranch=False, inc=False): |
214 """Check that a push won't add any outgoing head | 224 """Check that a push won't add any outgoing head |
215 | 225 |
216 raise Abort error and display ui message as needed. | 226 raise Abort error and display ui message as needed. |
224 if remoteheads == [nullid]: | 234 if remoteheads == [nullid]: |
225 # remote is empty, nothing to check. | 235 # remote is empty, nothing to check. |
226 return | 236 return |
227 | 237 |
228 if remote.capable('branchmap'): | 238 if remote.capable('branchmap'): |
229 bms = _branchmapsummary(repo, remote, outgoing) | 239 headssum = _headssummary(repo, remote, outgoing) |
230 else: | 240 else: |
231 bms = _oldbranchmapsummary(repo, remoteheads, outgoing, inc) | 241 headssum = _oldheadssummary(repo, remoteheads, outgoing, inc) |
232 oldmap, newmap, unsynced, branches, newbranches = bms | 242 newbranches = [branch for branch, heads in headssum.iteritems() |
243 if heads[0] is None] | |
233 # 1. Check for new branches on the remote. | 244 # 1. Check for new branches on the remote. |
234 if newbranches and not newbranch: # new branch requires --new-branch | 245 if newbranches and not newbranch: # new branch requires --new-branch |
235 branchnames = ', '.join(sorted(newbranches)) | 246 branchnames = ', '.join(sorted(newbranches)) |
236 raise util.Abort(_("push creates new remote branches: %s!") | 247 raise util.Abort(_("push creates new remote branches: %s!") |
237 % branchnames, | 248 % branchnames, |
242 # If there are more heads after the push than before, a suitable | 253 # If there are more heads after the push than before, a suitable |
243 # error message, depending on unsynced status, is displayed. | 254 # error message, depending on unsynced status, is displayed. |
244 error = None | 255 error = None |
245 localbookmarks = repo._bookmarks | 256 localbookmarks = repo._bookmarks |
246 | 257 |
247 for branch in branches: | 258 unsynced = False |
248 newhs = set(newmap[branch]) | 259 for branch, heads in headssum.iteritems(): |
249 oldhs = set(oldmap[branch]) | 260 if heads[0] is None: |
261 # Maybe we should abort if we push more that one head | |
262 # for new branches ? | |
263 continue | |
264 if heads[2]: | |
265 unsynced = True | |
266 oldhs = set(heads[0]) | |
267 newhs = set(heads[1]) | |
250 dhs = None | 268 dhs = None |
251 if len(newhs) > len(oldhs): | 269 if len(newhs) > len(oldhs): |
252 # strip updates to existing remote heads from the new heads list | |
253 remotebookmarks = remote.listkeys('bookmarks') | 270 remotebookmarks = remote.listkeys('bookmarks') |
254 bookmarkedheads = set() | 271 bookmarkedheads = set() |
255 for bm in localbookmarks: | 272 for bm in localbookmarks: |
256 rnode = remotebookmarks.get(bm) | 273 rnode = remotebookmarks.get(bm) |
257 if rnode and rnode in repo: | 274 if rnode and rnode in repo: |
258 lctx, rctx = repo[bm], repo[rnode] | 275 lctx, rctx = repo[bm], repo[rnode] |
259 if rctx == lctx.ancestor(rctx): | 276 if rctx == lctx.ancestor(rctx): |
260 bookmarkedheads.add(lctx.node()) | 277 bookmarkedheads.add(lctx.node()) |
278 # strip updates to existing remote heads from the new heads list | |
261 dhs = list(newhs - bookmarkedheads - oldhs) | 279 dhs = list(newhs - bookmarkedheads - oldhs) |
262 if dhs: | 280 if dhs: |
263 if error is None: | 281 if error is None: |
264 if branch not in ('default', None): | 282 if branch not in ('default', None): |
265 error = _("push creates new remote head %s " | 283 error = _("push creates new remote head %s " |
266 "on branch '%s'!") % (short(dhs[0]), branch) | 284 "on branch '%s'!") % (short(dhs[0]), branch) |
267 else: | 285 else: |
268 error = _("push creates new remote head %s!" | 286 error = _("push creates new remote head %s!" |
269 ) % short(dhs[0]) | 287 ) % short(dhs[0]) |
270 if branch in unsynced: | 288 if heads[2]: # unsynced |
271 hint = _("you should pull and merge or " | 289 hint = _("you should pull and merge or " |
272 "use push -f to force") | 290 "use push -f to force") |
273 else: | 291 else: |
274 hint = _("did you forget to merge? " | 292 hint = _("did you forget to merge? " |
275 "use push -f to force") | 293 "use push -f to force") |