Show More
@@ -149,48 +149,60 b' def findcommonoutgoing(repo, other, only' | |||||
149 |
|
149 | |||
150 | return og |
|
150 | return og | |
151 |
|
151 | |||
152 |
def _ |
|
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) | |
|
182 | headssum[branch] = (known, list(known), unsynced) | |||
|
183 | # B. add new branch data | |||
|
184 | missingctx = list(repo[n] for n in outgoing.missing) | |||
|
185 | touchedbranches = set() | |||
|
186 | for ctx in missingctx: | |||
|
187 | branch = ctx.branch() | |||
|
188 | touchedbranches.add(branch) | |||
|
189 | if branch not in headssum: | |||
|
190 | headssum[branch] = (None, [], []) | |||
180 |
|
191 | |||
181 | prunedbrheads = [h for h in remotebrheads if h in cl.nodemap] |
|
192 | # C drop data about untouched branches: | |
182 | oldmap[branch] = prunedbrheads |
|
193 | for branch in remotebranches - touchedbranches: | |
183 | newmap[branch] = list(prunedbrheads) |
|
194 | del headssum[branch] | |
184 | if len(remotebrheads) > len(prunedbrheads): |
|
|||
185 | unsynced.add(branch) |
|
|||
186 |
|
195 | |||
187 |
# |
|
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) | |
|
201 | for branch, newheads in newmap.iteritems(): | |||
|
202 | headssum[branch][1][:] = newheads | |||
|
203 | return headssum | |||
192 |
|
204 | |||
193 |
def _old |
|
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 | |
@@ -204,11 +216,9 b' def _oldbranchmapsummary(repo, remotehea' | |||||
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 | |
@@ -226,10 +236,11 b' def checkheads(repo, remote, outgoing, r' | |||||
226 | return |
|
236 | return | |
227 |
|
237 | |||
228 | if remote.capable('branchmap'): |
|
238 | if remote.capable('branchmap'): | |
229 |
|
|
239 | headssum = _headssummary(repo, remote, outgoing) | |
230 | else: |
|
240 | else: | |
231 |
|
|
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)) | |
@@ -244,12 +255,18 b' def checkheads(repo, remote, outgoing, r' | |||||
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: | |
@@ -258,6 +275,7 b' def checkheads(repo, remote, outgoing, r' | |||||
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: | |
@@ -267,7 +285,7 b' def checkheads(repo, remote, outgoing, r' | |||||
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 |
|
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: |
General Comments 0
You need to be logged in to leave comments.
Login now