##// END OF EJS Templates
changelog: fix readpending if no pending data exist (issue4609)...
Pierre-Yves David -
r24822:8678b1ea stable
parent child Browse files
Show More
@@ -1,385 +1,387 b''
1 1 # changelog.py - changelog class for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from node import bin, hex, nullid
9 9 from i18n import _
10 10 import util, error, revlog, encoding
11 11
12 12 _defaultextra = {'branch': 'default'}
13 13
14 14 def _string_escape(text):
15 15 """
16 16 >>> d = {'nl': chr(10), 'bs': chr(92), 'cr': chr(13), 'nul': chr(0)}
17 17 >>> s = "ab%(nl)scd%(bs)s%(bs)sn%(nul)sab%(cr)scd%(bs)s%(nl)s" % d
18 18 >>> s
19 19 'ab\\ncd\\\\\\\\n\\x00ab\\rcd\\\\\\n'
20 20 >>> res = _string_escape(s)
21 21 >>> s == res.decode('string_escape')
22 22 True
23 23 """
24 24 # subset of the string_escape codec
25 25 text = text.replace('\\', '\\\\').replace('\n', '\\n').replace('\r', '\\r')
26 26 return text.replace('\0', '\\0')
27 27
28 28 def decodeextra(text):
29 29 """
30 30 >>> sorted(decodeextra(encodeextra({'foo': 'bar', 'baz': chr(0) + '2'})
31 31 ... ).iteritems())
32 32 [('baz', '\\x002'), ('branch', 'default'), ('foo', 'bar')]
33 33 >>> sorted(decodeextra(encodeextra({'foo': 'bar',
34 34 ... 'baz': chr(92) + chr(0) + '2'})
35 35 ... ).iteritems())
36 36 [('baz', '\\\\\\x002'), ('branch', 'default'), ('foo', 'bar')]
37 37 """
38 38 extra = _defaultextra.copy()
39 39 for l in text.split('\0'):
40 40 if l:
41 41 if '\\0' in l:
42 42 # fix up \0 without getting into trouble with \\0
43 43 l = l.replace('\\\\', '\\\\\n')
44 44 l = l.replace('\\0', '\0')
45 45 l = l.replace('\n', '')
46 46 k, v = l.decode('string_escape').split(':', 1)
47 47 extra[k] = v
48 48 return extra
49 49
50 50 def encodeextra(d):
51 51 # keys must be sorted to produce a deterministic changelog entry
52 52 items = [_string_escape('%s:%s' % (k, d[k])) for k in sorted(d)]
53 53 return "\0".join(items)
54 54
55 55 def stripdesc(desc):
56 56 """strip trailing whitespace and leading and trailing empty lines"""
57 57 return '\n'.join([l.rstrip() for l in desc.splitlines()]).strip('\n')
58 58
59 59 class appender(object):
60 60 '''the changelog index must be updated last on disk, so we use this class
61 61 to delay writes to it'''
62 62 def __init__(self, vfs, name, mode, buf):
63 63 self.data = buf
64 64 fp = vfs(name, mode)
65 65 self.fp = fp
66 66 self.offset = fp.tell()
67 67 self.size = vfs.fstat(fp).st_size
68 68
69 69 def end(self):
70 70 return self.size + len("".join(self.data))
71 71 def tell(self):
72 72 return self.offset
73 73 def flush(self):
74 74 pass
75 75 def close(self):
76 76 self.fp.close()
77 77
78 78 def seek(self, offset, whence=0):
79 79 '''virtual file offset spans real file and data'''
80 80 if whence == 0:
81 81 self.offset = offset
82 82 elif whence == 1:
83 83 self.offset += offset
84 84 elif whence == 2:
85 85 self.offset = self.end() + offset
86 86 if self.offset < self.size:
87 87 self.fp.seek(self.offset)
88 88
89 89 def read(self, count=-1):
90 90 '''only trick here is reads that span real file and data'''
91 91 ret = ""
92 92 if self.offset < self.size:
93 93 s = self.fp.read(count)
94 94 ret = s
95 95 self.offset += len(s)
96 96 if count > 0:
97 97 count -= len(s)
98 98 if count != 0:
99 99 doff = self.offset - self.size
100 100 self.data.insert(0, "".join(self.data))
101 101 del self.data[1:]
102 102 s = self.data[0][doff:doff + count]
103 103 self.offset += len(s)
104 104 ret += s
105 105 return ret
106 106
107 107 def write(self, s):
108 108 self.data.append(str(s))
109 109 self.offset += len(s)
110 110
111 111 def _divertopener(opener, target):
112 112 """build an opener that writes in 'target.a' instead of 'target'"""
113 113 def _divert(name, mode='r'):
114 114 if name != target:
115 115 return opener(name, mode)
116 116 return opener(name + ".a", mode)
117 117 return _divert
118 118
119 119 def _delayopener(opener, target, buf):
120 120 """build an opener that stores chunks in 'buf' instead of 'target'"""
121 121 def _delay(name, mode='r'):
122 122 if name != target:
123 123 return opener(name, mode)
124 124 return appender(opener, name, mode, buf)
125 125 return _delay
126 126
127 127 class changelog(revlog.revlog):
128 128 def __init__(self, opener):
129 129 revlog.revlog.__init__(self, opener, "00changelog.i")
130 130 if self._initempty:
131 131 # changelogs don't benefit from generaldelta
132 132 self.version &= ~revlog.REVLOGGENERALDELTA
133 133 self._generaldelta = False
134 134 self._realopener = opener
135 135 self._delayed = False
136 136 self._delaybuf = None
137 137 self._divert = False
138 138 self.filteredrevs = frozenset()
139 139
140 140 def tip(self):
141 141 """filtered version of revlog.tip"""
142 142 for i in xrange(len(self) -1, -2, -1):
143 143 if i not in self.filteredrevs:
144 144 return self.node(i)
145 145
146 146 def __contains__(self, rev):
147 147 """filtered version of revlog.__contains__"""
148 148 return (0 <= rev < len(self)
149 149 and rev not in self.filteredrevs)
150 150
151 151 def __iter__(self):
152 152 """filtered version of revlog.__iter__"""
153 153 if len(self.filteredrevs) == 0:
154 154 return revlog.revlog.__iter__(self)
155 155
156 156 def filterediter():
157 157 for i in xrange(len(self)):
158 158 if i not in self.filteredrevs:
159 159 yield i
160 160
161 161 return filterediter()
162 162
163 163 def revs(self, start=0, stop=None):
164 164 """filtered version of revlog.revs"""
165 165 for i in super(changelog, self).revs(start, stop):
166 166 if i not in self.filteredrevs:
167 167 yield i
168 168
169 169 @util.propertycache
170 170 def nodemap(self):
171 171 # XXX need filtering too
172 172 self.rev(self.node(0))
173 173 return self._nodecache
174 174
175 175 def hasnode(self, node):
176 176 """filtered version of revlog.hasnode"""
177 177 try:
178 178 i = self.rev(node)
179 179 return i not in self.filteredrevs
180 180 except KeyError:
181 181 return False
182 182
183 183 def headrevs(self):
184 184 if self.filteredrevs:
185 185 try:
186 186 return self.index.headrevsfiltered(self.filteredrevs)
187 187 # AttributeError covers non-c-extension environments and
188 188 # old c extensions without filter handling.
189 189 except AttributeError:
190 190 return self._headrevs()
191 191
192 192 return super(changelog, self).headrevs()
193 193
194 194 def strip(self, *args, **kwargs):
195 195 # XXX make something better than assert
196 196 # We can't expect proper strip behavior if we are filtered.
197 197 assert not self.filteredrevs
198 198 super(changelog, self).strip(*args, **kwargs)
199 199
200 200 def rev(self, node):
201 201 """filtered version of revlog.rev"""
202 202 r = super(changelog, self).rev(node)
203 203 if r in self.filteredrevs:
204 204 raise error.FilteredLookupError(hex(node), self.indexfile,
205 205 _('filtered node'))
206 206 return r
207 207
208 208 def node(self, rev):
209 209 """filtered version of revlog.node"""
210 210 if rev in self.filteredrevs:
211 211 raise error.FilteredIndexError(rev)
212 212 return super(changelog, self).node(rev)
213 213
214 214 def linkrev(self, rev):
215 215 """filtered version of revlog.linkrev"""
216 216 if rev in self.filteredrevs:
217 217 raise error.FilteredIndexError(rev)
218 218 return super(changelog, self).linkrev(rev)
219 219
220 220 def parentrevs(self, rev):
221 221 """filtered version of revlog.parentrevs"""
222 222 if rev in self.filteredrevs:
223 223 raise error.FilteredIndexError(rev)
224 224 return super(changelog, self).parentrevs(rev)
225 225
226 226 def flags(self, rev):
227 227 """filtered version of revlog.flags"""
228 228 if rev in self.filteredrevs:
229 229 raise error.FilteredIndexError(rev)
230 230 return super(changelog, self).flags(rev)
231 231
232 232 def delayupdate(self, tr):
233 233 "delay visibility of index updates to other readers"
234 234
235 235 if not self._delayed:
236 236 if len(self) == 0:
237 237 self._divert = True
238 238 if self._realopener.exists(self.indexfile + '.a'):
239 239 self._realopener.unlink(self.indexfile + '.a')
240 240 self.opener = _divertopener(self._realopener, self.indexfile)
241 241 else:
242 242 self._delaybuf = []
243 243 self.opener = _delayopener(self._realopener, self.indexfile,
244 244 self._delaybuf)
245 245 self._delayed = True
246 246 tr.addpending('cl-%i' % id(self), self._writepending)
247 247 tr.addfinalize('cl-%i' % id(self), self._finalize)
248 248
249 249 def _finalize(self, tr):
250 250 "finalize index updates"
251 251 self._delayed = False
252 252 self.opener = self._realopener
253 253 # move redirected index data back into place
254 254 if self._divert:
255 255 assert not self._delaybuf
256 256 tmpname = self.indexfile + ".a"
257 257 nfile = self.opener.open(tmpname)
258 258 nfile.close()
259 259 self.opener.rename(tmpname, self.indexfile)
260 260 elif self._delaybuf:
261 261 fp = self.opener(self.indexfile, 'a')
262 262 fp.write("".join(self._delaybuf))
263 263 fp.close()
264 264 self._delaybuf = None
265 265 self._divert = False
266 266 # split when we're done
267 267 self.checkinlinesize(tr)
268 268
269 269 def readpending(self, file):
270 if not self.opener.exists(file):
271 return # no pending data for changelog
270 272 r = revlog.revlog(self.opener, file)
271 273 self.index = r.index
272 274 self.nodemap = r.nodemap
273 275 self._nodecache = r._nodecache
274 276 self._chunkcache = r._chunkcache
275 277
276 278 def _writepending(self, tr):
277 279 "create a file containing the unfinalized state for pretxnchangegroup"
278 280 if self._delaybuf:
279 281 # make a temporary copy of the index
280 282 fp1 = self._realopener(self.indexfile)
281 283 pendingfilename = self.indexfile + ".a"
282 284 # register as a temp file to ensure cleanup on failure
283 285 tr.registertmp(pendingfilename)
284 286 # write existing data
285 287 fp2 = self._realopener(pendingfilename, "w")
286 288 fp2.write(fp1.read())
287 289 # add pending data
288 290 fp2.write("".join(self._delaybuf))
289 291 fp2.close()
290 292 # switch modes so finalize can simply rename
291 293 self._delaybuf = None
292 294 self._divert = True
293 295 self.opener = _divertopener(self._realopener, self.indexfile)
294 296
295 297 if self._divert:
296 298 return True
297 299
298 300 return False
299 301
300 302 def checkinlinesize(self, tr, fp=None):
301 303 if not self._delayed:
302 304 revlog.revlog.checkinlinesize(self, tr, fp)
303 305
304 306 def read(self, node):
305 307 """
306 308 format used:
307 309 nodeid\n : manifest node in ascii
308 310 user\n : user, no \n or \r allowed
309 311 time tz extra\n : date (time is int or float, timezone is int)
310 312 : extra is metadata, encoded and separated by '\0'
311 313 : older versions ignore it
312 314 files\n\n : files modified by the cset, no \n or \r allowed
313 315 (.*) : comment (free text, ideally utf-8)
314 316
315 317 changelog v0 doesn't use extra
316 318 """
317 319 text = self.revision(node)
318 320 if not text:
319 321 return (nullid, "", (0, 0), [], "", _defaultextra)
320 322 last = text.index("\n\n")
321 323 desc = encoding.tolocal(text[last + 2:])
322 324 l = text[:last].split('\n')
323 325 manifest = bin(l[0])
324 326 user = encoding.tolocal(l[1])
325 327
326 328 tdata = l[2].split(' ', 2)
327 329 if len(tdata) != 3:
328 330 time = float(tdata[0])
329 331 try:
330 332 # various tools did silly things with the time zone field.
331 333 timezone = int(tdata[1])
332 334 except ValueError:
333 335 timezone = 0
334 336 extra = _defaultextra
335 337 else:
336 338 time, timezone = float(tdata[0]), int(tdata[1])
337 339 extra = decodeextra(tdata[2])
338 340
339 341 files = l[3:]
340 342 return (manifest, user, (time, timezone), files, desc, extra)
341 343
342 344 def add(self, manifest, files, desc, transaction, p1, p2,
343 345 user, date=None, extra=None):
344 346 # Convert to UTF-8 encoded bytestrings as the very first
345 347 # thing: calling any method on a localstr object will turn it
346 348 # into a str object and the cached UTF-8 string is thus lost.
347 349 user, desc = encoding.fromlocal(user), encoding.fromlocal(desc)
348 350
349 351 user = user.strip()
350 352 # An empty username or a username with a "\n" will make the
351 353 # revision text contain two "\n\n" sequences -> corrupt
352 354 # repository since read cannot unpack the revision.
353 355 if not user:
354 356 raise error.RevlogError(_("empty username"))
355 357 if "\n" in user:
356 358 raise error.RevlogError(_("username %s contains a newline")
357 359 % repr(user))
358 360
359 361 desc = stripdesc(desc)
360 362
361 363 if date:
362 364 parseddate = "%d %d" % util.parsedate(date)
363 365 else:
364 366 parseddate = "%d %d" % util.makedate()
365 367 if extra:
366 368 branch = extra.get("branch")
367 369 if branch in ("default", ""):
368 370 del extra["branch"]
369 371 elif branch in (".", "null", "tip"):
370 372 raise error.RevlogError(_('the name \'%s\' is reserved')
371 373 % branch)
372 374 if extra:
373 375 extra = encodeextra(extra)
374 376 parseddate = "%s %s" % (parseddate, extra)
375 377 l = [hex(manifest), user, parseddate] + sorted(files) + ["", desc]
376 378 text = "\n".join(l)
377 379 return self.addrevision(text, transaction, len(self), p1, p2)
378 380
379 381 def branchinfo(self, rev):
380 382 """return the branch name and open/close state of a revision
381 383
382 384 This function exists because creating a changectx object
383 385 just to access this is costly."""
384 386 extra = self.read(rev)[5]
385 387 return encoding.tolocal(extra.get("branch")), 'close' in extra
@@ -1,602 +1,602 b''
1 1 Test exchange of common information using bundle2
2 2
3 3
4 4 $ getmainid() {
5 5 > hg -R main log --template '{node}\n' --rev "$1"
6 6 > }
7 7
8 8 enable obsolescence
9 9
10 10 $ cat > $TESTTMP/bundle2-pushkey-hook.sh << EOF
11 11 > echo pushkey: lock state after \"\$HG_NAMESPACE\"
12 12 > hg debuglock
13 13 > EOF
14 14
15 15 $ cat >> $HGRCPATH << EOF
16 16 > [experimental]
17 17 > evolution=createmarkers,exchange
18 18 > bundle2-exp=True
19 19 > [ui]
20 20 > ssh=python "$TESTDIR/dummyssh"
21 21 > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
22 22 > [web]
23 23 > push_ssl = false
24 24 > allow_push = *
25 25 > [phases]
26 26 > publish=False
27 27 > [hooks]
28 28 > pretxnclose.tip = hg log -r tip -T "pre-close-tip:{node|short} {phase} {bookmarks}\n"
29 29 > txnclose.tip = hg log -r tip -T "postclose-tip:{node|short} {phase} {bookmarks}\n"
30 30 > txnclose.env = sh -c "HG_LOCAL= python \"$TESTDIR/printenv.py\" txnclose"
31 31 > pushkey= sh "$TESTTMP/bundle2-pushkey-hook.sh"
32 32 > EOF
33 33
34 34 The extension requires a repo (currently unused)
35 35
36 36 $ hg init main
37 37 $ cd main
38 38 $ touch a
39 39 $ hg add a
40 40 $ hg commit -m 'a'
41 41 pre-close-tip:3903775176ed draft
42 42 postclose-tip:3903775176ed draft
43 43 txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
44 44
45 45 $ hg unbundle $TESTDIR/bundles/rebase.hg
46 46 adding changesets
47 47 adding manifests
48 48 adding file changes
49 49 added 8 changesets with 7 changes to 7 files (+3 heads)
50 50 pre-close-tip:02de42196ebe draft
51 51 postclose-tip:02de42196ebe draft
52 52 txnclose hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_PHASES_MOVED=1 HG_SOURCE=unbundle HG_TXNID=TXN:* HG_TXNNAME=unbundle (glob)
53 53 bundle:*/tests/bundles/rebase.hg HG_URL=bundle:*/tests/bundles/rebase.hg (glob)
54 54 (run 'hg heads' to see heads, 'hg merge' to merge)
55 55
56 56 $ cd ..
57 57
58 58 Real world exchange
59 59 =====================
60 60
61 61 Add more obsolescence information
62 62
63 63 $ hg -R main debugobsolete -d '0 0' 1111111111111111111111111111111111111111 `getmainid 9520eea781bc`
64 64 pre-close-tip:02de42196ebe draft
65 65 postclose-tip:02de42196ebe draft
66 66 txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete (glob)
67 67 $ hg -R main debugobsolete -d '0 0' 2222222222222222222222222222222222222222 `getmainid 24b6387c8c8c`
68 68 pre-close-tip:02de42196ebe draft
69 69 postclose-tip:02de42196ebe draft
70 70 txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete (glob)
71 71
72 72 clone --pull
73 73
74 74 $ hg -R main phase --public cd010b8cd998
75 pre-close-tip:000000000000 public
75 pre-close-tip:02de42196ebe draft
76 76 postclose-tip:02de42196ebe draft
77 77 txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=phase (glob)
78 78 $ hg clone main other --pull --rev 9520eea781bc
79 79 adding changesets
80 80 adding manifests
81 81 adding file changes
82 82 added 2 changesets with 2 changes to 2 files
83 83 1 new obsolescence markers
84 84 pre-close-tip:9520eea781bc draft
85 85 postclose-tip:9520eea781bc draft
86 86 txnclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:* HG_TXNNAME=pull (glob)
87 87 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
88 88 updating to branch default
89 89 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 90 $ hg -R other log -G
91 91 @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
92 92 |
93 93 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
94 94
95 95 $ hg -R other debugobsolete
96 96 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
97 97
98 98 pull
99 99
100 100 $ hg -R main phase --public 9520eea781bc
101 pre-close-tip:000000000000 public
101 pre-close-tip:02de42196ebe draft
102 102 postclose-tip:02de42196ebe draft
103 103 txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=phase (glob)
104 104 $ hg -R other pull -r 24b6387c8c8c
105 105 pulling from $TESTTMP/main (glob)
106 106 searching for changes
107 107 adding changesets
108 108 adding manifests
109 109 adding file changes
110 110 added 1 changesets with 1 changes to 1 files (+1 heads)
111 111 1 new obsolescence markers
112 112 pre-close-tip:24b6387c8c8c draft
113 113 postclose-tip:24b6387c8c8c draft
114 114 txnclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:* HG_TXNNAME=pull (glob)
115 115 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
116 116 (run 'hg heads' to see heads, 'hg merge' to merge)
117 117 $ hg -R other log -G
118 118 o 2:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F
119 119 |
120 120 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
121 121 |/
122 122 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
123 123
124 124 $ hg -R other debugobsolete
125 125 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
126 126 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
127 127
128 128 pull empty (with phase movement)
129 129
130 130 $ hg -R main phase --public 24b6387c8c8c
131 pre-close-tip:000000000000 public
131 pre-close-tip:02de42196ebe draft
132 132 postclose-tip:02de42196ebe draft
133 133 txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=phase (glob)
134 134 $ hg -R other pull -r 24b6387c8c8c
135 135 pulling from $TESTTMP/main (glob)
136 136 no changes found
137 pre-close-tip:000000000000 public
137 pre-close-tip:24b6387c8c8c public
138 138 postclose-tip:24b6387c8c8c public
139 139 txnclose hook: HG_NEW_OBSMARKERS=0 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:* HG_TXNNAME=pull (glob)
140 140 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
141 141 $ hg -R other log -G
142 142 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
143 143 |
144 144 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
145 145 |/
146 146 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
147 147
148 148 $ hg -R other debugobsolete
149 149 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
150 150 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
151 151
152 152 pull empty
153 153
154 154 $ hg -R other pull -r 24b6387c8c8c
155 155 pulling from $TESTTMP/main (glob)
156 156 no changes found
157 157 pre-close-tip:24b6387c8c8c public
158 158 postclose-tip:24b6387c8c8c public
159 159 txnclose hook: HG_NEW_OBSMARKERS=0 HG_SOURCE=pull HG_TXNID=TXN:* HG_TXNNAME=pull (glob)
160 160 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
161 161 $ hg -R other log -G
162 162 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
163 163 |
164 164 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
165 165 |/
166 166 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
167 167
168 168 $ hg -R other debugobsolete
169 169 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
170 170 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
171 171
172 172 add extra data to test their exchange during push
173 173
174 174 $ hg -R main bookmark --rev eea13746799a book_eea1
175 175 $ hg -R main debugobsolete -d '0 0' 3333333333333333333333333333333333333333 `getmainid eea13746799a`
176 176 pre-close-tip:02de42196ebe draft
177 177 postclose-tip:02de42196ebe draft
178 178 txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete (glob)
179 179 $ hg -R main bookmark --rev 02de42196ebe book_02de
180 180 $ hg -R main debugobsolete -d '0 0' 4444444444444444444444444444444444444444 `getmainid 02de42196ebe`
181 181 pre-close-tip:02de42196ebe draft book_02de
182 182 postclose-tip:02de42196ebe draft book_02de
183 183 txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete (glob)
184 184 $ hg -R main bookmark --rev 42ccdea3bb16 book_42cc
185 185 $ hg -R main debugobsolete -d '0 0' 5555555555555555555555555555555555555555 `getmainid 42ccdea3bb16`
186 186 pre-close-tip:02de42196ebe draft book_02de
187 187 postclose-tip:02de42196ebe draft book_02de
188 188 txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete (glob)
189 189 $ hg -R main bookmark --rev 5fddd98957c8 book_5fdd
190 190 $ hg -R main debugobsolete -d '0 0' 6666666666666666666666666666666666666666 `getmainid 5fddd98957c8`
191 191 pre-close-tip:02de42196ebe draft book_02de
192 192 postclose-tip:02de42196ebe draft book_02de
193 193 txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete (glob)
194 194 $ hg -R main bookmark --rev 32af7686d403 book_32af
195 195 $ hg -R main debugobsolete -d '0 0' 7777777777777777777777777777777777777777 `getmainid 32af7686d403`
196 196 pre-close-tip:02de42196ebe draft book_02de
197 197 postclose-tip:02de42196ebe draft book_02de
198 198 txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete (glob)
199 199
200 200 $ hg -R other bookmark --rev cd010b8cd998 book_eea1
201 201 $ hg -R other bookmark --rev cd010b8cd998 book_02de
202 202 $ hg -R other bookmark --rev cd010b8cd998 book_42cc
203 203 $ hg -R other bookmark --rev cd010b8cd998 book_5fdd
204 204 $ hg -R other bookmark --rev cd010b8cd998 book_32af
205 205
206 206 $ hg -R main phase --public eea13746799a
207 pre-close-tip:000000000000 public
207 pre-close-tip:02de42196ebe draft book_02de
208 208 postclose-tip:02de42196ebe draft book_02de
209 209 txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=phase (glob)
210 210
211 211 push
212 212 $ hg -R main push other --rev eea13746799a --bookmark book_eea1
213 213 pushing to other
214 214 searching for changes
215 215 pre-close-tip:eea13746799a public book_eea1
216 216 pushkey: lock state after "phases"
217 217 lock: free
218 218 wlock: free
219 219 pushkey: lock state after "bookmarks"
220 220 lock: free
221 221 wlock: free
222 222 postclose-tip:eea13746799a public book_eea1
223 223 txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_NEW_OBSMARKERS=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_PHASES_MOVED=1 HG_SOURCE=push HG_TXNID=TXN:* HG_TXNNAME=push HG_URL=push (glob)
224 224 remote: adding changesets
225 225 remote: adding manifests
226 226 remote: adding file changes
227 227 remote: added 1 changesets with 0 changes to 0 files (-1 heads)
228 228 remote: 1 new obsolescence markers
229 229 updating bookmark book_eea1
230 230 pre-close-tip:02de42196ebe draft book_02de
231 231 postclose-tip:02de42196ebe draft book_02de
232 232 txnclose hook: HG_SOURCE=push-response HG_TXNID=TXN:* HG_TXNNAME=push-response (glob)
233 233 file:/*/$TESTTMP/other HG_URL=file:$TESTTMP/other (glob)
234 234 $ hg -R other log -G
235 235 o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
236 236 |\
237 237 | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
238 238 | |
239 239 @ | 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
240 240 |/
241 241 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de book_32af book_42cc book_5fdd A
242 242
243 243 $ hg -R other debugobsolete
244 244 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
245 245 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
246 246 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
247 247
248 248 pull over ssh
249 249
250 250 $ hg -R other pull ssh://user@dummy/main -r 02de42196ebe --bookmark book_02de
251 251 pulling from ssh://user@dummy/main
252 252 searching for changes
253 253 adding changesets
254 254 adding manifests
255 255 adding file changes
256 256 added 1 changesets with 1 changes to 1 files (+1 heads)
257 257 1 new obsolescence markers
258 258 updating bookmark book_02de
259 259 pre-close-tip:02de42196ebe draft book_02de
260 260 postclose-tip:02de42196ebe draft book_02de
261 261 txnclose hook: HG_BOOKMARK_MOVED=1 HG_NEW_OBSMARKERS=1 HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:* HG_TXNNAME=pull (glob)
262 262 ssh://user@dummy/main HG_URL=ssh://user@dummy/main
263 263 (run 'hg heads' to see heads, 'hg merge' to merge)
264 264 $ hg -R other debugobsolete
265 265 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
266 266 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
267 267 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
268 268 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
269 269
270 270 pull over http
271 271
272 272 $ hg -R main serve -p $HGPORT -d --pid-file=main.pid -E main-error.log
273 273 $ cat main.pid >> $DAEMON_PIDS
274 274
275 275 $ hg -R other pull http://localhost:$HGPORT/ -r 42ccdea3bb16 --bookmark book_42cc
276 276 pulling from http://localhost:$HGPORT/
277 277 searching for changes
278 278 adding changesets
279 279 adding manifests
280 280 adding file changes
281 281 added 1 changesets with 1 changes to 1 files (+1 heads)
282 282 1 new obsolescence markers
283 283 updating bookmark book_42cc
284 284 pre-close-tip:42ccdea3bb16 draft book_42cc
285 285 postclose-tip:42ccdea3bb16 draft book_42cc
286 286 txnclose hook: HG_BOOKMARK_MOVED=1 HG_NEW_OBSMARKERS=1 HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:* HG_TXNNAME=pull (glob)
287 287 http://localhost:$HGPORT/ HG_URL=http://localhost:$HGPORT/
288 288 (run 'hg heads .' to see heads, 'hg merge' to merge)
289 289 $ cat main-error.log
290 290 $ hg -R other debugobsolete
291 291 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
292 292 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
293 293 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
294 294 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
295 295 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
296 296
297 297 push over ssh
298 298
299 299 $ hg -R main push ssh://user@dummy/other -r 5fddd98957c8 --bookmark book_5fdd
300 300 pushing to ssh://user@dummy/other
301 301 searching for changes
302 302 remote: adding changesets
303 303 remote: adding manifests
304 304 remote: adding file changes
305 305 remote: added 1 changesets with 1 changes to 1 files
306 306 remote: 1 new obsolescence markers
307 307 updating bookmark book_5fdd
308 308 remote: pre-close-tip:5fddd98957c8 draft book_5fdd
309 309 remote: pushkey: lock state after "bookmarks"
310 310 remote: lock: free
311 311 remote: wlock: free
312 312 remote: postclose-tip:5fddd98957c8 draft book_5fdd
313 313 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_NEW_OBSMARKERS=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_TXNID=TXN:* HG_TXNNAME=serve HG_URL=remote:ssh:127.0.0.1 (glob)
314 314 pre-close-tip:02de42196ebe draft book_02de
315 315 postclose-tip:02de42196ebe draft book_02de
316 316 txnclose hook: HG_SOURCE=push-response HG_TXNID=TXN:* HG_TXNNAME=push-response (glob)
317 317 ssh://user@dummy/other HG_URL=ssh://user@dummy/other
318 318 $ hg -R other log -G
319 319 o 6:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
320 320 |
321 321 o 5:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
322 322 |
323 323 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
324 324 | |
325 325 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
326 326 | |/|
327 327 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
328 328 |/ /
329 329 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
330 330 |/
331 331 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af A
332 332
333 333 $ hg -R other debugobsolete
334 334 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
335 335 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
336 336 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
337 337 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
338 338 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
339 339 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
340 340
341 341 push over http
342 342
343 343 $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
344 344 $ cat other.pid >> $DAEMON_PIDS
345 345
346 346 $ hg -R main phase --public 32af7686d403
347 pre-close-tip:000000000000 public
347 pre-close-tip:02de42196ebe draft book_02de
348 348 postclose-tip:02de42196ebe draft book_02de
349 349 txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=phase (glob)
350 350 $ hg -R main push http://localhost:$HGPORT2/ -r 32af7686d403 --bookmark book_32af
351 351 pushing to http://localhost:$HGPORT2/
352 352 searching for changes
353 353 remote: adding changesets
354 354 remote: adding manifests
355 355 remote: adding file changes
356 356 remote: added 1 changesets with 1 changes to 1 files
357 357 remote: 1 new obsolescence markers
358 358 updating bookmark book_32af
359 359 pre-close-tip:02de42196ebe draft book_02de
360 360 postclose-tip:02de42196ebe draft book_02de
361 361 txnclose hook: HG_SOURCE=push-response HG_TXNID=TXN:* HG_TXNNAME=push-response (glob)
362 362 http://localhost:$HGPORT2/ HG_URL=http://localhost:$HGPORT2/
363 363 $ cat other-error.log
364 364
365 365 Check final content.
366 366
367 367 $ hg -R other log -G
368 368 o 7:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af D
369 369 |
370 370 o 6:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
371 371 |
372 372 o 5:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
373 373 |
374 374 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
375 375 | |
376 376 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
377 377 | |/|
378 378 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
379 379 |/ /
380 380 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
381 381 |/
382 382 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
383 383
384 384 $ hg -R other debugobsolete
385 385 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
386 386 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
387 387 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
388 388 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
389 389 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
390 390 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
391 391 7777777777777777777777777777777777777777 32af7686d403cf45b5d95f2d70cebea587ac806a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
392 392
393 393 (check that no 'pending' files remain)
394 394
395 395 $ ls -1 other/.hg/bookmarks*
396 396 other/.hg/bookmarks
397 397 $ ls -1 other/.hg/store/phaseroots*
398 398 other/.hg/store/phaseroots
399 399 $ ls -1 other/.hg/store/00changelog.i*
400 400 other/.hg/store/00changelog.i
401 401
402 402 Error Handling
403 403 ==============
404 404
405 405 Check that errors are properly returned to the client during push.
406 406
407 407 Setting up
408 408
409 409 $ cat > failpush.py << EOF
410 410 > """A small extension that makes push fails when using bundle2
411 411 >
412 412 > used to test error handling in bundle2
413 413 > """
414 414 >
415 415 > from mercurial import util
416 416 > from mercurial import bundle2
417 417 > from mercurial import exchange
418 418 > from mercurial import extensions
419 419 >
420 420 > def _pushbundle2failpart(pushop, bundler):
421 421 > reason = pushop.ui.config('failpush', 'reason', None)
422 422 > part = None
423 423 > if reason == 'abort':
424 424 > bundler.newpart('test:abort')
425 425 > if reason == 'unknown':
426 426 > bundler.newpart('test:unknown')
427 427 > if reason == 'race':
428 428 > # 20 Bytes of crap
429 429 > bundler.newpart('check:heads', data='01234567890123456789')
430 430 >
431 431 > @bundle2.parthandler("test:abort")
432 432 > def handleabort(op, part):
433 433 > raise util.Abort('Abandon ship!', hint="don't panic")
434 434 >
435 435 > def uisetup(ui):
436 436 > exchange.b2partsgenmapping['failpart'] = _pushbundle2failpart
437 437 > exchange.b2partsgenorder.insert(0, 'failpart')
438 438 >
439 439 > EOF
440 440
441 441 $ cd main
442 442 $ hg up tip
443 443 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
444 444 $ echo 'I' > I
445 445 $ hg add I
446 446 $ hg ci -m 'I'
447 447 pre-close-tip:e7ec4e813ba6 draft
448 448 postclose-tip:e7ec4e813ba6 draft
449 449 txnclose hook: HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
450 450 $ hg id
451 451 e7ec4e813ba6 tip
452 452 $ cd ..
453 453
454 454 $ cat << EOF >> $HGRCPATH
455 455 > [extensions]
456 456 > failpush=$TESTTMP/failpush.py
457 457 > EOF
458 458
459 459 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
460 460 $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
461 461 $ cat other.pid >> $DAEMON_PIDS
462 462
463 463 Doing the actual push: Abort error
464 464
465 465 $ cat << EOF >> $HGRCPATH
466 466 > [failpush]
467 467 > reason = abort
468 468 > EOF
469 469
470 470 $ hg -R main push other -r e7ec4e813ba6
471 471 pushing to other
472 472 searching for changes
473 473 abort: Abandon ship!
474 474 (don't panic)
475 475 [255]
476 476
477 477 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
478 478 pushing to ssh://user@dummy/other
479 479 searching for changes
480 480 abort: Abandon ship!
481 481 (don't panic)
482 482 [255]
483 483
484 484 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
485 485 pushing to http://localhost:$HGPORT2/
486 486 searching for changes
487 487 abort: Abandon ship!
488 488 (don't panic)
489 489 [255]
490 490
491 491
492 492 Doing the actual push: unknown mandatory parts
493 493
494 494 $ cat << EOF >> $HGRCPATH
495 495 > [failpush]
496 496 > reason = unknown
497 497 > EOF
498 498
499 499 $ hg -R main push other -r e7ec4e813ba6
500 500 pushing to other
501 501 searching for changes
502 502 abort: missing support for test:unknown
503 503 [255]
504 504
505 505 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
506 506 pushing to ssh://user@dummy/other
507 507 searching for changes
508 508 abort: missing support for test:unknown
509 509 [255]
510 510
511 511 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
512 512 pushing to http://localhost:$HGPORT2/
513 513 searching for changes
514 514 abort: missing support for test:unknown
515 515 [255]
516 516
517 517 Doing the actual push: race
518 518
519 519 $ cat << EOF >> $HGRCPATH
520 520 > [failpush]
521 521 > reason = race
522 522 > EOF
523 523
524 524 $ hg -R main push other -r e7ec4e813ba6
525 525 pushing to other
526 526 searching for changes
527 527 abort: push failed:
528 528 'repository changed while pushing - please try again'
529 529 [255]
530 530
531 531 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
532 532 pushing to ssh://user@dummy/other
533 533 searching for changes
534 534 abort: push failed:
535 535 'repository changed while pushing - please try again'
536 536 [255]
537 537
538 538 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
539 539 pushing to http://localhost:$HGPORT2/
540 540 searching for changes
541 541 abort: push failed:
542 542 'repository changed while pushing - please try again'
543 543 [255]
544 544
545 545 Doing the actual push: hook abort
546 546
547 547 $ cat << EOF >> $HGRCPATH
548 548 > [failpush]
549 549 > reason =
550 550 > [hooks]
551 551 > pretxnclose.failpush = false
552 552 > EOF
553 553
554 554 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
555 555 $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
556 556 $ cat other.pid >> $DAEMON_PIDS
557 557
558 558 $ hg -R main push other -r e7ec4e813ba6
559 559 pushing to other
560 560 searching for changes
561 561 pre-close-tip:e7ec4e813ba6 draft
562 562 transaction abort!
563 563 rollback completed
564 564 remote: adding changesets
565 565 remote: adding manifests
566 566 remote: adding file changes
567 567 remote: added 1 changesets with 1 changes to 1 files
568 568 abort: pretxnclose.failpush hook exited with status 1
569 569 [255]
570 570
571 571 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
572 572 pushing to ssh://user@dummy/other
573 573 searching for changes
574 574 remote: adding changesets
575 575 remote: adding manifests
576 576 remote: adding file changes
577 577 remote: added 1 changesets with 1 changes to 1 files
578 578 abort: pretxnclose.failpush hook exited with status 1
579 579 remote: pre-close-tip:e7ec4e813ba6 draft
580 580 remote: transaction abort!
581 581 remote: rollback completed
582 582 [255]
583 583
584 584 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
585 585 pushing to http://localhost:$HGPORT2/
586 586 searching for changes
587 587 remote: adding changesets
588 588 remote: adding manifests
589 589 remote: adding file changes
590 590 remote: added 1 changesets with 1 changes to 1 files
591 591 abort: pretxnclose.failpush hook exited with status 1
592 592 [255]
593 593
594 594 (check that no 'pending' files remain)
595 595
596 596 $ ls -1 other/.hg/bookmarks*
597 597 other/.hg/bookmarks
598 598 $ ls -1 other/.hg/store/phaseroots*
599 599 other/.hg/store/phaseroots
600 600 $ ls -1 other/.hg/store/00changelog.i*
601 601 other/.hg/store/00changelog.i
602 602
@@ -1,115 +1,139 b''
1 1 Verify that pending changesets are seen by pretxn* hooks but not by other
2 2 processes that access the destination repo while the hooks are running.
3 3
4 4 The hooks (python and external) both reject changesets after some think time,
5 5 during which another process runs pull. Each hook creates a file ('notify') to
6 6 indicate to the controlling process that it is running; the process removes the
7 7 file to indicate the hook can terminate.
8 8
9 9 init env vars
10 10
11 11 $ d=`pwd`
12 12 $ maxwait=20
13 13
14 14 utility to run the test - start a push in the background and run pull
15 15
16 16 $ dotest() {
17 17 > rm -f notify
18 18 > printf 'push '; hg -R child-push tip --template '{node}\n'
19 19 > hg -R child-push -q push > push.out 2>&1 &
20 20 >
21 21 > # wait for hook to create the notify file
22 22 > i=$maxwait
23 23 > while [ ! -f notify -a $i != 0 ]; do
24 24 > sleep 1
25 25 > i=`expr $i - 1`
26 26 > done
27 27 >
28 28 > # run pull
29 29 > hg -R child-pull -q pull
30 30 > rc=$?
31 31 >
32 32 > # tell hook to finish; notify should exist.
33 33 > rm notify
34 34 > wait
35 35 >
36 36 > cat push.out
37 37 > printf 'pull '; hg -R child-pull tip --template '{node}\n'
38 38 > return $rc
39 39 > }
40 40
41 41 python hook
42 42
43 43 $ cat <<EOF > reject.py
44 44 > import os, time
45 45 > from mercurial import ui, localrepo
46 46 > def rejecthook(ui, repo, hooktype, node, **opts):
47 47 > ui.write('hook %s\\n' % repo['tip'].hex())
48 48 > # create the notify file so caller knows we're running
49 49 > fpath = os.path.join('$d', 'notify')
50 50 > f = open(fpath, 'w')
51 51 > f.close()
52 52 > # wait for ack - caller should delete the notify file
53 53 > i = $maxwait
54 54 > while os.path.exists(fpath) and i > 0:
55 55 > time.sleep(1)
56 56 > i -= 1
57 57 > return True # reject the changesets
58 58 > EOF
59 59
60 60 external hook
61 61
62 62 $ cat <<EOF > reject.sh
63 63 > printf 'hook '; hg tip --template '{node}\\n'
64 64 > # create the notify file so caller knows we're running
65 65 > fpath=$d/notify
66 66 > touch \$fpath
67 67 > # wait for ack - caller should delete the notify file
68 68 > i=$maxwait
69 69 > while [ -f \$fpath -a \$i != 0 ]; do
70 70 > sleep 1
71 71 > i=\`expr \$i - 1\`
72 72 > done
73 73 > exit 1 # reject the changesets
74 74 > EOF
75 75
76 76 create repos
77 77
78 78 $ hg init parent
79 79 $ hg clone -q parent child-push
80 80 $ hg clone -q parent child-pull
81 81 $ echo a > child-push/a
82 82 $ hg -R child-push add child-push/a
83 83 $ hg -R child-push commit -m a -d '1000000 0'
84 84
85 85 test python hook
86 86
87 87 $ cat <<EOF > parent/.hg/hgrc
88 88 > [extensions]
89 89 > reject = $d/reject.py
90 90 > [hooks]
91 91 > pretxnchangegroup = python:reject.rejecthook
92 92 > EOF
93 93
94 94 $ dotest
95 95 push 29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
96 96 hook 29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
97 97 transaction abort!
98 98 rollback completed
99 99 abort: pretxnchangegroup hook failed
100 100 pull 0000000000000000000000000000000000000000
101 101
102 102 test external hook
103 103
104 104 $ cat <<EOF > parent/.hg/hgrc
105 105 > [hooks]
106 106 > pretxnchangegroup = sh $d/reject.sh
107 107 > EOF
108 108
109 109 $ dotest
110 110 push 29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
111 111 hook 29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
112 112 transaction abort!
113 113 rollback completed
114 114 abort: pretxnchangegroup hook exited with status 1
115 115 pull 0000000000000000000000000000000000000000
116
117 Test that pending on transaction without changegroup see the normal changegroup(
118 (issue4609)
119
120 $ cat <<EOF > parent/.hg/hgrc
121 > [hooks]
122 > pretxnchangegroup=
123 > pretxnclose = hg tip -T 'tip: {node|short}\n'
124 > [phases]
125 > publishing=False
126 > EOF
127
128 setup
129
130 $ cd parent
131 $ echo a > a
132 $ hg add a
133 $ hg commit -m a
134 tip: cb9a9f314b8b
135
136 actual test
137
138 $ hg phase --public .
139 tip: cb9a9f314b8b
General Comments 0
You need to be logged in to leave comments. Login now