##// END OF EJS Templates
checkheads: take future obsoleted heads into account...
Pierre-Yves David -
r17214:738ad56d default
parent child Browse files
Show More
@@ -1,345 +1,372
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, setdiscovery, treediscovery, phases
10 import util, setdiscovery, treediscovery, phases, obsolete
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, anyincoming, heads) used to identify the common
13 """Return a tuple (common, anyincoming, 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 "anyincoming" is testable as a boolean indicating if any nodes are missing
17 "anyincoming" is testable as a boolean indicating if any nodes are missing
18 locally. If remote does not support getbundle, this actually is a list of
18 locally. If remote does not support getbundle, this actually is a list of
19 roots of the nodes that would be incoming, to be supplied to
19 roots of the nodes that would be incoming, to be supplied to
20 changegroupsubset. No code except for pull should be relying on this fact
20 changegroupsubset. No code except for pull should be relying on this fact
21 any longer.
21 any longer.
22 "heads" is either the supplied heads, or else the remote's heads.
22 "heads" is either the supplied heads, or else the remote's heads.
23
23
24 If you pass heads and they are all known locally, the reponse lists justs
24 If you pass heads and they are all known locally, the reponse lists justs
25 these heads in "common" and in "heads".
25 these heads in "common" and in "heads".
26
26
27 Please use findcommonoutgoing to compute the set of outgoing nodes to give
27 Please use findcommonoutgoing to compute the set of outgoing nodes to give
28 extensions a good hook into outgoing.
28 extensions a good hook into outgoing.
29 """
29 """
30
30
31 if not remote.capable('getbundle'):
31 if not remote.capable('getbundle'):
32 return treediscovery.findcommonincoming(repo, remote, heads, force)
32 return treediscovery.findcommonincoming(repo, remote, heads, force)
33
33
34 if heads:
34 if heads:
35 allknown = True
35 allknown = True
36 nm = repo.changelog.nodemap
36 nm = repo.changelog.nodemap
37 for h in heads:
37 for h in heads:
38 if nm.get(h) is None:
38 if nm.get(h) is None:
39 allknown = False
39 allknown = False
40 break
40 break
41 if allknown:
41 if allknown:
42 return (heads, False, heads)
42 return (heads, False, heads)
43
43
44 res = setdiscovery.findcommonheads(repo.ui, repo, remote,
44 res = setdiscovery.findcommonheads(repo.ui, repo, remote,
45 abortwhenunrelated=not force)
45 abortwhenunrelated=not force)
46 common, anyinc, srvheads = res
46 common, anyinc, srvheads = res
47 return (list(common), anyinc, heads or list(srvheads))
47 return (list(common), anyinc, heads or list(srvheads))
48
48
49 class outgoing(object):
49 class outgoing(object):
50 '''Represents the set of nodes present in a local repo but not in a
50 '''Represents the set of nodes present in a local repo but not in a
51 (possibly) remote one.
51 (possibly) remote one.
52
52
53 Members:
53 Members:
54
54
55 missing is a list of all nodes present in local but not in remote.
55 missing is a list of all nodes present in local but not in remote.
56 common is a list of all nodes shared between the two repos.
56 common is a list of all nodes shared between the two repos.
57 excluded is the list of missing changeset that shouldn't be sent remotely.
57 excluded is the list of missing changeset that shouldn't be sent remotely.
58 missingheads is the list of heads of missing.
58 missingheads is the list of heads of missing.
59 commonheads is the list of heads of common.
59 commonheads is the list of heads of common.
60
60
61 The sets are computed on demand from the heads, unless provided upfront
61 The sets are computed on demand from the heads, unless provided upfront
62 by discovery.'''
62 by discovery.'''
63
63
64 def __init__(self, revlog, commonheads, missingheads):
64 def __init__(self, revlog, commonheads, missingheads):
65 self.commonheads = commonheads
65 self.commonheads = commonheads
66 self.missingheads = missingheads
66 self.missingheads = missingheads
67 self._revlog = revlog
67 self._revlog = revlog
68 self._common = None
68 self._common = None
69 self._missing = None
69 self._missing = None
70 self.excluded = []
70 self.excluded = []
71
71
72 def _computecommonmissing(self):
72 def _computecommonmissing(self):
73 sets = self._revlog.findcommonmissing(self.commonheads,
73 sets = self._revlog.findcommonmissing(self.commonheads,
74 self.missingheads)
74 self.missingheads)
75 self._common, self._missing = sets
75 self._common, self._missing = sets
76
76
77 @util.propertycache
77 @util.propertycache
78 def common(self):
78 def common(self):
79 if self._common is None:
79 if self._common is None:
80 self._computecommonmissing()
80 self._computecommonmissing()
81 return self._common
81 return self._common
82
82
83 @util.propertycache
83 @util.propertycache
84 def missing(self):
84 def missing(self):
85 if self._missing is None:
85 if self._missing is None:
86 self._computecommonmissing()
86 self._computecommonmissing()
87 return self._missing
87 return self._missing
88
88
89 def findcommonoutgoing(repo, other, onlyheads=None, force=False,
89 def findcommonoutgoing(repo, other, onlyheads=None, force=False,
90 commoninc=None, portable=False):
90 commoninc=None, portable=False):
91 '''Return an outgoing instance to identify the nodes present in repo but
91 '''Return an outgoing instance to identify the nodes present in repo but
92 not in other.
92 not in other.
93
93
94 If onlyheads is given, only nodes ancestral to nodes in onlyheads
94 If onlyheads is given, only nodes ancestral to nodes in onlyheads
95 (inclusive) are included. If you already know the local repo's heads,
95 (inclusive) are included. If you already know the local repo's heads,
96 passing them in onlyheads is faster than letting them be recomputed here.
96 passing them in onlyheads is faster than letting them be recomputed here.
97
97
98 If commoninc is given, it must the the result of a prior call to
98 If commoninc is given, it must the the result of a prior call to
99 findcommonincoming(repo, other, force) to avoid recomputing it here.
99 findcommonincoming(repo, other, force) to avoid recomputing it here.
100
100
101 If portable is given, compute more conservative common and missingheads,
101 If portable is given, compute more conservative common and missingheads,
102 to make bundles created from the instance more portable.'''
102 to make bundles created from the instance more portable.'''
103 # declare an empty outgoing object to be filled later
103 # declare an empty outgoing object to be filled later
104 og = outgoing(repo.changelog, None, None)
104 og = outgoing(repo.changelog, None, None)
105
105
106 # get common set if not provided
106 # get common set if not provided
107 if commoninc is None:
107 if commoninc is None:
108 commoninc = findcommonincoming(repo, other, force=force)
108 commoninc = findcommonincoming(repo, other, force=force)
109 og.commonheads, _any, _hds = commoninc
109 og.commonheads, _any, _hds = commoninc
110
110
111 # compute outgoing
111 # compute outgoing
112 mayexclude = (repo._phasecache.phaseroots[phases.secret] or repo.obsstore)
112 mayexclude = (repo._phasecache.phaseroots[phases.secret] or repo.obsstore)
113 if not mayexclude:
113 if not mayexclude:
114 og.missingheads = onlyheads or repo.heads()
114 og.missingheads = onlyheads or repo.heads()
115 elif onlyheads is None:
115 elif onlyheads is None:
116 # use visible heads as it should be cached
116 # use visible heads as it should be cached
117 og.missingheads = visibleheads(repo)
117 og.missingheads = visibleheads(repo)
118 # extinct changesets are silently ignored
118 # extinct changesets are silently ignored
119 og.excluded = [ctx.node() for ctx in repo.set('secret()')]
119 og.excluded = [ctx.node() for ctx in repo.set('secret()')]
120 else:
120 else:
121 # compute common, missing and exclude secret stuff
121 # compute common, missing and exclude secret stuff
122 sets = repo.changelog.findcommonmissing(og.commonheads, onlyheads)
122 sets = repo.changelog.findcommonmissing(og.commonheads, onlyheads)
123 og._common, allmissing = sets
123 og._common, allmissing = sets
124 og._missing = missing = []
124 og._missing = missing = []
125 og.excluded = excluded = []
125 og.excluded = excluded = []
126 for node in allmissing:
126 for node in allmissing:
127 ctx = repo[node]
127 ctx = repo[node]
128 if not ctx.extinct():
128 if not ctx.extinct():
129 # extinct changesets are silently ignored
129 # extinct changesets are silently ignored
130 if ctx.phase() >= phases.secret:
130 if ctx.phase() >= phases.secret:
131 excluded.append(node)
131 excluded.append(node)
132 else:
132 else:
133 missing.append(node)
133 missing.append(node)
134 if len(missing) == len(allmissing):
134 if len(missing) == len(allmissing):
135 missingheads = onlyheads
135 missingheads = onlyheads
136 else: # update missing heads
136 else: # update missing heads
137 missingheads = phases.newheads(repo, onlyheads, excluded)
137 missingheads = phases.newheads(repo, onlyheads, excluded)
138 og.missingheads = missingheads
138 og.missingheads = missingheads
139 if portable:
139 if portable:
140 # recompute common and missingheads as if -r<rev> had been given for
140 # recompute common and missingheads as if -r<rev> had been given for
141 # each head of missing, and --base <rev> for each head of the proper
141 # each head of missing, and --base <rev> for each head of the proper
142 # ancestors of missing
142 # ancestors of missing
143 og._computecommonmissing()
143 og._computecommonmissing()
144 cl = repo.changelog
144 cl = repo.changelog
145 missingrevs = set(cl.rev(n) for n in og._missing)
145 missingrevs = set(cl.rev(n) for n in og._missing)
146 og._common = set(cl.ancestors(missingrevs)) - missingrevs
146 og._common = set(cl.ancestors(missingrevs)) - missingrevs
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 _headssummary(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 return {'branch': ([remoteheads], [newheads], [unsyncedheads])} mapping
155 return {'branch': ([remoteheads], [newheads], [unsyncedheads])} mapping
156
156
157 - branch: the branch name
157 - branch: the branch name
158 - remoteheads: the list of remote heads known locally
158 - remoteheads: the list of remote heads known locally
159 None is the branch is new
159 None is the branch is new
160 - newheads: the new remote heads (known locally) with outgoing pushed
160 - newheads: the new remote heads (known locally) with outgoing pushed
161 - unsyncedheads: the list of remote heads unknown locally.
161 - unsyncedheads: the list of remote heads unknown locally.
162 """
162 """
163 cl = repo.changelog
163 cl = repo.changelog
164 headssum = {}
164 headssum = {}
165 # A. Create set of branches involved in the push.
165 # A. Create set of branches involved in the push.
166 branches = set(repo[n].branch() for n in outgoing.missing)
166 branches = set(repo[n].branch() for n in outgoing.missing)
167 remotemap = remote.branchmap()
167 remotemap = remote.branchmap()
168 newbranches = branches - set(remotemap)
168 newbranches = branches - set(remotemap)
169 branches.difference_update(newbranches)
169 branches.difference_update(newbranches)
170
170
171 # A. register remote heads
171 # A. register remote heads
172 remotebranches = set()
172 remotebranches = set()
173 for branch, heads in remote.branchmap().iteritems():
173 for branch, heads in remote.branchmap().iteritems():
174 remotebranches.add(branch)
174 remotebranches.add(branch)
175 known = []
175 known = []
176 unsynced = []
176 unsynced = []
177 for h in heads:
177 for h in heads:
178 if h in cl.nodemap:
178 if h in cl.nodemap:
179 known.append(h)
179 known.append(h)
180 else:
180 else:
181 unsynced.append(h)
181 unsynced.append(h)
182 headssum[branch] = (known, list(known), unsynced)
182 headssum[branch] = (known, list(known), unsynced)
183 # B. add new branch data
183 # B. add new branch data
184 missingctx = list(repo[n] for n in outgoing.missing)
184 missingctx = list(repo[n] for n in outgoing.missing)
185 touchedbranches = set()
185 touchedbranches = set()
186 for ctx in missingctx:
186 for ctx in missingctx:
187 branch = ctx.branch()
187 branch = ctx.branch()
188 touchedbranches.add(branch)
188 touchedbranches.add(branch)
189 if branch not in headssum:
189 if branch not in headssum:
190 headssum[branch] = (None, [], [])
190 headssum[branch] = (None, [], [])
191
191
192 # C drop data about untouched branches:
192 # C drop data about untouched branches:
193 for branch in remotebranches - touchedbranches:
193 for branch in remotebranches - touchedbranches:
194 del headssum[branch]
194 del headssum[branch]
195
195
196 # D. Update newmap with outgoing changes.
196 # D. Update newmap with outgoing changes.
197 # This will possibly add new heads and remove existing ones.
197 # This will possibly add new heads and remove existing ones.
198 newmap = dict((branch, heads[1]) for branch, heads in headssum.iteritems()
198 newmap = dict((branch, heads[1]) for branch, heads in headssum.iteritems()
199 if heads[0] is not None)
199 if heads[0] is not None)
200 repo._updatebranchcache(newmap, missingctx)
200 repo._updatebranchcache(newmap, missingctx)
201 for branch, newheads in newmap.iteritems():
201 for branch, newheads in newmap.iteritems():
202 headssum[branch][1][:] = newheads
202 headssum[branch][1][:] = newheads
203 return headssum
203 return headssum
204
204
205 def _oldheadssummary(repo, remoteheads, outgoing, inc=False):
205 def _oldheadssummary(repo, remoteheads, outgoing, inc=False):
206 """Compute branchmapsummary for repo without branchmap support"""
206 """Compute branchmapsummary for repo without branchmap support"""
207
207
208 cl = repo.changelog
208 cl = repo.changelog
209 # 1-4b. old servers: Check for new topological heads.
209 # 1-4b. old servers: Check for new topological heads.
210 # Construct {old,new}map with branch = None (topological branch).
210 # Construct {old,new}map with branch = None (topological branch).
211 # (code based on _updatebranchcache)
211 # (code based on _updatebranchcache)
212 oldheads = set(h for h in remoteheads if h in cl.nodemap)
212 oldheads = set(h for h in remoteheads if h in cl.nodemap)
213 # all nodes in outgoing.missing are children of either:
213 # all nodes in outgoing.missing are children of either:
214 # - an element of oldheads
214 # - an element of oldheads
215 # - another element of outgoing.missing
215 # - another element of outgoing.missing
216 # - nullrev
216 # - nullrev
217 # This explains why the new head are very simple to compute.
217 # This explains why the new head are very simple to compute.
218 r = repo.set('heads(%ln + %ln)', oldheads, outgoing.missing)
218 r = repo.set('heads(%ln + %ln)', oldheads, outgoing.missing)
219 newheads = list(c.node() for c in r)
219 newheads = list(c.node() for c in r)
220 unsynced = inc and set([None]) or set()
220 unsynced = inc and set([None]) or set()
221 return {None: (oldheads, newheads, unsynced)}
221 return {None: (oldheads, newheads, unsynced)}
222
222
223 def checkheads(repo, remote, outgoing, remoteheads, newbranch=False, inc=False):
223 def checkheads(repo, remote, outgoing, remoteheads, newbranch=False, inc=False):
224 """Check that a push won't add any outgoing head
224 """Check that a push won't add any outgoing head
225
225
226 raise Abort error and display ui message as needed.
226 raise Abort error and display ui message as needed.
227 """
227 """
228 # Check for each named branch if we're creating new remote heads.
228 # Check for each named branch if we're creating new remote heads.
229 # To be a remote head after push, node must be either:
229 # To be a remote head after push, node must be either:
230 # - unknown locally
230 # - unknown locally
231 # - a local outgoing head descended from update
231 # - a local outgoing head descended from update
232 # - a remote head that's known locally and not
232 # - a remote head that's known locally and not
233 # ancestral to an outgoing head
233 # ancestral to an outgoing head
234 if remoteheads == [nullid]:
234 if remoteheads == [nullid]:
235 # remote is empty, nothing to check.
235 # remote is empty, nothing to check.
236 return
236 return
237
237
238 if remote.capable('branchmap'):
238 if remote.capable('branchmap'):
239 headssum = _headssummary(repo, remote, outgoing)
239 headssum = _headssummary(repo, remote, outgoing)
240 else:
240 else:
241 headssum = _oldheadssummary(repo, remoteheads, outgoing, inc)
241 headssum = _oldheadssummary(repo, remoteheads, outgoing, inc)
242 newbranches = [branch for branch, heads in headssum.iteritems()
242 newbranches = [branch for branch, heads in headssum.iteritems()
243 if heads[0] is None]
243 if heads[0] is None]
244 # 1. Check for new branches on the remote.
244 # 1. Check for new branches on the remote.
245 if newbranches and not newbranch: # new branch requires --new-branch
245 if newbranches and not newbranch: # new branch requires --new-branch
246 branchnames = ', '.join(sorted(newbranches))
246 branchnames = ', '.join(sorted(newbranches))
247 raise util.Abort(_("push creates new remote branches: %s!")
247 raise util.Abort(_("push creates new remote branches: %s!")
248 % branchnames,
248 % branchnames,
249 hint=_("use 'hg push --new-branch' to create"
249 hint=_("use 'hg push --new-branch' to create"
250 " new remote branches"))
250 " new remote branches"))
251
251
252 # 2 compute newly pushed bookmarks. We
252 # 2 compute newly pushed bookmarks. We
253 # we don't warned about bookmarked heads.
253 # we don't warned about bookmarked heads.
254 localbookmarks = repo._bookmarks
254 localbookmarks = repo._bookmarks
255 remotebookmarks = remote.listkeys('bookmarks')
255 remotebookmarks = remote.listkeys('bookmarks')
256 bookmarkedheads = set()
256 bookmarkedheads = set()
257 for bm in localbookmarks:
257 for bm in localbookmarks:
258 rnode = remotebookmarks.get(bm)
258 rnode = remotebookmarks.get(bm)
259 if rnode and rnode in repo:
259 if rnode and rnode in repo:
260 lctx, rctx = repo[bm], repo[rnode]
260 lctx, rctx = repo[bm], repo[rnode]
261 if rctx == lctx.ancestor(rctx):
261 if rctx == lctx.ancestor(rctx):
262 bookmarkedheads.add(lctx.node())
262 bookmarkedheads.add(lctx.node())
263
263
264 # 3. Check for new heads.
264 # 3. Check for new heads.
265 # If there are more heads after the push than before, a suitable
265 # If there are more heads after the push than before, a suitable
266 # error message, depending on unsynced status, is displayed.
266 # error message, depending on unsynced status, is displayed.
267 error = None
267 error = None
268 unsynced = False
268 unsynced = False
269 allmissing = set(outgoing.missing)
269 for branch, heads in headssum.iteritems():
270 for branch, heads in headssum.iteritems():
270 if heads[0] is None:
271 if heads[0] is None:
271 # Maybe we should abort if we push more that one head
272 # Maybe we should abort if we push more that one head
272 # for new branches ?
273 # for new branches ?
273 continue
274 continue
274 if heads[2]:
275 if heads[2]:
275 unsynced = True
276 unsynced = True
276 oldhs = set(heads[0])
277 oldhs = set(heads[0])
277 newhs = set(heads[1])
278 candidate_newhs = set(heads[1])
279 # add unsynced data
280 oldhs.update(heads[2])
281 candidate_newhs.update(heads[2])
278 dhs = None
282 dhs = None
283 if repo.obsstore:
284 # remove future heads which are actually obsolete by another
285 # pushed element:
286 #
287 # XXX There is several case this case does not handle properly
288 #
289 # (1) if <nh> is public, it won't be affected by obsolete marker
290 # and a new is created
291 #
292 # (2) if the new heads have ancestors which are not obsolete and
293 # not ancestors of any other heads we will have a new head too.
294 #
295 # This two case will be easy to handle for know changeset but much
296 # more tricky for unsynced changes.
297 newhs = set()
298 for nh in candidate_newhs:
299 for suc in obsolete.anysuccessors(repo.obsstore, nh):
300 if suc != nh and suc in allmissing:
301 break
302 else:
303 newhs.add(nh)
304 else:
305 newhs = candidate_newhs
279 if len(newhs) > len(oldhs):
306 if len(newhs) > len(oldhs):
280 # strip updates to existing remote heads from the new heads list
307 # strip updates to existing remote heads from the new heads list
281 dhs = list(newhs - bookmarkedheads - oldhs)
308 dhs = list(newhs - bookmarkedheads - oldhs)
282 if dhs:
309 if dhs:
283 if error is None:
310 if error is None:
284 if branch not in ('default', None):
311 if branch not in ('default', None):
285 error = _("push creates new remote head %s "
312 error = _("push creates new remote head %s "
286 "on branch '%s'!") % (short(dhs[0]), branch)
313 "on branch '%s'!") % (short(dhs[0]), branch)
287 else:
314 else:
288 error = _("push creates new remote head %s!"
315 error = _("push creates new remote head %s!"
289 ) % short(dhs[0])
316 ) % short(dhs[0])
290 if heads[2]: # unsynced
317 if heads[2]: # unsynced
291 hint = _("you should pull and merge or "
318 hint = _("you should pull and merge or "
292 "use push -f to force")
319 "use push -f to force")
293 else:
320 else:
294 hint = _("did you forget to merge? "
321 hint = _("did you forget to merge? "
295 "use push -f to force")
322 "use push -f to force")
296 if branch is not None:
323 if branch is not None:
297 repo.ui.note(_("new remote heads on branch '%s'\n") % branch)
324 repo.ui.note(_("new remote heads on branch '%s'\n") % branch)
298 for h in dhs:
325 for h in dhs:
299 repo.ui.note(_("new remote head %s\n") % short(h))
326 repo.ui.note(_("new remote head %s\n") % short(h))
300 if error:
327 if error:
301 raise util.Abort(error, hint=hint)
328 raise util.Abort(error, hint=hint)
302
329
303 # 6. Check for unsynced changes on involved branches.
330 # 6. Check for unsynced changes on involved branches.
304 if unsynced:
331 if unsynced:
305 repo.ui.warn(_("note: unsynced remote changes!\n"))
332 repo.ui.warn(_("note: unsynced remote changes!\n"))
306
333
307 def visibleheads(repo):
334 def visibleheads(repo):
308 """return the set of visible head of this repo"""
335 """return the set of visible head of this repo"""
309 # XXX we want a cache on this
336 # XXX we want a cache on this
310 sroots = repo._phasecache.phaseroots[phases.secret]
337 sroots = repo._phasecache.phaseroots[phases.secret]
311 if sroots or repo.obsstore:
338 if sroots or repo.obsstore:
312 # XXX very slow revset. storing heads or secret "boundary"
339 # XXX very slow revset. storing heads or secret "boundary"
313 # would help.
340 # would help.
314 revset = repo.set('heads(not (%ln:: + extinct()))', sroots)
341 revset = repo.set('heads(not (%ln:: + extinct()))', sroots)
315
342
316 vheads = [ctx.node() for ctx in revset]
343 vheads = [ctx.node() for ctx in revset]
317 if not vheads:
344 if not vheads:
318 vheads.append(nullid)
345 vheads.append(nullid)
319 else:
346 else:
320 vheads = repo.heads()
347 vheads = repo.heads()
321 return vheads
348 return vheads
322
349
323
350
324 def visiblebranchmap(repo):
351 def visiblebranchmap(repo):
325 """return a branchmap for the visible set"""
352 """return a branchmap for the visible set"""
326 # XXX Recomputing this data on the fly is very slow. We should build a
353 # XXX Recomputing this data on the fly is very slow. We should build a
327 # XXX cached version while computin the standard branchmap version.
354 # XXX cached version while computin the standard branchmap version.
328 sroots = repo._phasecache.phaseroots[phases.secret]
355 sroots = repo._phasecache.phaseroots[phases.secret]
329 if sroots or repo.obsstore:
356 if sroots or repo.obsstore:
330 vbranchmap = {}
357 vbranchmap = {}
331 for branch, nodes in repo.branchmap().iteritems():
358 for branch, nodes in repo.branchmap().iteritems():
332 # search for secret heads.
359 # search for secret heads.
333 for n in nodes:
360 for n in nodes:
334 if repo[n].phase() >= phases.secret:
361 if repo[n].phase() >= phases.secret:
335 nodes = None
362 nodes = None
336 break
363 break
337 # if secret heads were found we must compute them again
364 # if secret heads were found we must compute them again
338 if nodes is None:
365 if nodes is None:
339 s = repo.set('heads(branch(%s) - secret() - extinct())',
366 s = repo.set('heads(branch(%s) - secret() - extinct())',
340 branch)
367 branch)
341 nodes = [c.node() for c in s]
368 nodes = [c.node() for c in s]
342 vbranchmap[branch] = nodes
369 vbranchmap[branch] = nodes
343 else:
370 else:
344 vbranchmap = repo.branchmap()
371 vbranchmap = repo.branchmap()
345 return vbranchmap
372 return vbranchmap
@@ -1,359 +1,406
1 $ cat >> $HGRCPATH << EOF
1 $ cat >> $HGRCPATH << EOF
2 > [extensions]
2 > [extensions]
3 > graphlog=
3 > graphlog=
4 > [phases]
4 > [phases]
5 > # public changeset are not obsolete
5 > # public changeset are not obsolete
6 > publish=false
6 > publish=false
7 > EOF
7 > EOF
8 $ mkcommit() {
8 $ mkcommit() {
9 > echo "$1" > "$1"
9 > echo "$1" > "$1"
10 > hg add "$1"
10 > hg add "$1"
11 > hg ci -m "add $1"
11 > hg ci -m "add $1"
12 > }
12 > }
13 $ getid() {
13 $ getid() {
14 > hg id --debug -ir "desc('$1')"
14 > hg id --debug -ir "desc('$1')"
15 > }
15 > }
16
16
17
17
18 $ hg init tmpa
18 $ hg init tmpa
19 $ cd tmpa
19 $ cd tmpa
20
20
21 Killing a single changeset without replacement
21 Killing a single changeset without replacement
22
22
23 $ mkcommit kill_me
23 $ mkcommit kill_me
24 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
24 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
25 $ hg debugobsolete
25 $ hg debugobsolete
26 97b7c2d76b1845ed3eb988cd612611e72406cef0 0 {'date': '0 0', 'user': 'babar'}
26 97b7c2d76b1845ed3eb988cd612611e72406cef0 0 {'date': '0 0', 'user': 'babar'}
27 $ cd ..
27 $ cd ..
28
28
29 Killing a single changeset with replacement
29 Killing a single changeset with replacement
30
30
31 $ hg init tmpb
31 $ hg init tmpb
32 $ cd tmpb
32 $ cd tmpb
33 $ mkcommit a
33 $ mkcommit a
34 $ mkcommit b
34 $ mkcommit b
35 $ mkcommit original_c
35 $ mkcommit original_c
36 $ hg up "desc('b')"
36 $ hg up "desc('b')"
37 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
37 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
38 $ mkcommit new_c
38 $ mkcommit new_c
39 created new head
39 created new head
40 $ hg debugobsolete `getid original_c` `getid new_c` -d '56 12'
40 $ hg debugobsolete `getid original_c` `getid new_c` -d '56 12'
41 $ hg debugobsolete
41 $ hg debugobsolete
42 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
42 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
43
43
44 do it again (it read the obsstore before adding new changeset)
44 do it again (it read the obsstore before adding new changeset)
45
45
46 $ hg up '.^'
46 $ hg up '.^'
47 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
47 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
48 $ mkcommit new_2_c
48 $ mkcommit new_2_c
49 created new head
49 created new head
50 $ hg debugobsolete -d '1337 0' `getid new_c` `getid new_2_c`
50 $ hg debugobsolete -d '1337 0' `getid new_c` `getid new_2_c`
51 $ hg debugobsolete
51 $ hg debugobsolete
52 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
52 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
53 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
53 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
54
54
55 Register two markers with a missing node
55 Register two markers with a missing node
56
56
57 $ hg up '.^'
57 $ hg up '.^'
58 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
58 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
59 $ mkcommit new_3_c
59 $ mkcommit new_3_c
60 created new head
60 created new head
61 $ hg debugobsolete -d '1338 0' `getid new_2_c` 1337133713371337133713371337133713371337
61 $ hg debugobsolete -d '1338 0' `getid new_2_c` 1337133713371337133713371337133713371337
62 $ hg debugobsolete -d '1339 0' 1337133713371337133713371337133713371337 `getid new_3_c`
62 $ hg debugobsolete -d '1339 0' 1337133713371337133713371337133713371337 `getid new_3_c`
63 $ hg debugobsolete
63 $ hg debugobsolete
64 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
64 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
65 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
65 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
66 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
66 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
67 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
67 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
68
68
69 Check that graphlog detect that a changeset is obsolete:
69 Check that graphlog detect that a changeset is obsolete:
70
70
71 $ hg glog
71 $ hg glog
72 @ changeset: 5:5601fb93a350
72 @ changeset: 5:5601fb93a350
73 | tag: tip
73 | tag: tip
74 | parent: 1:7c3bad9141dc
74 | parent: 1:7c3bad9141dc
75 | user: test
75 | user: test
76 | date: Thu Jan 01 00:00:00 1970 +0000
76 | date: Thu Jan 01 00:00:00 1970 +0000
77 | summary: add new_3_c
77 | summary: add new_3_c
78 |
78 |
79 o changeset: 1:7c3bad9141dc
79 o changeset: 1:7c3bad9141dc
80 | user: test
80 | user: test
81 | date: Thu Jan 01 00:00:00 1970 +0000
81 | date: Thu Jan 01 00:00:00 1970 +0000
82 | summary: add b
82 | summary: add b
83 |
83 |
84 o changeset: 0:1f0dee641bb7
84 o changeset: 0:1f0dee641bb7
85 user: test
85 user: test
86 date: Thu Jan 01 00:00:00 1970 +0000
86 date: Thu Jan 01 00:00:00 1970 +0000
87 summary: add a
87 summary: add a
88
88
89
89
90 Check that public changeset are not accounted as obsolete:
90 Check that public changeset are not accounted as obsolete:
91
91
92 $ hg phase --public 2
92 $ hg phase --public 2
93 $ hg --config 'extensions.graphlog=' glog
93 $ hg --config 'extensions.graphlog=' glog
94 @ changeset: 5:5601fb93a350
94 @ changeset: 5:5601fb93a350
95 | tag: tip
95 | tag: tip
96 | parent: 1:7c3bad9141dc
96 | parent: 1:7c3bad9141dc
97 | user: test
97 | user: test
98 | date: Thu Jan 01 00:00:00 1970 +0000
98 | date: Thu Jan 01 00:00:00 1970 +0000
99 | summary: add new_3_c
99 | summary: add new_3_c
100 |
100 |
101 | o changeset: 2:245bde4270cd
101 | o changeset: 2:245bde4270cd
102 |/ user: test
102 |/ user: test
103 | date: Thu Jan 01 00:00:00 1970 +0000
103 | date: Thu Jan 01 00:00:00 1970 +0000
104 | summary: add original_c
104 | summary: add original_c
105 |
105 |
106 o changeset: 1:7c3bad9141dc
106 o changeset: 1:7c3bad9141dc
107 | user: test
107 | user: test
108 | date: Thu Jan 01 00:00:00 1970 +0000
108 | date: Thu Jan 01 00:00:00 1970 +0000
109 | summary: add b
109 | summary: add b
110 |
110 |
111 o changeset: 0:1f0dee641bb7
111 o changeset: 0:1f0dee641bb7
112 user: test
112 user: test
113 date: Thu Jan 01 00:00:00 1970 +0000
113 date: Thu Jan 01 00:00:00 1970 +0000
114 summary: add a
114 summary: add a
115
115
116
116
117 $ cd ..
117 $ cd ..
118
118
119 Exchange Test
119 Exchange Test
120 ============================
120 ============================
121
121
122 Destination repo does not have any data
122 Destination repo does not have any data
123 ---------------------------------------
123 ---------------------------------------
124
124
125 Try to pull markers
125 Try to pull markers
126 (extinct changeset are excluded but marker are pushed)
126 (extinct changeset are excluded but marker are pushed)
127
127
128 $ hg init tmpc
128 $ hg init tmpc
129 $ cd tmpc
129 $ cd tmpc
130 $ hg pull ../tmpb
130 $ hg pull ../tmpb
131 pulling from ../tmpb
131 pulling from ../tmpb
132 requesting all changes
132 requesting all changes
133 adding changesets
133 adding changesets
134 adding manifests
134 adding manifests
135 adding file changes
135 adding file changes
136 added 4 changesets with 4 changes to 4 files (+1 heads)
136 added 4 changesets with 4 changes to 4 files (+1 heads)
137 (run 'hg heads' to see heads, 'hg merge' to merge)
137 (run 'hg heads' to see heads, 'hg merge' to merge)
138 $ hg debugobsolete
138 $ hg debugobsolete
139 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
139 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
140 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
140 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
141 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
141 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
142 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
142 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
143
143
144 Rollback//Transaction support
144 Rollback//Transaction support
145
145
146 $ hg debugobsolete -d '1340 0' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
146 $ hg debugobsolete -d '1340 0' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
147 $ hg debugobsolete
147 $ hg debugobsolete
148 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
148 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
149 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
149 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
150 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
150 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
151 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
151 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
152 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 {'date': '1340 0', 'user': 'test'}
152 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 {'date': '1340 0', 'user': 'test'}
153 $ hg rollback -n
153 $ hg rollback -n
154 repository tip rolled back to revision 3 (undo debugobsolete)
154 repository tip rolled back to revision 3 (undo debugobsolete)
155 $ hg rollback
155 $ hg rollback
156 repository tip rolled back to revision 3 (undo debugobsolete)
156 repository tip rolled back to revision 3 (undo debugobsolete)
157 $ hg debugobsolete
157 $ hg debugobsolete
158 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
158 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
159 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
159 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
160 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
160 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
161 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
161 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
162
162
163 $ cd ..
163 $ cd ..
164
164
165 Try to pull markers
165 Try to pull markers
166
166
167 $ hg init tmpd
167 $ hg init tmpd
168 $ hg -R tmpb push tmpd
168 $ hg -R tmpb push tmpd
169 pushing to tmpd
169 pushing to tmpd
170 searching for changes
170 searching for changes
171 adding changesets
171 adding changesets
172 adding manifests
172 adding manifests
173 adding file changes
173 adding file changes
174 added 4 changesets with 4 changes to 4 files (+1 heads)
174 added 4 changesets with 4 changes to 4 files (+1 heads)
175 $ hg -R tmpd debugobsolete
175 $ hg -R tmpd debugobsolete
176 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
176 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
177 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
177 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
178 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
178 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
179 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
179 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
180
180
181
181
182 Destination repo have existing data
182 Destination repo have existing data
183 ---------------------------------------
183 ---------------------------------------
184
184
185 On pull
185 On pull
186
186
187 $ hg init tmpe
187 $ hg init tmpe
188 $ cd tmpe
188 $ cd tmpe
189 $ hg debugobsolete -d '1339 0' 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339
189 $ hg debugobsolete -d '1339 0' 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339
190 $ hg pull ../tmpb
190 $ hg pull ../tmpb
191 pulling from ../tmpb
191 pulling from ../tmpb
192 requesting all changes
192 requesting all changes
193 adding changesets
193 adding changesets
194 adding manifests
194 adding manifests
195 adding file changes
195 adding file changes
196 added 4 changesets with 4 changes to 4 files (+1 heads)
196 added 4 changesets with 4 changes to 4 files (+1 heads)
197 (run 'hg heads' to see heads, 'hg merge' to merge)
197 (run 'hg heads' to see heads, 'hg merge' to merge)
198 $ hg debugobsolete
198 $ hg debugobsolete
199 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 {'date': '1339 0', 'user': 'test'}
199 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 {'date': '1339 0', 'user': 'test'}
200 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
200 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
201 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
201 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
202 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
202 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
203 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
203 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
204
204
205
205
206 On push
206 On push
207
207
208 $ hg push ../tmpc
208 $ hg push ../tmpc
209 pushing to ../tmpc
209 pushing to ../tmpc
210 searching for changes
210 searching for changes
211 no changes found
211 no changes found
212 [1]
212 [1]
213 $ hg -R ../tmpc debugobsolete
213 $ hg -R ../tmpc debugobsolete
214 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
214 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f 0 {'date': '56 12', 'user': 'test'}
215 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
215 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 {'date': '1337 0', 'user': 'test'}
216 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
216 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 {'date': '1338 0', 'user': 'test'}
217 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
217 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 {'date': '1339 0', 'user': 'test'}
218 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 {'date': '1339 0', 'user': 'test'}
218 2448244824482448244824482448244824482448 1339133913391339133913391339133913391339 0 {'date': '1339 0', 'user': 'test'}
219
219
220 detect outgoing obsolete and unstable
220 detect outgoing obsolete and unstable
221 ---------------------------------------
221 ---------------------------------------
222
222
223
223
224 $ hg glog
224 $ hg glog
225 o changeset: 3:5601fb93a350
225 o changeset: 3:5601fb93a350
226 | tag: tip
226 | tag: tip
227 | parent: 1:7c3bad9141dc
227 | parent: 1:7c3bad9141dc
228 | user: test
228 | user: test
229 | date: Thu Jan 01 00:00:00 1970 +0000
229 | date: Thu Jan 01 00:00:00 1970 +0000
230 | summary: add new_3_c
230 | summary: add new_3_c
231 |
231 |
232 | o changeset: 2:245bde4270cd
232 | o changeset: 2:245bde4270cd
233 |/ user: test
233 |/ user: test
234 | date: Thu Jan 01 00:00:00 1970 +0000
234 | date: Thu Jan 01 00:00:00 1970 +0000
235 | summary: add original_c
235 | summary: add original_c
236 |
236 |
237 o changeset: 1:7c3bad9141dc
237 o changeset: 1:7c3bad9141dc
238 | user: test
238 | user: test
239 | date: Thu Jan 01 00:00:00 1970 +0000
239 | date: Thu Jan 01 00:00:00 1970 +0000
240 | summary: add b
240 | summary: add b
241 |
241 |
242 o changeset: 0:1f0dee641bb7
242 o changeset: 0:1f0dee641bb7
243 user: test
243 user: test
244 date: Thu Jan 01 00:00:00 1970 +0000
244 date: Thu Jan 01 00:00:00 1970 +0000
245 summary: add a
245 summary: add a
246
246
247 $ hg up 'desc("new_3_c")'
247 $ hg up 'desc("new_3_c")'
248 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
248 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
249 $ mkcommit original_d
249 $ mkcommit original_d
250 $ mkcommit original_e
250 $ mkcommit original_e
251 $ hg debugobsolete `getid original_d` -d '0 0'
251 $ hg debugobsolete `getid original_d` -d '0 0'
252 $ hg log -r 'obsolete()'
252 $ hg log -r 'obsolete()'
253 changeset: 4:7c694bff0650
253 changeset: 4:7c694bff0650
254 user: test
254 user: test
255 date: Thu Jan 01 00:00:00 1970 +0000
255 date: Thu Jan 01 00:00:00 1970 +0000
256 summary: add original_d
256 summary: add original_d
257
257
258 $ hg glog -r '::unstable()'
258 $ hg glog -r '::unstable()'
259 @ changeset: 5:6e572121998e
259 @ changeset: 5:6e572121998e
260 | tag: tip
260 | tag: tip
261 | user: test
261 | user: test
262 | date: Thu Jan 01 00:00:00 1970 +0000
262 | date: Thu Jan 01 00:00:00 1970 +0000
263 | summary: add original_e
263 | summary: add original_e
264 |
264 |
265 x changeset: 4:7c694bff0650
265 x changeset: 4:7c694bff0650
266 | user: test
266 | user: test
267 | date: Thu Jan 01 00:00:00 1970 +0000
267 | date: Thu Jan 01 00:00:00 1970 +0000
268 | summary: add original_d
268 | summary: add original_d
269 |
269 |
270 o changeset: 3:5601fb93a350
270 o changeset: 3:5601fb93a350
271 | parent: 1:7c3bad9141dc
271 | parent: 1:7c3bad9141dc
272 | user: test
272 | user: test
273 | date: Thu Jan 01 00:00:00 1970 +0000
273 | date: Thu Jan 01 00:00:00 1970 +0000
274 | summary: add new_3_c
274 | summary: add new_3_c
275 |
275 |
276 o changeset: 1:7c3bad9141dc
276 o changeset: 1:7c3bad9141dc
277 | user: test
277 | user: test
278 | date: Thu Jan 01 00:00:00 1970 +0000
278 | date: Thu Jan 01 00:00:00 1970 +0000
279 | summary: add b
279 | summary: add b
280 |
280 |
281 o changeset: 0:1f0dee641bb7
281 o changeset: 0:1f0dee641bb7
282 user: test
282 user: test
283 date: Thu Jan 01 00:00:00 1970 +0000
283 date: Thu Jan 01 00:00:00 1970 +0000
284 summary: add a
284 summary: add a
285
285
286
286
287 refuse to push obsolete changeset
287 refuse to push obsolete changeset
288
288
289 $ hg push ../tmpc/ -r 'desc("original_d")'
289 $ hg push ../tmpc/ -r 'desc("original_d")'
290 pushing to ../tmpc/
290 pushing to ../tmpc/
291 searching for changes
291 searching for changes
292 abort: push includes an obsolete changeset: 7c694bff0650!
292 abort: push includes an obsolete changeset: 7c694bff0650!
293 [255]
293 [255]
294
294
295 refuse to push unstable changeset
295 refuse to push unstable changeset
296
296
297 $ hg push ../tmpc/
297 $ hg push ../tmpc/
298 pushing to ../tmpc/
298 pushing to ../tmpc/
299 searching for changes
299 searching for changes
300 abort: push includes an unstable changeset: 6e572121998e!
300 abort: push includes an unstable changeset: 6e572121998e!
301 [255]
301 [255]
302
302
303 Test that extinct changeset are properly detected
303 Test that extinct changeset are properly detected
304
304
305 $ hg log -r 'extinct()'
305 $ hg log -r 'extinct()'
306
306
307 Don't try to push extinct changeset
307 Don't try to push extinct changeset
308
308
309 $ hg init ../tmpf
309 $ hg init ../tmpf
310 $ hg out ../tmpf
310 $ hg out ../tmpf
311 comparing with ../tmpf
311 comparing with ../tmpf
312 searching for changes
312 searching for changes
313 changeset: 0:1f0dee641bb7
313 changeset: 0:1f0dee641bb7
314 user: test
314 user: test
315 date: Thu Jan 01 00:00:00 1970 +0000
315 date: Thu Jan 01 00:00:00 1970 +0000
316 summary: add a
316 summary: add a
317
317
318 changeset: 1:7c3bad9141dc
318 changeset: 1:7c3bad9141dc
319 user: test
319 user: test
320 date: Thu Jan 01 00:00:00 1970 +0000
320 date: Thu Jan 01 00:00:00 1970 +0000
321 summary: add b
321 summary: add b
322
322
323 changeset: 2:245bde4270cd
323 changeset: 2:245bde4270cd
324 user: test
324 user: test
325 date: Thu Jan 01 00:00:00 1970 +0000
325 date: Thu Jan 01 00:00:00 1970 +0000
326 summary: add original_c
326 summary: add original_c
327
327
328 changeset: 3:5601fb93a350
328 changeset: 3:5601fb93a350
329 parent: 1:7c3bad9141dc
329 parent: 1:7c3bad9141dc
330 user: test
330 user: test
331 date: Thu Jan 01 00:00:00 1970 +0000
331 date: Thu Jan 01 00:00:00 1970 +0000
332 summary: add new_3_c
332 summary: add new_3_c
333
333
334 changeset: 4:7c694bff0650
334 changeset: 4:7c694bff0650
335 user: test
335 user: test
336 date: Thu Jan 01 00:00:00 1970 +0000
336 date: Thu Jan 01 00:00:00 1970 +0000
337 summary: add original_d
337 summary: add original_d
338
338
339 changeset: 5:6e572121998e
339 changeset: 5:6e572121998e
340 tag: tip
340 tag: tip
341 user: test
341 user: test
342 date: Thu Jan 01 00:00:00 1970 +0000
342 date: Thu Jan 01 00:00:00 1970 +0000
343 summary: add original_e
343 summary: add original_e
344
344
345 $ hg push ../tmpf -f # -f because be push unstable too
345 $ hg push ../tmpf -f # -f because be push unstable too
346 pushing to ../tmpf
346 pushing to ../tmpf
347 searching for changes
347 searching for changes
348 adding changesets
348 adding changesets
349 adding manifests
349 adding manifests
350 adding file changes
350 adding file changes
351 added 6 changesets with 6 changes to 6 files (+1 heads)
351 added 6 changesets with 6 changes to 6 files (+1 heads)
352
352
353 no warning displayed
353 no warning displayed
354
354
355 $ hg push ../tmpf
355 $ hg push ../tmpf
356 pushing to ../tmpf
356 pushing to ../tmpf
357 searching for changes
357 searching for changes
358 no changes found
358 no changes found
359 [1]
359 [1]
360
361 Do not warn about new head when the new head is a successors of a remote one
362
363 $ hg glog
364 @ changeset: 5:6e572121998e
365 | tag: tip
366 | user: test
367 | date: Thu Jan 01 00:00:00 1970 +0000
368 | summary: add original_e
369 |
370 x changeset: 4:7c694bff0650
371 | user: test
372 | date: Thu Jan 01 00:00:00 1970 +0000
373 | summary: add original_d
374 |
375 o changeset: 3:5601fb93a350
376 | parent: 1:7c3bad9141dc
377 | user: test
378 | date: Thu Jan 01 00:00:00 1970 +0000
379 | summary: add new_3_c
380 |
381 | o changeset: 2:245bde4270cd
382 |/ user: test
383 | date: Thu Jan 01 00:00:00 1970 +0000
384 | summary: add original_c
385 |
386 o changeset: 1:7c3bad9141dc
387 | user: test
388 | date: Thu Jan 01 00:00:00 1970 +0000
389 | summary: add b
390 |
391 o changeset: 0:1f0dee641bb7
392 user: test
393 date: Thu Jan 01 00:00:00 1970 +0000
394 summary: add a
395
396 $ hg up -q 'desc(new_3_c)'
397 $ mkcommit obsolete_e
398 created new head
399 $ hg debugobsolete `getid 'original_e'` `getid 'obsolete_e'`
400 $ hg push ../tmpf
401 pushing to ../tmpf
402 searching for changes
403 adding changesets
404 adding manifests
405 adding file changes
406 added 1 changesets with 1 changes to 1 files (+1 heads)
General Comments 0
You need to be logged in to leave comments. Login now