##// END OF EJS Templates
repoview: fix corrupted hiddencache crash Mercurial (issue5042)...
Laurent Charignon -
r27917:97e0dc6d stable
parent child Browse files
Show More
@@ -1,346 +1,353
1 1 # repoview.py - Filtered view of a localrepo object
2 2 #
3 3 # Copyright 2012 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
4 4 # Logilab SA <contact@logilab.fr>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 from __future__ import absolute_import
10 10
11 11 import copy
12 12 import heapq
13 13 import struct
14 14
15 15 from .node import nullrev
16 16 from . import (
17 17 error,
18 18 obsolete,
19 19 phases,
20 20 tags as tagsmod,
21 21 util,
22 22 )
23 23
24 24 def hideablerevs(repo):
25 25 """Revisions candidates to be hidden
26 26
27 27 This is a standalone function to help extensions to wrap it."""
28 28 return obsolete.getrevs(repo, 'obsolete')
29 29
30 30 def _getstatichidden(repo):
31 31 """Revision to be hidden (disregarding dynamic blocker)
32 32
33 33 To keep a consistent graph, we cannot hide any revisions with
34 34 non-hidden descendants. This function computes the set of
35 35 revisions that could be hidden while keeping the graph consistent.
36 36
37 37 A second pass will be done to apply "dynamic blocker" like bookmarks or
38 38 working directory parents.
39 39
40 40 """
41 41 assert not repo.changelog.filteredrevs
42 42 hidden = set(hideablerevs(repo))
43 43 if hidden:
44 44 getphase = repo._phasecache.phase
45 45 getparentrevs = repo.changelog.parentrevs
46 46 # Skip heads which are public (guaranteed to not be hidden)
47 47 heap = [-r for r in repo.changelog.headrevs() if getphase(repo, r)]
48 48 heapq.heapify(heap)
49 49 heappop = heapq.heappop
50 50 heappush = heapq.heappush
51 51 seen = set() # no need to init it with heads, they have no children
52 52 while heap:
53 53 rev = -heappop(heap)
54 54 # All children have been processed so at that point, if no children
55 55 # removed 'rev' from the 'hidden' set, 'rev' is going to be hidden.
56 56 blocker = rev not in hidden
57 57 for parent in getparentrevs(rev):
58 58 if parent == nullrev:
59 59 continue
60 60 if blocker:
61 61 # If visible, ensure parent will be visible too
62 62 hidden.discard(parent)
63 63 # - Avoid adding the same revision twice
64 64 # - Skip nodes which are public (guaranteed to not be hidden)
65 65 pre = len(seen)
66 66 seen.add(parent)
67 67 if pre < len(seen) and getphase(repo, rev):
68 68 heappush(heap, -parent)
69 69 return hidden
70 70
71 71 def _getdynamicblockers(repo):
72 72 """Non-cacheable revisions blocking hidden changesets from being filtered.
73 73
74 74 Get revisions that will block hidden changesets and are likely to change,
75 75 but unlikely to create hidden blockers. They won't be cached, so be careful
76 76 with adding additional computation."""
77 77
78 78 cl = repo.changelog
79 79 blockers = set()
80 80 blockers.update([par.rev() for par in repo[None].parents()])
81 81 blockers.update([cl.rev(bm) for bm in repo._bookmarks.values()])
82 82
83 83 tags = {}
84 84 tagsmod.readlocaltags(repo.ui, repo, tags, {})
85 85 if tags:
86 86 rev, nodemap = cl.rev, cl.nodemap
87 87 blockers.update(rev(t[0]) for t in tags.values() if t[0] in nodemap)
88 88 return blockers
89 89
90 90 cacheversion = 1
91 91 cachefile = 'cache/hidden'
92 92
93 93 def cachehash(repo, hideable):
94 94 """return sha1 hash of repository data to identify a valid cache.
95 95
96 96 We calculate a sha1 of repo heads and the content of the obsstore and write
97 97 it to the cache. Upon reading we can easily validate by checking the hash
98 98 against the stored one and discard the cache in case the hashes don't match.
99 99 """
100 100 h = util.sha1()
101 101 h.update(''.join(repo.heads()))
102 102 h.update(str(hash(frozenset(hideable))))
103 103 return h.digest()
104 104
105 105 def _writehiddencache(cachefile, cachehash, hidden):
106 106 """write hidden data to a cache file"""
107 107 data = struct.pack('>%ii' % len(hidden), *sorted(hidden))
108 108 cachefile.write(struct.pack(">H", cacheversion))
109 109 cachefile.write(cachehash)
110 110 cachefile.write(data)
111 111
112 112 def trywritehiddencache(repo, hideable, hidden):
113 113 """write cache of hidden changesets to disk
114 114
115 115 Will not write the cache if a wlock cannot be obtained lazily.
116 116 The cache consists of a head of 22byte:
117 117 2 byte version number of the cache
118 118 20 byte sha1 to validate the cache
119 119 n*4 byte hidden revs
120 120 """
121 121 wlock = fh = None
122 122 try:
123 123 wlock = repo.wlock(wait=False)
124 124 # write cache to file
125 125 newhash = cachehash(repo, hideable)
126 126 fh = repo.vfs.open(cachefile, 'w+b', atomictemp=True)
127 127 _writehiddencache(fh, newhash, hidden)
128 128 except (IOError, OSError):
129 129 repo.ui.debug('error writing hidden changesets cache\n')
130 130 except error.LockHeld:
131 131 repo.ui.debug('cannot obtain lock to write hidden changesets cache\n')
132 132 finally:
133 133 if fh:
134 134 fh.close()
135 135 if wlock:
136 136 wlock.release()
137 137
138 138 def tryreadcache(repo, hideable):
139 139 """read a cache if the cache exists and is valid, otherwise returns None."""
140 140 hidden = fh = None
141 141 try:
142 142 if repo.vfs.exists(cachefile):
143 143 fh = repo.vfs.open(cachefile, 'rb')
144 144 version, = struct.unpack(">H", fh.read(2))
145 145 oldhash = fh.read(20)
146 146 newhash = cachehash(repo, hideable)
147 147 if (cacheversion, oldhash) == (version, newhash):
148 148 # cache is valid, so we can start reading the hidden revs
149 149 data = fh.read()
150 150 count = len(data) / 4
151 151 hidden = frozenset(struct.unpack('>%ii' % count, data))
152 152 return hidden
153 except struct.error:
154 repo.ui.debug('corrupted hidden cache\n')
155 # No need to fix the content as it will get rewritten
156 return None
157 except (IOError, OSError):
158 repo.ui.debug('cannot read hidden cache\n')
159 return None
153 160 finally:
154 161 if fh:
155 162 fh.close()
156 163
157 164 def computehidden(repo):
158 165 """compute the set of hidden revision to filter
159 166
160 167 During most operation hidden should be filtered."""
161 168 assert not repo.changelog.filteredrevs
162 169
163 170 hidden = frozenset()
164 171 hideable = hideablerevs(repo)
165 172 if hideable:
166 173 cl = repo.changelog
167 174 hidden = tryreadcache(repo, hideable)
168 175 if hidden is None:
169 176 hidden = frozenset(_getstatichidden(repo))
170 177 trywritehiddencache(repo, hideable, hidden)
171 178
172 179 # check if we have wd parents, bookmarks or tags pointing to hidden
173 180 # changesets and remove those.
174 181 dynamic = hidden & _getdynamicblockers(repo)
175 182 if dynamic:
176 183 blocked = cl.ancestors(dynamic, inclusive=True)
177 184 hidden = frozenset(r for r in hidden if r not in blocked)
178 185 return hidden
179 186
180 187 def computeunserved(repo):
181 188 """compute the set of revision that should be filtered when used a server
182 189
183 190 Secret and hidden changeset should not pretend to be here."""
184 191 assert not repo.changelog.filteredrevs
185 192 # fast path in simple case to avoid impact of non optimised code
186 193 hiddens = filterrevs(repo, 'visible')
187 194 if phases.hassecret(repo):
188 195 cl = repo.changelog
189 196 secret = phases.secret
190 197 getphase = repo._phasecache.phase
191 198 first = min(cl.rev(n) for n in repo._phasecache.phaseroots[secret])
192 199 revs = cl.revs(start=first)
193 200 secrets = set(r for r in revs if getphase(repo, r) >= secret)
194 201 return frozenset(hiddens | secrets)
195 202 else:
196 203 return hiddens
197 204
198 205 def computemutable(repo):
199 206 """compute the set of revision that should be filtered when used a server
200 207
201 208 Secret and hidden changeset should not pretend to be here."""
202 209 assert not repo.changelog.filteredrevs
203 210 # fast check to avoid revset call on huge repo
204 211 if any(repo._phasecache.phaseroots[1:]):
205 212 getphase = repo._phasecache.phase
206 213 maymutable = filterrevs(repo, 'base')
207 214 return frozenset(r for r in maymutable if getphase(repo, r))
208 215 return frozenset()
209 216
210 217 def computeimpactable(repo):
211 218 """Everything impactable by mutable revision
212 219
213 220 The immutable filter still have some chance to get invalidated. This will
214 221 happen when:
215 222
216 223 - you garbage collect hidden changeset,
217 224 - public phase is moved backward,
218 225 - something is changed in the filtering (this could be fixed)
219 226
220 227 This filter out any mutable changeset and any public changeset that may be
221 228 impacted by something happening to a mutable revision.
222 229
223 230 This is achieved by filtered everything with a revision number egal or
224 231 higher than the first mutable changeset is filtered."""
225 232 assert not repo.changelog.filteredrevs
226 233 cl = repo.changelog
227 234 firstmutable = len(cl)
228 235 for roots in repo._phasecache.phaseroots[1:]:
229 236 if roots:
230 237 firstmutable = min(firstmutable, min(cl.rev(r) for r in roots))
231 238 # protect from nullrev root
232 239 firstmutable = max(0, firstmutable)
233 240 return frozenset(xrange(firstmutable, len(cl)))
234 241
235 242 # function to compute filtered set
236 243 #
237 244 # When adding a new filter you MUST update the table at:
238 245 # mercurial.branchmap.subsettable
239 246 # Otherwise your filter will have to recompute all its branches cache
240 247 # from scratch (very slow).
241 248 filtertable = {'visible': computehidden,
242 249 'served': computeunserved,
243 250 'immutable': computemutable,
244 251 'base': computeimpactable}
245 252
246 253 def filterrevs(repo, filtername):
247 254 """returns set of filtered revision for this filter name"""
248 255 if filtername not in repo.filteredrevcache:
249 256 func = filtertable[filtername]
250 257 repo.filteredrevcache[filtername] = func(repo.unfiltered())
251 258 return repo.filteredrevcache[filtername]
252 259
253 260 class repoview(object):
254 261 """Provide a read/write view of a repo through a filtered changelog
255 262
256 263 This object is used to access a filtered version of a repository without
257 264 altering the original repository object itself. We can not alter the
258 265 original object for two main reasons:
259 266 - It prevents the use of a repo with multiple filters at the same time. In
260 267 particular when multiple threads are involved.
261 268 - It makes scope of the filtering harder to control.
262 269
263 270 This object behaves very closely to the original repository. All attribute
264 271 operations are done on the original repository:
265 272 - An access to `repoview.someattr` actually returns `repo.someattr`,
266 273 - A write to `repoview.someattr` actually sets value of `repo.someattr`,
267 274 - A deletion of `repoview.someattr` actually drops `someattr`
268 275 from `repo.__dict__`.
269 276
270 277 The only exception is the `changelog` property. It is overridden to return
271 278 a (surface) copy of `repo.changelog` with some revisions filtered. The
272 279 `filtername` attribute of the view control the revisions that need to be
273 280 filtered. (the fact the changelog is copied is an implementation detail).
274 281
275 282 Unlike attributes, this object intercepts all method calls. This means that
276 283 all methods are run on the `repoview` object with the filtered `changelog`
277 284 property. For this purpose the simple `repoview` class must be mixed with
278 285 the actual class of the repository. This ensures that the resulting
279 286 `repoview` object have the very same methods than the repo object. This
280 287 leads to the property below.
281 288
282 289 repoview.method() --> repo.__class__.method(repoview)
283 290
284 291 The inheritance has to be done dynamically because `repo` can be of any
285 292 subclasses of `localrepo`. Eg: `bundlerepo` or `statichttprepo`.
286 293 """
287 294
288 295 def __init__(self, repo, filtername):
289 296 object.__setattr__(self, '_unfilteredrepo', repo)
290 297 object.__setattr__(self, 'filtername', filtername)
291 298 object.__setattr__(self, '_clcachekey', None)
292 299 object.__setattr__(self, '_clcache', None)
293 300
294 301 # not a propertycache on purpose we shall implement a proper cache later
295 302 @property
296 303 def changelog(self):
297 304 """return a filtered version of the changeset
298 305
299 306 this changelog must not be used for writing"""
300 307 # some cache may be implemented later
301 308 unfi = self._unfilteredrepo
302 309 unfichangelog = unfi.changelog
303 310 # bypass call to changelog.method
304 311 unfiindex = unfichangelog.index
305 312 unfilen = len(unfiindex) - 1
306 313 unfinode = unfiindex[unfilen - 1][7]
307 314
308 315 revs = filterrevs(unfi, self.filtername)
309 316 cl = self._clcache
310 317 newkey = (unfilen, unfinode, hash(revs), unfichangelog._delayed)
311 318 if cl is not None and newkey != self._clcachekey:
312 319 cl = None
313 320 # could have been made None by the previous if
314 321 if cl is None:
315 322 cl = copy.copy(unfichangelog)
316 323 cl.filteredrevs = revs
317 324 object.__setattr__(self, '_clcache', cl)
318 325 object.__setattr__(self, '_clcachekey', newkey)
319 326 return cl
320 327
321 328 def unfiltered(self):
322 329 """Return an unfiltered version of a repo"""
323 330 return self._unfilteredrepo
324 331
325 332 def filtered(self, name):
326 333 """Return a filtered version of a repository"""
327 334 if name == self.filtername:
328 335 return self
329 336 return self.unfiltered().filtered(name)
330 337
331 338 # everything access are forwarded to the proxied repo
332 339 def __getattr__(self, attr):
333 340 return getattr(self._unfilteredrepo, attr)
334 341
335 342 def __setattr__(self, attr, value):
336 343 return setattr(self._unfilteredrepo, attr, value)
337 344
338 345 def __delattr__(self, attr):
339 346 return delattr(self._unfilteredrepo, attr)
340 347
341 348 # The `requirements` attribute is initialized during __init__. But
342 349 # __getattr__ won't be called as it also exists on the class. We need
343 350 # explicit forwarding to main repo here
344 351 @property
345 352 def requirements(self):
346 353 return self._unfilteredrepo.requirements
@@ -1,991 +1,1008
1 1 $ cat >> $HGRCPATH << EOF
2 2 > [phases]
3 3 > # public changeset are not obsolete
4 4 > publish=false
5 5 > [ui]
6 6 > logtemplate="{rev}:{node|short} ({phase}) [{tags} {bookmarks}] {desc|firstline}\n"
7 7 > [experimental]
8 8 > # drop me once bundle2 is the default,
9 9 > # added to get test change early.
10 10 > bundle2-exp = True
11 11 > EOF
12 12 $ mkcommit() {
13 13 > echo "$1" > "$1"
14 14 > hg add "$1"
15 15 > hg ci -m "add $1"
16 16 > }
17 17 $ getid() {
18 18 > hg log -T "{node}\n" --hidden -r "desc('$1')"
19 19 > }
20 20
21 21 $ cat > debugkeys.py <<EOF
22 22 > def reposetup(ui, repo):
23 23 > class debugkeysrepo(repo.__class__):
24 24 > def listkeys(self, namespace):
25 25 > ui.write('listkeys %s\n' % (namespace,))
26 26 > return super(debugkeysrepo, self).listkeys(namespace)
27 27 >
28 28 > if repo.local():
29 29 > repo.__class__ = debugkeysrepo
30 30 > EOF
31 31
32 32 $ hg init tmpa
33 33 $ cd tmpa
34 34 $ mkcommit kill_me
35 35
36 36 Checking that the feature is properly disabled
37 37
38 38 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
39 39 abort: creating obsolete markers is not enabled on this repo
40 40 [255]
41 41
42 42 Enabling it
43 43
44 44 $ cat >> $HGRCPATH << EOF
45 45 > [experimental]
46 46 > evolution=createmarkers,exchange
47 47 > EOF
48 48
49 49 Killing a single changeset without replacement
50 50
51 51 $ hg debugobsolete 0
52 52 abort: changeset references must be full hexadecimal node identifiers
53 53 [255]
54 54 $ hg debugobsolete '00'
55 55 abort: changeset references must be full hexadecimal node identifiers
56 56 [255]
57 57 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
58 58 $ hg debugobsolete
59 59 97b7c2d76b1845ed3eb988cd612611e72406cef0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'babar'}
60 60
61 61 (test that mercurial is not confused)
62 62
63 63 $ hg up null --quiet # having 0 as parent prevents it to be hidden
64 64 $ hg tip
65 65 -1:000000000000 (public) [tip ]
66 66 $ hg up --hidden tip --quiet
67 67
68 68 Killing a single changeset with itself should fail
69 69 (simple local safeguard)
70 70
71 71 $ hg debugobsolete `getid kill_me` `getid kill_me`
72 72 abort: bad obsmarker input: in-marker cycle with 97b7c2d76b1845ed3eb988cd612611e72406cef0
73 73 [255]
74 74
75 75 $ cd ..
76 76
77 77 Killing a single changeset with replacement
78 78 (and testing the format option)
79 79
80 80 $ hg init tmpb
81 81 $ cd tmpb
82 82 $ mkcommit a
83 83 $ mkcommit b
84 84 $ mkcommit original_c
85 85 $ hg up "desc('b')"
86 86 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
87 87 $ mkcommit new_c
88 88 created new head
89 89 $ hg log -r 'hidden()' --template '{rev}:{node|short} {desc}\n' --hidden
90 90 $ hg debugobsolete --config format.obsstore-version=0 --flag 12 `getid original_c` `getid new_c` -d '121 120'
91 91 $ hg log -r 'hidden()' --template '{rev}:{node|short} {desc}\n' --hidden
92 92 2:245bde4270cd add original_c
93 93 $ hg debugrevlog -cd
94 94 # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads chainlen
95 95 0 -1 -1 0 59 0 0 0 0 58 58 0 1 0
96 96 1 0 -1 59 118 59 59 0 0 58 116 0 1 0
97 97 2 1 -1 118 193 118 118 59 0 76 192 0 1 0
98 98 3 1 -1 193 260 193 193 59 0 66 258 0 2 0
99 99 $ hg debugobsolete
100 100 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
101 101
102 102 (check for version number of the obsstore)
103 103
104 104 $ dd bs=1 count=1 if=.hg/store/obsstore 2>/dev/null
105 105 \x00 (no-eol) (esc)
106 106
107 107 do it again (it read the obsstore before adding new changeset)
108 108
109 109 $ hg up '.^'
110 110 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
111 111 $ mkcommit new_2_c
112 112 created new head
113 113 $ hg debugobsolete -d '1337 0' `getid new_c` `getid new_2_c`
114 114 $ hg debugobsolete
115 115 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
116 116 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
117 117
118 118 Register two markers with a missing node
119 119
120 120 $ hg up '.^'
121 121 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
122 122 $ mkcommit new_3_c
123 123 created new head
124 124 $ hg debugobsolete -d '1338 0' `getid new_2_c` 1337133713371337133713371337133713371337
125 125 $ hg debugobsolete -d '1339 0' 1337133713371337133713371337133713371337 `getid new_3_c`
126 126 $ hg debugobsolete
127 127 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
128 128 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
129 129 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
130 130 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
131 131
132 132 Refuse pathological nullid successors
133 133 $ hg debugobsolete -d '9001 0' 1337133713371337133713371337133713371337 0000000000000000000000000000000000000000
134 134 transaction abort!
135 135 rollback completed
136 136 abort: bad obsolescence marker detected: invalid successors nullid
137 137 [255]
138 138
139 139 Check that graphlog detect that a changeset is obsolete:
140 140
141 141 $ hg log -G
142 142 @ 5:5601fb93a350 (draft) [tip ] add new_3_c
143 143 |
144 144 o 1:7c3bad9141dc (draft) [ ] add b
145 145 |
146 146 o 0:1f0dee641bb7 (draft) [ ] add a
147 147
148 148
149 149 check that heads does not report them
150 150
151 151 $ hg heads
152 152 5:5601fb93a350 (draft) [tip ] add new_3_c
153 153 $ hg heads --hidden
154 154 5:5601fb93a350 (draft) [tip ] add new_3_c
155 155 4:ca819180edb9 (draft) [ ] add new_2_c
156 156 3:cdbce2fbb163 (draft) [ ] add new_c
157 157 2:245bde4270cd (draft) [ ] add original_c
158 158
159 159
160 160 check that summary does not report them
161 161
162 162 $ hg init ../sink
163 163 $ echo '[paths]' >> .hg/hgrc
164 164 $ echo 'default=../sink' >> .hg/hgrc
165 165 $ hg summary --remote
166 166 parent: 5:5601fb93a350 tip
167 167 add new_3_c
168 168 branch: default
169 169 commit: (clean)
170 170 update: (current)
171 171 phases: 3 draft
172 172 remote: 3 outgoing
173 173
174 174 $ hg summary --remote --hidden
175 175 parent: 5:5601fb93a350 tip
176 176 add new_3_c
177 177 branch: default
178 178 commit: (clean)
179 179 update: 3 new changesets, 4 branch heads (merge)
180 180 phases: 6 draft
181 181 remote: 3 outgoing
182 182
183 183 check that various commands work well with filtering
184 184
185 185 $ hg tip
186 186 5:5601fb93a350 (draft) [tip ] add new_3_c
187 187 $ hg log -r 6
188 188 abort: unknown revision '6'!
189 189 [255]
190 190 $ hg log -r 4
191 191 abort: hidden revision '4'!
192 192 (use --hidden to access hidden revisions)
193 193 [255]
194 194 $ hg debugrevspec 'rev(6)'
195 195 $ hg debugrevspec 'rev(4)'
196 196 $ hg debugrevspec 'null'
197 197 -1
198 198
199 199 Check that public changeset are not accounted as obsolete:
200 200
201 201 $ hg --hidden phase --public 2
202 202 $ hg log -G
203 203 @ 5:5601fb93a350 (draft) [tip ] add new_3_c
204 204 |
205 205 | o 2:245bde4270cd (public) [ ] add original_c
206 206 |/
207 207 o 1:7c3bad9141dc (public) [ ] add b
208 208 |
209 209 o 0:1f0dee641bb7 (public) [ ] add a
210 210
211 211
212 212 And that bumped changeset are detected
213 213 --------------------------------------
214 214
215 215 If we didn't filtered obsolete changesets out, 3 and 4 would show up too. Also
216 216 note that the bumped changeset (5:5601fb93a350) is not a direct successor of
217 217 the public changeset
218 218
219 219 $ hg log --hidden -r 'bumped()'
220 220 5:5601fb93a350 (draft) [tip ] add new_3_c
221 221
222 222 And that we can't push bumped changeset
223 223
224 224 $ hg push ../tmpa -r 0 --force #(make repo related)
225 225 pushing to ../tmpa
226 226 searching for changes
227 227 warning: repository is unrelated
228 228 adding changesets
229 229 adding manifests
230 230 adding file changes
231 231 added 1 changesets with 1 changes to 1 files (+1 heads)
232 232 $ hg push ../tmpa
233 233 pushing to ../tmpa
234 234 searching for changes
235 235 abort: push includes bumped changeset: 5601fb93a350!
236 236 [255]
237 237
238 238 Fixing "bumped" situation
239 239 We need to create a clone of 5 and add a special marker with a flag
240 240
241 241 $ hg summary
242 242 parent: 5:5601fb93a350 tip
243 243 add new_3_c
244 244 branch: default
245 245 commit: (clean)
246 246 update: 1 new changesets, 2 branch heads (merge)
247 247 phases: 1 draft
248 248 bumped: 1 changesets
249 249 $ hg up '5^'
250 250 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
251 251 $ hg revert -ar 5
252 252 adding new_3_c
253 253 $ hg ci -m 'add n3w_3_c'
254 254 created new head
255 255 $ hg debugobsolete -d '1338 0' --flags 1 `getid new_3_c` `getid n3w_3_c`
256 256 $ hg log -r 'bumped()'
257 257 $ hg log -G
258 258 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
259 259 |
260 260 | o 2:245bde4270cd (public) [ ] add original_c
261 261 |/
262 262 o 1:7c3bad9141dc (public) [ ] add b
263 263 |
264 264 o 0:1f0dee641bb7 (public) [ ] add a
265 265
266 266
267 267 $ cd ..
268 268
269 269 Revision 0 is hidden
270 270 --------------------
271 271
272 272 $ hg init rev0hidden
273 273 $ cd rev0hidden
274 274
275 275 $ mkcommit kill0
276 276 $ hg up -q null
277 277 $ hg debugobsolete `getid kill0`
278 278 $ mkcommit a
279 279 $ mkcommit b
280 280
281 281 Should pick the first visible revision as "repo" node
282 282
283 283 $ hg archive ../archive-null
284 284 $ cat ../archive-null/.hg_archival.txt
285 285 repo: 1f0dee641bb7258c56bd60e93edfa2405381c41e
286 286 node: 7c3bad9141dcb46ff89abf5f61856facd56e476c
287 287 branch: default
288 288 latesttag: null
289 289 latesttagdistance: 2
290 290 changessincelatesttag: 2
291 291
292 292
293 293 $ cd ..
294 294
295 295 Exchange Test
296 296 ============================
297 297
298 298 Destination repo does not have any data
299 299 ---------------------------------------
300 300
301 301 Simple incoming test
302 302
303 303 $ hg init tmpc
304 304 $ cd tmpc
305 305 $ hg incoming ../tmpb
306 306 comparing with ../tmpb
307 307 0:1f0dee641bb7 (public) [ ] add a
308 308 1:7c3bad9141dc (public) [ ] add b
309 309 2:245bde4270cd (public) [ ] add original_c
310 310 6:6f9641995072 (draft) [tip ] add n3w_3_c
311 311
312 312 Try to pull markers
313 313 (extinct changeset are excluded but marker are pushed)
314 314
315 315 $ hg pull ../tmpb
316 316 pulling from ../tmpb
317 317 requesting all changes
318 318 adding changesets
319 319 adding manifests
320 320 adding file changes
321 321 added 4 changesets with 4 changes to 4 files (+1 heads)
322 322 5 new obsolescence markers
323 323 (run 'hg heads' to see heads, 'hg merge' to merge)
324 324 $ hg debugobsolete
325 325 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
326 326 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
327 327 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
328 328 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
329 329 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
330 330
331 331 Rollback//Transaction support
332 332
333 333 $ hg debugobsolete -d '1340 0' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
334 334 $ hg debugobsolete
335 335 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
336 336 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
337 337 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
338 338 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
339 339 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
340 340 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 (Thu Jan 01 00:22:20 1970 +0000) {'user': 'test'}
341 341 $ hg rollback -n
342 342 repository tip rolled back to revision 3 (undo debugobsolete)
343 343 $ hg rollback
344 344 repository tip rolled back to revision 3 (undo debugobsolete)
345 345 $ hg debugobsolete
346 346 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
347 347 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
348 348 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
349 349 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
350 350 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
351 351
352 352 $ cd ..
353 353
354 354 Try to push markers
355 355
356 356 $ hg init tmpd
357 357 $ hg -R tmpb push tmpd
358 358 pushing to tmpd
359 359 searching for changes
360 360 adding changesets
361 361 adding manifests
362 362 adding file changes
363 363 added 4 changesets with 4 changes to 4 files (+1 heads)
364 364 5 new obsolescence markers
365 365 $ hg -R tmpd debugobsolete | sort
366 366 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
367 367 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
368 368 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
369 369 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
370 370 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
371 371
372 372 Check obsolete keys are exchanged only if source has an obsolete store
373 373
374 374 $ hg init empty
375 375 $ hg --config extensions.debugkeys=debugkeys.py -R empty push tmpd
376 376 pushing to tmpd
377 377 listkeys phases
378 378 listkeys bookmarks
379 379 no changes found
380 380 listkeys phases
381 381 [1]
382 382
383 383 clone support
384 384 (markers are copied and extinct changesets are included to allow hardlinks)
385 385
386 386 $ hg clone tmpb clone-dest
387 387 updating to branch default
388 388 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
389 389 $ hg -R clone-dest log -G --hidden
390 390 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
391 391 |
392 392 | x 5:5601fb93a350 (draft) [ ] add new_3_c
393 393 |/
394 394 | x 4:ca819180edb9 (draft) [ ] add new_2_c
395 395 |/
396 396 | x 3:cdbce2fbb163 (draft) [ ] add new_c
397 397 |/
398 398 | o 2:245bde4270cd (public) [ ] add original_c
399 399 |/
400 400 o 1:7c3bad9141dc (public) [ ] add b
401 401 |
402 402 o 0:1f0dee641bb7 (public) [ ] add a
403 403
404 404 $ hg -R clone-dest debugobsolete
405 405 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
406 406 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
407 407 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
408 408 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
409 409 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
410 410
411 411
412 412 Destination repo have existing data
413 413 ---------------------------------------
414 414
415 415 On pull
416 416
417 417 $ hg init tmpe
418 418 $ cd tmpe
419 419 $ hg debugobsolete -d '1339 0' 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00
420 420 $ hg pull ../tmpb
421 421 pulling from ../tmpb
422 422 requesting all changes
423 423 adding changesets
424 424 adding manifests
425 425 adding file changes
426 426 added 4 changesets with 4 changes to 4 files (+1 heads)
427 427 5 new obsolescence markers
428 428 (run 'hg heads' to see heads, 'hg merge' to merge)
429 429 $ hg debugobsolete
430 430 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
431 431 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
432 432 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
433 433 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
434 434 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
435 435 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
436 436
437 437
438 438 On push
439 439
440 440 $ hg push ../tmpc
441 441 pushing to ../tmpc
442 442 searching for changes
443 443 no changes found
444 444 1 new obsolescence markers
445 445 [1]
446 446 $ hg -R ../tmpc debugobsolete
447 447 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
448 448 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
449 449 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
450 450 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
451 451 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
452 452 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
453 453
454 454 detect outgoing obsolete and unstable
455 455 ---------------------------------------
456 456
457 457
458 458 $ hg log -G
459 459 o 3:6f9641995072 (draft) [tip ] add n3w_3_c
460 460 |
461 461 | o 2:245bde4270cd (public) [ ] add original_c
462 462 |/
463 463 o 1:7c3bad9141dc (public) [ ] add b
464 464 |
465 465 o 0:1f0dee641bb7 (public) [ ] add a
466 466
467 467 $ hg up 'desc("n3w_3_c")'
468 468 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
469 469 $ mkcommit original_d
470 470 $ mkcommit original_e
471 471 $ hg debugobsolete --record-parents `getid original_d` -d '0 0'
472 472 $ hg debugobsolete | grep `getid original_d`
473 473 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
474 474 $ hg log -r 'obsolete()'
475 475 4:94b33453f93b (draft) [ ] add original_d
476 476 $ hg summary
477 477 parent: 5:cda648ca50f5 tip
478 478 add original_e
479 479 branch: default
480 480 commit: (clean)
481 481 update: 1 new changesets, 2 branch heads (merge)
482 482 phases: 3 draft
483 483 unstable: 1 changesets
484 484 $ hg log -G -r '::unstable()'
485 485 @ 5:cda648ca50f5 (draft) [tip ] add original_e
486 486 |
487 487 x 4:94b33453f93b (draft) [ ] add original_d
488 488 |
489 489 o 3:6f9641995072 (draft) [ ] add n3w_3_c
490 490 |
491 491 o 1:7c3bad9141dc (public) [ ] add b
492 492 |
493 493 o 0:1f0dee641bb7 (public) [ ] add a
494 494
495 495
496 496 refuse to push obsolete changeset
497 497
498 498 $ hg push ../tmpc/ -r 'desc("original_d")'
499 499 pushing to ../tmpc/
500 500 searching for changes
501 501 abort: push includes obsolete changeset: 94b33453f93b!
502 502 [255]
503 503
504 504 refuse to push unstable changeset
505 505
506 506 $ hg push ../tmpc/
507 507 pushing to ../tmpc/
508 508 searching for changes
509 509 abort: push includes unstable changeset: cda648ca50f5!
510 510 [255]
511 511
512 512 Test that extinct changeset are properly detected
513 513
514 514 $ hg log -r 'extinct()'
515 515
516 516 Don't try to push extinct changeset
517 517
518 518 $ hg init ../tmpf
519 519 $ hg out ../tmpf
520 520 comparing with ../tmpf
521 521 searching for changes
522 522 0:1f0dee641bb7 (public) [ ] add a
523 523 1:7c3bad9141dc (public) [ ] add b
524 524 2:245bde4270cd (public) [ ] add original_c
525 525 3:6f9641995072 (draft) [ ] add n3w_3_c
526 526 4:94b33453f93b (draft) [ ] add original_d
527 527 5:cda648ca50f5 (draft) [tip ] add original_e
528 528 $ hg push ../tmpf -f # -f because be push unstable too
529 529 pushing to ../tmpf
530 530 searching for changes
531 531 adding changesets
532 532 adding manifests
533 533 adding file changes
534 534 added 6 changesets with 6 changes to 6 files (+1 heads)
535 535 7 new obsolescence markers
536 536
537 537 no warning displayed
538 538
539 539 $ hg push ../tmpf
540 540 pushing to ../tmpf
541 541 searching for changes
542 542 no changes found
543 543 [1]
544 544
545 545 Do not warn about new head when the new head is a successors of a remote one
546 546
547 547 $ hg log -G
548 548 @ 5:cda648ca50f5 (draft) [tip ] add original_e
549 549 |
550 550 x 4:94b33453f93b (draft) [ ] add original_d
551 551 |
552 552 o 3:6f9641995072 (draft) [ ] add n3w_3_c
553 553 |
554 554 | o 2:245bde4270cd (public) [ ] add original_c
555 555 |/
556 556 o 1:7c3bad9141dc (public) [ ] add b
557 557 |
558 558 o 0:1f0dee641bb7 (public) [ ] add a
559 559
560 560 $ hg up -q 'desc(n3w_3_c)'
561 561 $ mkcommit obsolete_e
562 562 created new head
563 563 $ hg debugobsolete `getid 'original_e'` `getid 'obsolete_e'`
564 564 $ hg outgoing ../tmpf # parasite hg outgoing testin
565 565 comparing with ../tmpf
566 566 searching for changes
567 567 6:3de5eca88c00 (draft) [tip ] add obsolete_e
568 568 $ hg push ../tmpf
569 569 pushing to ../tmpf
570 570 searching for changes
571 571 adding changesets
572 572 adding manifests
573 573 adding file changes
574 574 added 1 changesets with 1 changes to 1 files (+1 heads)
575 575 1 new obsolescence markers
576 576
577 577 test relevance computation
578 578 ---------------------------------------
579 579
580 580 Checking simple case of "marker relevance".
581 581
582 582
583 583 Reminder of the repo situation
584 584
585 585 $ hg log --hidden --graph
586 586 @ 6:3de5eca88c00 (draft) [tip ] add obsolete_e
587 587 |
588 588 | x 5:cda648ca50f5 (draft) [ ] add original_e
589 589 | |
590 590 | x 4:94b33453f93b (draft) [ ] add original_d
591 591 |/
592 592 o 3:6f9641995072 (draft) [ ] add n3w_3_c
593 593 |
594 594 | o 2:245bde4270cd (public) [ ] add original_c
595 595 |/
596 596 o 1:7c3bad9141dc (public) [ ] add b
597 597 |
598 598 o 0:1f0dee641bb7 (public) [ ] add a
599 599
600 600
601 601 List of all markers
602 602
603 603 $ hg debugobsolete
604 604 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
605 605 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
606 606 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
607 607 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
608 608 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
609 609 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
610 610 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
611 611 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test'} (glob)
612 612
613 613 List of changesets with no chain
614 614
615 615 $ hg debugobsolete --hidden --rev ::2
616 616
617 617 List of changesets that are included on marker chain
618 618
619 619 $ hg debugobsolete --hidden --rev 6
620 620 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test'} (glob)
621 621
622 622 List of changesets with a longer chain, (including a pruned children)
623 623
624 624 $ hg debugobsolete --hidden --rev 3
625 625 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
626 626 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
627 627 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
628 628 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
629 629 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
630 630 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
631 631 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
632 632
633 633 List of both
634 634
635 635 $ hg debugobsolete --hidden --rev 3::6
636 636 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
637 637 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
638 638 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
639 639 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
640 640 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
641 641 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
642 642 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test'} (glob)
643 643 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
644 644
645 645 #if serve
646 646
647 647 Test the debug output for exchange
648 648 ----------------------------------
649 649
650 650 $ hg pull ../tmpb --config 'experimental.obsmarkers-exchange-debug=True' --config 'experimental.bundle2-exp=True'
651 651 pulling from ../tmpb
652 652 searching for changes
653 653 no changes found
654 654 obsmarker-exchange: 346 bytes received
655 655
656 656 check hgweb does not explode
657 657 ====================================
658 658
659 659 $ hg unbundle $TESTDIR/bundles/hgweb+obs.hg
660 660 adding changesets
661 661 adding manifests
662 662 adding file changes
663 663 added 62 changesets with 63 changes to 9 files (+60 heads)
664 664 (run 'hg heads .' to see heads, 'hg merge' to merge)
665 665 $ for node in `hg log -r 'desc(babar_)' --template '{node}\n'`;
666 666 > do
667 667 > hg debugobsolete $node
668 668 > done
669 669 $ hg up tip
670 670 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
671 671
672 672 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
673 673 $ cat hg.pid >> $DAEMON_PIDS
674 674
675 675 check changelog view
676 676
677 677 $ get-with-headers.py --headeronly localhost:$HGPORT 'shortlog/'
678 678 200 Script output follows
679 679
680 680 check graph view
681 681
682 682 $ get-with-headers.py --headeronly localhost:$HGPORT 'graph'
683 683 200 Script output follows
684 684
685 685 check filelog view
686 686
687 687 $ get-with-headers.py --headeronly localhost:$HGPORT 'log/'`hg log -r . -T "{node}"`/'babar'
688 688 200 Script output follows
689 689
690 690 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/68'
691 691 200 Script output follows
692 692 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/67'
693 693 404 Not Found
694 694 [1]
695 695
696 696 check that web.view config option:
697 697
698 698 $ killdaemons.py hg.pid
699 699 $ cat >> .hg/hgrc << EOF
700 700 > [web]
701 701 > view=all
702 702 > EOF
703 703 $ wait
704 704 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
705 705 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/67'
706 706 200 Script output follows
707 707 $ killdaemons.py hg.pid
708 708
709 709 Checking _enable=False warning if obsolete marker exists
710 710
711 711 $ echo '[experimental]' >> $HGRCPATH
712 712 $ echo "evolution=" >> $HGRCPATH
713 713 $ hg log -r tip
714 714 obsolete feature not enabled but 68 markers found!
715 715 68:c15e9edfca13 (draft) [tip ] add celestine
716 716
717 717 reenable for later test
718 718
719 719 $ echo '[experimental]' >> $HGRCPATH
720 720 $ echo "evolution=createmarkers,exchange" >> $HGRCPATH
721 721
722 722 #endif
723 723
724 724 Test incoming/outcoming with changesets obsoleted remotely, known locally
725 725 ===============================================================================
726 726
727 727 This test issue 3805
728 728
729 729 $ hg init repo-issue3805
730 730 $ cd repo-issue3805
731 731 $ echo "base" > base
732 732 $ hg ci -Am "base"
733 733 adding base
734 734 $ echo "foo" > foo
735 735 $ hg ci -Am "A"
736 736 adding foo
737 737 $ hg clone . ../other-issue3805
738 738 updating to branch default
739 739 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
740 740 $ echo "bar" >> foo
741 741 $ hg ci --amend
742 742 $ cd ../other-issue3805
743 743 $ hg log -G
744 744 @ 1:29f0c6921ddd (draft) [tip ] A
745 745 |
746 746 o 0:d20a80d4def3 (draft) [ ] base
747 747
748 748 $ hg log -G -R ../repo-issue3805
749 749 @ 3:323a9c3ddd91 (draft) [tip ] A
750 750 |
751 751 o 0:d20a80d4def3 (draft) [ ] base
752 752
753 753 $ hg incoming
754 754 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
755 755 searching for changes
756 756 3:323a9c3ddd91 (draft) [tip ] A
757 757 $ hg incoming --bundle ../issue3805.hg
758 758 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
759 759 searching for changes
760 760 3:323a9c3ddd91 (draft) [tip ] A
761 761 $ hg outgoing
762 762 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
763 763 searching for changes
764 764 1:29f0c6921ddd (draft) [tip ] A
765 765
766 766 #if serve
767 767
768 768 $ hg serve -R ../repo-issue3805 -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
769 769 $ cat hg.pid >> $DAEMON_PIDS
770 770
771 771 $ hg incoming http://localhost:$HGPORT
772 772 comparing with http://localhost:$HGPORT/
773 773 searching for changes
774 774 2:323a9c3ddd91 (draft) [tip ] A
775 775 $ hg outgoing http://localhost:$HGPORT
776 776 comparing with http://localhost:$HGPORT/
777 777 searching for changes
778 778 1:29f0c6921ddd (draft) [tip ] A
779 779
780 780 $ killdaemons.py
781 781
782 782 #endif
783 783
784 784 This test issue 3814
785 785
786 786 (nothing to push but locally hidden changeset)
787 787
788 788 $ cd ..
789 789 $ hg init repo-issue3814
790 790 $ cd repo-issue3805
791 791 $ hg push -r 323a9c3ddd91 ../repo-issue3814
792 792 pushing to ../repo-issue3814
793 793 searching for changes
794 794 adding changesets
795 795 adding manifests
796 796 adding file changes
797 797 added 2 changesets with 2 changes to 2 files
798 798 2 new obsolescence markers
799 799 $ hg out ../repo-issue3814
800 800 comparing with ../repo-issue3814
801 801 searching for changes
802 802 no changes found
803 803 [1]
804 804
805 805 Test that a local tag blocks a changeset from being hidden
806 806
807 807 $ hg tag -l visible -r 1 --hidden
808 808 $ hg log -G
809 809 @ 3:323a9c3ddd91 (draft) [tip ] A
810 810 |
811 811 | x 1:29f0c6921ddd (draft) [visible ] A
812 812 |/
813 813 o 0:d20a80d4def3 (draft) [ ] base
814 814
815 815 Test that removing a local tag does not cause some commands to fail
816 816
817 817 $ hg tag -l -r tip tiptag
818 818 $ hg tags
819 819 tiptag 3:323a9c3ddd91
820 820 tip 3:323a9c3ddd91
821 821 visible 1:29f0c6921ddd
822 822 $ hg --config extensions.strip= strip -r tip --no-backup
823 823 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
824 824 $ hg tags
825 825 visible 1:29f0c6921ddd
826 826 tip 1:29f0c6921ddd
827 827
828 828 Test bundle overlay onto hidden revision
829 829
830 830 $ cd ..
831 831 $ hg init repo-bundleoverlay
832 832 $ cd repo-bundleoverlay
833 833 $ echo "A" > foo
834 834 $ hg ci -Am "A"
835 835 adding foo
836 836 $ echo "B" >> foo
837 837 $ hg ci -m "B"
838 838 $ hg up 0
839 839 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
840 840 $ echo "C" >> foo
841 841 $ hg ci -m "C"
842 842 created new head
843 843 $ hg log -G
844 844 @ 2:c186d7714947 (draft) [tip ] C
845 845 |
846 846 | o 1:44526ebb0f98 (draft) [ ] B
847 847 |/
848 848 o 0:4b34ecfb0d56 (draft) [ ] A
849 849
850 850
851 851 $ hg clone -r1 . ../other-bundleoverlay
852 852 adding changesets
853 853 adding manifests
854 854 adding file changes
855 855 added 2 changesets with 2 changes to 1 files
856 856 updating to branch default
857 857 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
858 858 $ cd ../other-bundleoverlay
859 859 $ echo "B+" >> foo
860 860 $ hg ci --amend -m "B+"
861 861 $ hg log -G --hidden
862 862 @ 3:b7d587542d40 (draft) [tip ] B+
863 863 |
864 864 | x 2:eb95e9297e18 (draft) [ ] temporary amend commit for 44526ebb0f98
865 865 | |
866 866 | x 1:44526ebb0f98 (draft) [ ] B
867 867 |/
868 868 o 0:4b34ecfb0d56 (draft) [ ] A
869 869
870 870
871 871 $ hg incoming ../repo-bundleoverlay --bundle ../bundleoverlay.hg
872 872 comparing with ../repo-bundleoverlay
873 873 searching for changes
874 874 1:44526ebb0f98 (draft) [ ] B
875 875 2:c186d7714947 (draft) [tip ] C
876 876 $ hg log -G -R ../bundleoverlay.hg
877 877 o 4:c186d7714947 (draft) [tip ] C
878 878 |
879 879 | @ 3:b7d587542d40 (draft) [ ] B+
880 880 |/
881 881 o 0:4b34ecfb0d56 (draft) [ ] A
882 882
883 883
884 884 #if serve
885 885
886 886 Test issue 4506
887 887
888 888 $ cd ..
889 889 $ hg init repo-issue4506
890 890 $ cd repo-issue4506
891 891 $ echo "0" > foo
892 892 $ hg add foo
893 893 $ hg ci -m "content-0"
894 894
895 895 $ hg up null
896 896 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
897 897 $ echo "1" > bar
898 898 $ hg add bar
899 899 $ hg ci -m "content-1"
900 900 created new head
901 901 $ hg up 0
902 902 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
903 903 $ hg graft 1
904 904 grafting 1:1c9eddb02162 "content-1" (tip)
905 905
906 906 $ hg debugobsolete `hg log -r1 -T'{node}'` `hg log -r2 -T'{node}'`
907 907
908 908 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
909 909 $ cat hg.pid >> $DAEMON_PIDS
910 910
911 911 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/1'
912 912 404 Not Found
913 913 [1]
914 914 $ get-with-headers.py --headeronly localhost:$HGPORT 'file/tip/bar'
915 915 200 Script output follows
916 916 $ get-with-headers.py --headeronly localhost:$HGPORT 'annotate/tip/bar'
917 917 200 Script output follows
918 918
919 919 $ killdaemons.py
920 920
921 921 #endif
922 922
923 923 Test heads computation on pending index changes with obsolescence markers
924 924 $ cd ..
925 925 $ cat >$TESTTMP/test_extension.py << EOF
926 926 > from mercurial import cmdutil
927 927 > from mercurial.i18n import _
928 928 >
929 929 > cmdtable = {}
930 930 > command = cmdutil.command(cmdtable)
931 931 > @command("amendtransient",[], _('hg amendtransient [rev]'))
932 932 > def amend(ui, repo, *pats, **opts):
933 933 > def commitfunc(ui, repo, message, match, opts):
934 934 > return repo.commit(message, repo['.'].user(), repo['.'].date(), match)
935 935 > opts['message'] = 'Test'
936 936 > opts['logfile'] = None
937 937 > cmdutil.amend(ui, repo, commitfunc, repo['.'], {}, pats, opts)
938 938 > print repo.changelog.headrevs()
939 939 > EOF
940 940 $ cat >> $HGRCPATH << EOF
941 941 > [extensions]
942 942 > testextension=$TESTTMP/test_extension.py
943 943 > EOF
944 944 $ hg init repo-issue-nativerevs-pending-changes
945 945 $ cd repo-issue-nativerevs-pending-changes
946 946 $ mkcommit a
947 947 $ mkcommit b
948 948 $ hg up ".^"
949 949 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
950 950 $ echo aa > a
951 951 $ hg amendtransient
952 952 [1, 3]
953 953
954 Check that corrupted hidden cache does not crash
955
956 $ printf "" > .hg/cache/hidden
957 $ hg log -r . -T '{node}' --debug
958 corrupted hidden cache
959 8fd96dfc63e51ed5a8af1bec18eb4b19dbf83812 (no-eol)
960 $ hg log -r . -T '{node}' --debug
961 8fd96dfc63e51ed5a8af1bec18eb4b19dbf83812 (no-eol)
962
963 Check that wrong hidden cache permission does not crash
964
965 $ chmod 000 .hg/cache/hidden
966 $ hg log -r . -T '{node}' --debug
967 cannot read hidden cache
968 error writing hidden changesets cache
969 8fd96dfc63e51ed5a8af1bec18eb4b19dbf83812 (no-eol)
970
954 971 Test cache consistency for the visible filter
955 972 1) We want to make sure that the cached filtered revs are invalidated when
956 973 bookmarks change
957 974 $ cd ..
958 975 $ cat >$TESTTMP/test_extension.py << EOF
959 976 > from mercurial import cmdutil, extensions, bookmarks, repoview
960 977 > def _bookmarkchanged(orig, bkmstoreinst, *args, **kwargs):
961 978 > repo = bkmstoreinst._repo
962 979 > ret = orig(bkmstoreinst, *args, **kwargs)
963 980 > hidden1 = repoview.computehidden(repo)
964 981 > hidden = repoview.filterrevs(repo, 'visible')
965 982 > if sorted(hidden1) != sorted(hidden):
966 983 > print "cache inconsistency"
967 984 > return ret
968 985 > def extsetup(ui):
969 986 > extensions.wrapfunction(bookmarks.bmstore, 'write', _bookmarkchanged)
970 987 > EOF
971 988
972 989 $ hg init repo-cache-inconsistency
973 990 $ cd repo-issue-nativerevs-pending-changes
974 991 $ mkcommit a
975 992 a already tracked!
976 993 $ mkcommit b
977 994 $ hg id
978 995 13bedc178fce tip
979 996 $ echo "hello" > b
980 997 $ hg commit --amend -m "message"
981 998 $ hg book bookb -r 13bedc178fce --hidden
982 999 $ hg log -r 13bedc178fce
983 1000 5:13bedc178fce (draft) [ bookb] add b
984 1001 $ hg book -d bookb
985 1002 $ hg log -r 13bedc178fce
986 1003 abort: hidden revision '13bedc178fce'!
987 1004 (use --hidden to access hidden revisions)
988 1005 [255]
989 1006
990 1007
991 1008
General Comments 0
You need to be logged in to leave comments. Login now