Show More
@@ -1,960 +1,960 b'' | |||
|
1 | 1 | # transaction.py - simple journaling scheme for mercurial |
|
2 | 2 | # |
|
3 | 3 | # This transaction scheme is intended to gracefully handle program |
|
4 | 4 | # errors and interruptions. More serious failures like system crashes |
|
5 | 5 | # can be recovered with an fsck-like tool. As the whole repository is |
|
6 | 6 | # effectively log-structured, this should amount to simply truncating |
|
7 | 7 | # anything that isn't referenced in the changelog. |
|
8 | 8 | # |
|
9 | 9 | # Copyright 2005, 2006 Olivia Mackall <olivia@selenic.com> |
|
10 | 10 | # |
|
11 | 11 | # This software may be used and distributed according to the terms of the |
|
12 | 12 | # GNU General Public License version 2 or any later version. |
|
13 | 13 | |
|
14 | 14 | import errno |
|
15 | 15 | import os |
|
16 | 16 | |
|
17 | 17 | from .i18n import _ |
|
18 | 18 | from . import ( |
|
19 | 19 | error, |
|
20 | 20 | pycompat, |
|
21 | 21 | util, |
|
22 | 22 | ) |
|
23 | 23 | from .utils import stringutil |
|
24 | 24 | |
|
25 | 25 | version = 2 |
|
26 | 26 | |
|
27 | 27 | GEN_GROUP_ALL = b'all' |
|
28 | 28 | GEN_GROUP_PRE_FINALIZE = b'prefinalize' |
|
29 | 29 | GEN_GROUP_POST_FINALIZE = b'postfinalize' |
|
30 | 30 | |
|
31 | 31 | |
|
32 | 32 | def active(func): |
|
33 | 33 | def _active(self, *args, **kwds): |
|
34 | 34 | if self._count == 0: |
|
35 | 35 | raise error.ProgrammingError( |
|
36 | 36 | b'cannot use transaction when it is already committed/aborted' |
|
37 | 37 | ) |
|
38 | 38 | return func(self, *args, **kwds) |
|
39 | 39 | |
|
40 | 40 | return _active |
|
41 | 41 | |
|
42 | 42 | |
|
43 | 43 | UNDO_BACKUP = b'%s.backupfiles' |
|
44 | 44 | |
|
45 | 45 | UNDO_FILES_MAY_NEED_CLEANUP = [ |
|
46 | 46 | # legacy entries that might exists on disk from previous version: |
|
47 | 47 | (b'store', b'%s.narrowspec'), |
|
48 | 48 | (b'plain', b'%s.narrowspec.dirstate'), |
|
49 | 49 | (b'plain', b'%s.branch'), |
|
50 | 50 | (b'plain', b'%s.bookmarks'), |
|
51 | 51 | (b'store', b'%s.phaseroots'), |
|
52 | 52 | (b'plain', b'%s.dirstate'), |
|
53 | 53 | # files actually in uses today: |
|
54 | 54 | (b'plain', b'%s.desc'), |
|
55 | 55 | # Always delete undo last to make sure we detect that a clean up is needed if |
|
56 | 56 | # the process is interrupted. |
|
57 | 57 | (b'store', b'%s'), |
|
58 | 58 | ] |
|
59 | 59 | |
|
60 | 60 | |
|
61 | 61 | def cleanup_undo_files(report, vfsmap, undo_prefix=b'undo'): |
|
62 | 62 | """remove "undo" files used by the rollback logic |
|
63 | 63 | |
|
64 | 64 | This is useful to prevent rollback running in situation were it does not |
|
65 | 65 | make sense. For example after a strip. |
|
66 | 66 | """ |
|
67 | 67 | backup_listing = UNDO_BACKUP % undo_prefix |
|
68 | 68 | |
|
69 | 69 | backup_entries = [] |
|
70 | 70 | undo_files = [] |
|
71 | 71 | svfs = vfsmap[b'store'] |
|
72 | 72 | try: |
|
73 | 73 | with svfs(backup_listing) as f: |
|
74 | 74 | backup_entries = read_backup_files(report, f) |
|
75 | 75 | except OSError as e: |
|
76 | 76 | if e.errno != errno.ENOENT: |
|
77 | 77 | msg = _(b'could not read %s: %s\n') |
|
78 | 78 | msg %= (svfs.join(backup_listing), stringutil.forcebytestr(e)) |
|
79 | 79 | report(msg) |
|
80 | 80 | |
|
81 | 81 | for location, f, backup_path, c in backup_entries: |
|
82 | 82 | if location in vfsmap and backup_path: |
|
83 | 83 | undo_files.append((vfsmap[location], backup_path)) |
|
84 | 84 | |
|
85 | 85 | undo_files.append((svfs, backup_listing)) |
|
86 | 86 | for location, undo_path in UNDO_FILES_MAY_NEED_CLEANUP: |
|
87 | 87 | undo_files.append((vfsmap[location], undo_path % undo_prefix)) |
|
88 | 88 | for undovfs, undofile in undo_files: |
|
89 | 89 | try: |
|
90 | 90 | undovfs.unlink(undofile) |
|
91 | 91 | except OSError as e: |
|
92 | 92 | if e.errno != errno.ENOENT: |
|
93 | 93 | msg = _(b'error removing %s: %s\n') |
|
94 | 94 | msg %= (undovfs.join(undofile), stringutil.forcebytestr(e)) |
|
95 | 95 | report(msg) |
|
96 | 96 | |
|
97 | 97 | |
|
98 | 98 | def _playback( |
|
99 | 99 | journal, |
|
100 | 100 | report, |
|
101 | 101 | opener, |
|
102 | 102 | vfsmap, |
|
103 | 103 | entries, |
|
104 | 104 | backupentries, |
|
105 | 105 | unlink=True, |
|
106 | 106 | checkambigfiles=None, |
|
107 | 107 | ): |
|
108 | 108 | """rollback a transaction : |
|
109 | 109 | - truncate files that have been appended to |
|
110 | 110 | - restore file backups |
|
111 | 111 | - delete temporary files |
|
112 | 112 | """ |
|
113 | 113 | backupfiles = [] |
|
114 | 114 | |
|
115 | 115 | def restore_one_backup(vfs, f, b, checkambig): |
|
116 | 116 | filepath = vfs.join(f) |
|
117 | 117 | backuppath = vfs.join(b) |
|
118 | 118 | try: |
|
119 | 119 | util.copyfile(backuppath, filepath, checkambig=checkambig) |
|
120 | 120 | backupfiles.append((vfs, b)) |
|
121 | 121 | except IOError as exc: |
|
122 | 122 | e_msg = stringutil.forcebytestr(exc) |
|
123 | 123 | report(_(b"failed to recover %s (%s)\n") % (f, e_msg)) |
|
124 | 124 | raise |
|
125 | 125 | |
|
126 | 126 | # gather all backup files that impact the store |
|
127 | 127 | # (we need this to detect files that are both backed up and truncated) |
|
128 | 128 | store_backup = {} |
|
129 | 129 | for entry in backupentries: |
|
130 | 130 | location, file_path, backup_path, cache = entry |
|
131 | 131 | vfs = vfsmap[location] |
|
132 | 132 | is_store = vfs.join(b'') == opener.join(b'') |
|
133 | 133 | if is_store and file_path and backup_path: |
|
134 | 134 | store_backup[file_path] = entry |
|
135 | 135 | copy_done = set() |
|
136 | 136 | |
|
137 | 137 | # truncate all file `f` to offset `o` |
|
138 | 138 | for f, o in sorted(dict(entries).items()): |
|
139 | 139 | # if we have a backup for `f`, we should restore it first and truncate |
|
140 | 140 | # the restored file |
|
141 | 141 | bck_entry = store_backup.get(f) |
|
142 | 142 | if bck_entry is not None: |
|
143 | 143 | location, file_path, backup_path, cache = bck_entry |
|
144 | 144 | checkambig = False |
|
145 | 145 | if checkambigfiles: |
|
146 | 146 | checkambig = (file_path, location) in checkambigfiles |
|
147 | 147 | restore_one_backup(opener, file_path, backup_path, checkambig) |
|
148 | 148 | copy_done.add(bck_entry) |
|
149 | 149 | # truncate the file to its pre-transaction size |
|
150 | 150 | if o or not unlink: |
|
151 | 151 | checkambig = checkambigfiles and (f, b'') in checkambigfiles |
|
152 | 152 | try: |
|
153 | 153 | fp = opener(f, b'a', checkambig=checkambig) |
|
154 | 154 | if fp.tell() < o: |
|
155 | 155 | raise error.Abort( |
|
156 | 156 | _( |
|
157 | 157 | b"attempted to truncate %s to %d bytes, but it was " |
|
158 | 158 | b"already %d bytes\n" |
|
159 | 159 | ) |
|
160 | 160 | % (f, o, fp.tell()) |
|
161 | 161 | ) |
|
162 | 162 | fp.truncate(o) |
|
163 | 163 | fp.close() |
|
164 | 164 | except IOError: |
|
165 | 165 | report(_(b"failed to truncate %s\n") % f) |
|
166 | 166 | raise |
|
167 | 167 | else: |
|
168 | 168 | # delete empty file |
|
169 | 169 | try: |
|
170 | 170 | opener.unlink(f) |
|
171 | 171 | except FileNotFoundError: |
|
172 | 172 | pass |
|
173 | 173 | # restore backed up files and clean up temporary files |
|
174 | 174 | for entry in backupentries: |
|
175 | 175 | if entry in copy_done: |
|
176 | 176 | continue |
|
177 | 177 | l, f, b, c = entry |
|
178 | 178 | if l not in vfsmap and c: |
|
179 | 179 | report(b"couldn't handle %s: unknown cache location %s\n" % (b, l)) |
|
180 | 180 | vfs = vfsmap[l] |
|
181 | 181 | try: |
|
182 | 182 | checkambig = checkambigfiles and (f, l) in checkambigfiles |
|
183 | 183 | if f and b: |
|
184 | 184 | restore_one_backup(vfs, f, b, checkambig) |
|
185 | 185 | else: |
|
186 | 186 | target = f or b |
|
187 | 187 | try: |
|
188 | 188 | vfs.unlink(target) |
|
189 | 189 | except FileNotFoundError: |
|
190 | 190 | # This is fine because |
|
191 | 191 | # |
|
192 | 192 | # either we are trying to delete the main file, and it is |
|
193 | 193 | # already deleted. |
|
194 | 194 | # |
|
195 | 195 | # or we are trying to delete a temporary file and it is |
|
196 | 196 | # already deleted. |
|
197 | 197 | # |
|
198 | 198 | # in both case, our target result (delete the file) is |
|
199 | 199 | # already achieved. |
|
200 | 200 | pass |
|
201 | 201 | except (IOError, OSError, error.Abort): |
|
202 | 202 | if not c: |
|
203 | 203 | raise |
|
204 | 204 | |
|
205 | 205 | # cleanup transaction state file and the backups file |
|
206 | 206 | backuppath = b"%s.backupfiles" % journal |
|
207 | 207 | if opener.exists(backuppath): |
|
208 | 208 | opener.unlink(backuppath) |
|
209 | 209 | opener.unlink(journal) |
|
210 | 210 | try: |
|
211 | 211 | for vfs, f in backupfiles: |
|
212 | 212 | if vfs.exists(f): |
|
213 | 213 | vfs.unlink(f) |
|
214 | 214 | except (IOError, OSError, error.Abort): |
|
215 | 215 | # only pure backup file remains, it is sage to ignore any error |
|
216 | 216 | pass |
|
217 | 217 | |
|
218 | 218 | |
|
219 | 219 | class transaction(util.transactional): |
|
220 | 220 | def __init__( |
|
221 | 221 | self, |
|
222 | 222 | report, |
|
223 | 223 | opener, |
|
224 | 224 | vfsmap, |
|
225 | 225 | journalname, |
|
226 | 226 | undoname=None, |
|
227 | 227 | after=None, |
|
228 | 228 | createmode=None, |
|
229 | 229 | validator=None, |
|
230 | 230 | releasefn=None, |
|
231 | 231 | checkambigfiles=None, |
|
232 | 232 | name='<unnamed>', |
|
233 | 233 | ): |
|
234 | 234 | """Begin a new transaction |
|
235 | 235 | |
|
236 | 236 | Begins a new transaction that allows rolling back writes in the event of |
|
237 | 237 | an exception. |
|
238 | 238 | |
|
239 | 239 | * `after`: called after the transaction has been committed |
|
240 | 240 | * `createmode`: the mode of the journal file that will be created |
|
241 | 241 | * `releasefn`: called after releasing (with transaction and result) |
|
242 | 242 | |
|
243 | 243 | `checkambigfiles` is a set of (path, vfs-location) tuples, |
|
244 | 244 | which determine whether file stat ambiguity should be avoided |
|
245 | 245 | for corresponded files. |
|
246 | 246 | """ |
|
247 | 247 | self._count = 1 |
|
248 | 248 | self._usages = 1 |
|
249 | 249 | self._report = report |
|
250 | 250 | # a vfs to the store content |
|
251 | 251 | self._opener = opener |
|
252 | 252 | # a map to access file in various {location -> vfs} |
|
253 | 253 | vfsmap = vfsmap.copy() |
|
254 | 254 | vfsmap[b''] = opener # set default value |
|
255 | 255 | self._vfsmap = vfsmap |
|
256 | 256 | self._after = after |
|
257 | 257 | self._offsetmap = {} |
|
258 | 258 | self._newfiles = set() |
|
259 | 259 | self._journal = journalname |
|
260 | 260 | self._journal_files = [] |
|
261 | 261 | self._undoname = undoname |
|
262 | 262 | self._queue = [] |
|
263 | 263 | # A callback to do something just after releasing transaction. |
|
264 | 264 | if releasefn is None: |
|
265 | 265 | releasefn = lambda tr, success: None |
|
266 | 266 | self._releasefn = releasefn |
|
267 | 267 | |
|
268 | 268 | self._checkambigfiles = set() |
|
269 | 269 | if checkambigfiles: |
|
270 | 270 | self._checkambigfiles.update(checkambigfiles) |
|
271 | 271 | |
|
272 | 272 | self._names = [name] |
|
273 | 273 | |
|
274 | 274 | # A dict dedicated to precisely tracking the changes introduced in the |
|
275 | 275 | # transaction. |
|
276 | 276 | self.changes = {} |
|
277 | 277 | |
|
278 | 278 | # a dict of arguments to be passed to hooks |
|
279 | 279 | self.hookargs = {} |
|
280 | 280 | self._file = opener.open(self._journal, b"w+") |
|
281 | 281 | |
|
282 | 282 | # a list of ('location', 'path', 'backuppath', cache) entries. |
|
283 | 283 | # - if 'backuppath' is empty, no file existed at backup time |
|
284 | 284 | # - if 'path' is empty, this is a temporary transaction file |
|
285 | 285 | # - if 'location' is not empty, the path is outside main opener reach. |
|
286 | 286 | # use 'location' value as a key in a vfsmap to find the right 'vfs' |
|
287 | 287 | # (cache is currently unused) |
|
288 | 288 | self._backupentries = [] |
|
289 | 289 | self._backupmap = {} |
|
290 | 290 | self._backupjournal = b"%s.backupfiles" % self._journal |
|
291 | 291 | self._backupsfile = opener.open(self._backupjournal, b'w') |
|
292 | 292 | self._backupsfile.write(b'%d\n' % version) |
|
293 | 293 | |
|
294 | 294 | if createmode is not None: |
|
295 | 295 | opener.chmod(self._journal, createmode & 0o666) |
|
296 | 296 | opener.chmod(self._backupjournal, createmode & 0o666) |
|
297 | 297 | |
|
298 | 298 | # hold file generations to be performed on commit |
|
299 | 299 | self._filegenerators = {} |
|
300 | 300 | # hold callback to write pending data for hooks |
|
301 | 301 | self._pendingcallback = {} |
|
302 | 302 | # True is any pending data have been written ever |
|
303 | 303 | self._anypending = False |
|
304 | 304 | # holds callback to call when writing the transaction |
|
305 | 305 | self._finalizecallback = {} |
|
306 | 306 | # holds callback to call when validating the transaction |
|
307 | 307 | # should raise exception if anything is wrong |
|
308 | 308 | self._validatecallback = {} |
|
309 | 309 | if validator is not None: |
|
310 | 310 | self._validatecallback[b'001-userhooks'] = validator |
|
311 | 311 | # hold callback for post transaction close |
|
312 | 312 | self._postclosecallback = {} |
|
313 | 313 | # holds callbacks to call during abort |
|
314 | 314 | self._abortcallback = {} |
|
315 | 315 | |
|
316 | 316 | def __repr__(self): |
|
317 | 317 | name = b'/'.join(self._names) |
|
318 | 318 | return '<transaction name=%s, count=%d, usages=%d>' % ( |
|
319 | 319 | name, |
|
320 | 320 | self._count, |
|
321 | 321 | self._usages, |
|
322 | 322 | ) |
|
323 | 323 | |
|
324 | 324 | def __del__(self): |
|
325 | 325 | if self._journal: |
|
326 | 326 | self._abort() |
|
327 | 327 | |
|
328 | 328 | @property |
|
329 | 329 | def finalized(self): |
|
330 | 330 | return self._finalizecallback is None |
|
331 | 331 | |
|
332 | 332 | @active |
|
333 | 333 | def startgroup(self): |
|
334 | 334 | """delay registration of file entry |
|
335 | 335 | |
|
336 | 336 | This is used by strip to delay vision of strip offset. The transaction |
|
337 | 337 | sees either none or all of the strip actions to be done.""" |
|
338 | 338 | self._queue.append([]) |
|
339 | 339 | |
|
340 | 340 | @active |
|
341 | 341 | def endgroup(self): |
|
342 | 342 | """apply delayed registration of file entry. |
|
343 | 343 | |
|
344 | 344 | This is used by strip to delay vision of strip offset. The transaction |
|
345 | 345 | sees either none or all of the strip actions to be done.""" |
|
346 | 346 | q = self._queue.pop() |
|
347 | 347 | for f, o in q: |
|
348 | 348 | self._addentry(f, o) |
|
349 | 349 | |
|
350 | 350 | @active |
|
351 | 351 | def add(self, file, offset): |
|
352 | 352 | """record the state of an append-only file before update""" |
|
353 | 353 | if ( |
|
354 | 354 | file in self._newfiles |
|
355 | 355 | or file in self._offsetmap |
|
356 | 356 | or file in self._backupmap |
|
357 | 357 | ): |
|
358 | 358 | return |
|
359 | 359 | if self._queue: |
|
360 | 360 | self._queue[-1].append((file, offset)) |
|
361 | 361 | return |
|
362 | 362 | |
|
363 | 363 | self._addentry(file, offset) |
|
364 | 364 | |
|
365 | 365 | def _addentry(self, file, offset): |
|
366 | 366 | """add a append-only entry to memory and on-disk state""" |
|
367 | 367 | if ( |
|
368 | 368 | file in self._newfiles |
|
369 | 369 | or file in self._offsetmap |
|
370 | 370 | or file in self._backupmap |
|
371 | 371 | ): |
|
372 | 372 | return |
|
373 | 373 | if offset: |
|
374 | 374 | self._offsetmap[file] = offset |
|
375 | 375 | else: |
|
376 | 376 | self._newfiles.add(file) |
|
377 | 377 | # add enough data to the journal to do the truncate |
|
378 | 378 | self._file.write(b"%s\0%d\n" % (file, offset)) |
|
379 | 379 | self._file.flush() |
|
380 | 380 | |
|
381 | 381 | @active |
|
382 | 382 | def addbackup(self, file, hardlink=True, location=b'', for_offset=False): |
|
383 | 383 | """Adds a backup of the file to the transaction |
|
384 | 384 | |
|
385 | 385 | Calling addbackup() creates a hardlink backup of the specified file |
|
386 | 386 | that is used to recover the file in the event of the transaction |
|
387 | 387 | aborting. |
|
388 | 388 | |
|
389 | 389 | * `file`: the file path, relative to .hg/store |
|
390 | 390 | * `hardlink`: use a hardlink to quickly create the backup |
|
391 | 391 | |
|
392 | 392 | If `for_offset` is set, we expect a offset for this file to have been previously recorded |
|
393 | 393 | """ |
|
394 | 394 | if self._queue: |
|
395 | 395 | msg = b'cannot use transaction.addbackup inside "group"' |
|
396 | 396 | raise error.ProgrammingError(msg) |
|
397 | 397 | |
|
398 | 398 | if file in self._newfiles or file in self._backupmap: |
|
399 | 399 | return |
|
400 | 400 | elif file in self._offsetmap and not for_offset: |
|
401 | 401 | return |
|
402 | 402 | elif for_offset and file not in self._offsetmap: |
|
403 | 403 | msg = ( |
|
404 | 404 | 'calling `addbackup` with `for_offmap=True`, ' |
|
405 | 405 | 'but no offset recorded: [%r] %r' |
|
406 | 406 | ) |
|
407 | 407 | msg %= (location, file) |
|
408 | 408 | raise error.ProgrammingError(msg) |
|
409 | 409 | |
|
410 | 410 | vfs = self._vfsmap[location] |
|
411 | 411 | dirname, filename = vfs.split(file) |
|
412 | backupfilename = b"%s.backup.%s" % (self._journal, filename) | |
|
412 | backupfilename = b"%s.backup.%s.bck" % (self._journal, filename) | |
|
413 | 413 | backupfile = vfs.reljoin(dirname, backupfilename) |
|
414 | 414 | if vfs.exists(file): |
|
415 | 415 | filepath = vfs.join(file) |
|
416 | 416 | backuppath = vfs.join(backupfile) |
|
417 | 417 | # store encoding may result in different directory here. |
|
418 | 418 | # so we have to ensure the destination directory exist |
|
419 | 419 | final_dir_name = os.path.dirname(backuppath) |
|
420 | 420 | util.makedirs(final_dir_name, mode=vfs.createmode, notindexed=True) |
|
421 | 421 | # then we can copy the backup |
|
422 | 422 | util.copyfile(filepath, backuppath, hardlink=hardlink) |
|
423 | 423 | else: |
|
424 | 424 | backupfile = b'' |
|
425 | 425 | |
|
426 | 426 | self._addbackupentry((location, file, backupfile, False)) |
|
427 | 427 | |
|
428 | 428 | def _addbackupentry(self, entry): |
|
429 | 429 | """register a new backup entry and write it to disk""" |
|
430 | 430 | self._backupentries.append(entry) |
|
431 | 431 | self._backupmap[entry[1]] = len(self._backupentries) - 1 |
|
432 | 432 | self._backupsfile.write(b"%s\0%s\0%s\0%d\n" % entry) |
|
433 | 433 | self._backupsfile.flush() |
|
434 | 434 | |
|
435 | 435 | @active |
|
436 | 436 | def registertmp(self, tmpfile, location=b''): |
|
437 | 437 | """register a temporary transaction file |
|
438 | 438 | |
|
439 | 439 | Such files will be deleted when the transaction exits (on both |
|
440 | 440 | failure and success). |
|
441 | 441 | """ |
|
442 | 442 | self._addbackupentry((location, b'', tmpfile, False)) |
|
443 | 443 | |
|
444 | 444 | @active |
|
445 | 445 | def addfilegenerator( |
|
446 | 446 | self, |
|
447 | 447 | genid, |
|
448 | 448 | filenames, |
|
449 | 449 | genfunc, |
|
450 | 450 | order=0, |
|
451 | 451 | location=b'', |
|
452 | 452 | post_finalize=False, |
|
453 | 453 | ): |
|
454 | 454 | """add a function to generates some files at transaction commit |
|
455 | 455 | |
|
456 | 456 | The `genfunc` argument is a function capable of generating proper |
|
457 | 457 | content of each entry in the `filename` tuple. |
|
458 | 458 | |
|
459 | 459 | At transaction close time, `genfunc` will be called with one file |
|
460 | 460 | object argument per entries in `filenames`. |
|
461 | 461 | |
|
462 | 462 | The transaction itself is responsible for the backup, creation and |
|
463 | 463 | final write of such file. |
|
464 | 464 | |
|
465 | 465 | The `genid` argument is used to ensure the same set of file is only |
|
466 | 466 | generated once. Call to `addfilegenerator` for a `genid` already |
|
467 | 467 | present will overwrite the old entry. |
|
468 | 468 | |
|
469 | 469 | The `order` argument may be used to control the order in which multiple |
|
470 | 470 | generator will be executed. |
|
471 | 471 | |
|
472 | 472 | The `location` arguments may be used to indicate the files are located |
|
473 | 473 | outside of the the standard directory for transaction. It should match |
|
474 | 474 | one of the key of the `transaction.vfsmap` dictionary. |
|
475 | 475 | |
|
476 | 476 | The `post_finalize` argument can be set to `True` for file generation |
|
477 | 477 | that must be run after the transaction has been finalized. |
|
478 | 478 | """ |
|
479 | 479 | # For now, we are unable to do proper backup and restore of custom vfs |
|
480 | 480 | # but for bookmarks that are handled outside this mechanism. |
|
481 | 481 | entry = (order, filenames, genfunc, location, post_finalize) |
|
482 | 482 | self._filegenerators[genid] = entry |
|
483 | 483 | |
|
484 | 484 | @active |
|
485 | 485 | def removefilegenerator(self, genid): |
|
486 | 486 | """reverse of addfilegenerator, remove a file generator function""" |
|
487 | 487 | if genid in self._filegenerators: |
|
488 | 488 | del self._filegenerators[genid] |
|
489 | 489 | |
|
490 | 490 | def _generatefiles(self, suffix=b'', group=GEN_GROUP_ALL): |
|
491 | 491 | # write files registered for generation |
|
492 | 492 | any = False |
|
493 | 493 | |
|
494 | 494 | if group == GEN_GROUP_ALL: |
|
495 | 495 | skip_post = skip_pre = False |
|
496 | 496 | else: |
|
497 | 497 | skip_pre = group == GEN_GROUP_POST_FINALIZE |
|
498 | 498 | skip_post = group == GEN_GROUP_PRE_FINALIZE |
|
499 | 499 | |
|
500 | 500 | for id, entry in sorted(self._filegenerators.items()): |
|
501 | 501 | any = True |
|
502 | 502 | order, filenames, genfunc, location, post_finalize = entry |
|
503 | 503 | |
|
504 | 504 | # for generation at closing, check if it's before or after finalize |
|
505 | 505 | if skip_post and post_finalize: |
|
506 | 506 | continue |
|
507 | 507 | elif skip_pre and not post_finalize: |
|
508 | 508 | continue |
|
509 | 509 | |
|
510 | 510 | vfs = self._vfsmap[location] |
|
511 | 511 | files = [] |
|
512 | 512 | try: |
|
513 | 513 | for name in filenames: |
|
514 | 514 | name += suffix |
|
515 | 515 | if suffix: |
|
516 | 516 | self.registertmp(name, location=location) |
|
517 | 517 | checkambig = False |
|
518 | 518 | else: |
|
519 | 519 | self.addbackup(name, location=location) |
|
520 | 520 | checkambig = (name, location) in self._checkambigfiles |
|
521 | 521 | files.append( |
|
522 | 522 | vfs(name, b'w', atomictemp=True, checkambig=checkambig) |
|
523 | 523 | ) |
|
524 | 524 | genfunc(*files) |
|
525 | 525 | for f in files: |
|
526 | 526 | f.close() |
|
527 | 527 | # skip discard() loop since we're sure no open file remains |
|
528 | 528 | del files[:] |
|
529 | 529 | finally: |
|
530 | 530 | for f in files: |
|
531 | 531 | f.discard() |
|
532 | 532 | return any |
|
533 | 533 | |
|
534 | 534 | @active |
|
535 | 535 | def findoffset(self, file): |
|
536 | 536 | if file in self._newfiles: |
|
537 | 537 | return 0 |
|
538 | 538 | return self._offsetmap.get(file) |
|
539 | 539 | |
|
540 | 540 | @active |
|
541 | 541 | def readjournal(self): |
|
542 | 542 | self._file.seek(0) |
|
543 | 543 | entries = [] |
|
544 | 544 | for l in self._file.readlines(): |
|
545 | 545 | file, troffset = l.split(b'\0') |
|
546 | 546 | entries.append((file, int(troffset))) |
|
547 | 547 | return entries |
|
548 | 548 | |
|
549 | 549 | @active |
|
550 | 550 | def replace(self, file, offset): |
|
551 | 551 | """ |
|
552 | 552 | replace can only replace already committed entries |
|
553 | 553 | that are not pending in the queue |
|
554 | 554 | """ |
|
555 | 555 | if file in self._newfiles: |
|
556 | 556 | if not offset: |
|
557 | 557 | return |
|
558 | 558 | self._newfiles.remove(file) |
|
559 | 559 | self._offsetmap[file] = offset |
|
560 | 560 | elif file in self._offsetmap: |
|
561 | 561 | if not offset: |
|
562 | 562 | del self._offsetmap[file] |
|
563 | 563 | self._newfiles.add(file) |
|
564 | 564 | else: |
|
565 | 565 | self._offsetmap[file] = offset |
|
566 | 566 | else: |
|
567 | 567 | raise KeyError(file) |
|
568 | 568 | self._file.write(b"%s\0%d\n" % (file, offset)) |
|
569 | 569 | self._file.flush() |
|
570 | 570 | |
|
571 | 571 | @active |
|
572 | 572 | def nest(self, name='<unnamed>'): |
|
573 | 573 | self._count += 1 |
|
574 | 574 | self._usages += 1 |
|
575 | 575 | self._names.append(name) |
|
576 | 576 | return self |
|
577 | 577 | |
|
578 | 578 | def release(self): |
|
579 | 579 | if self._count > 0: |
|
580 | 580 | self._usages -= 1 |
|
581 | 581 | if self._names: |
|
582 | 582 | self._names.pop() |
|
583 | 583 | # if the transaction scopes are left without being closed, fail |
|
584 | 584 | if self._count > 0 and self._usages == 0: |
|
585 | 585 | self._abort() |
|
586 | 586 | |
|
587 | 587 | def running(self): |
|
588 | 588 | return self._count > 0 |
|
589 | 589 | |
|
590 | 590 | def addpending(self, category, callback): |
|
591 | 591 | """add a callback to be called when the transaction is pending |
|
592 | 592 | |
|
593 | 593 | The transaction will be given as callback's first argument. |
|
594 | 594 | |
|
595 | 595 | Category is a unique identifier to allow overwriting an old callback |
|
596 | 596 | with a newer callback. |
|
597 | 597 | """ |
|
598 | 598 | self._pendingcallback[category] = callback |
|
599 | 599 | |
|
600 | 600 | @active |
|
601 | 601 | def writepending(self): |
|
602 | 602 | """write pending file to temporary version |
|
603 | 603 | |
|
604 | 604 | This is used to allow hooks to view a transaction before commit""" |
|
605 | 605 | categories = sorted(self._pendingcallback) |
|
606 | 606 | for cat in categories: |
|
607 | 607 | # remove callback since the data will have been flushed |
|
608 | 608 | any = self._pendingcallback.pop(cat)(self) |
|
609 | 609 | self._anypending = self._anypending or any |
|
610 | 610 | self._anypending |= self._generatefiles(suffix=b'.pending') |
|
611 | 611 | return self._anypending |
|
612 | 612 | |
|
613 | 613 | @active |
|
614 | 614 | def hasfinalize(self, category): |
|
615 | 615 | """check is a callback already exist for a category""" |
|
616 | 616 | return category in self._finalizecallback |
|
617 | 617 | |
|
618 | 618 | @active |
|
619 | 619 | def addfinalize(self, category, callback): |
|
620 | 620 | """add a callback to be called when the transaction is closed |
|
621 | 621 | |
|
622 | 622 | The transaction will be given as callback's first argument. |
|
623 | 623 | |
|
624 | 624 | Category is a unique identifier to allow overwriting old callbacks with |
|
625 | 625 | newer callbacks. |
|
626 | 626 | """ |
|
627 | 627 | self._finalizecallback[category] = callback |
|
628 | 628 | |
|
629 | 629 | @active |
|
630 | 630 | def addpostclose(self, category, callback): |
|
631 | 631 | """add or replace a callback to be called after the transaction closed |
|
632 | 632 | |
|
633 | 633 | The transaction will be given as callback's first argument. |
|
634 | 634 | |
|
635 | 635 | Category is a unique identifier to allow overwriting an old callback |
|
636 | 636 | with a newer callback. |
|
637 | 637 | """ |
|
638 | 638 | self._postclosecallback[category] = callback |
|
639 | 639 | |
|
640 | 640 | @active |
|
641 | 641 | def getpostclose(self, category): |
|
642 | 642 | """return a postclose callback added before, or None""" |
|
643 | 643 | return self._postclosecallback.get(category, None) |
|
644 | 644 | |
|
645 | 645 | @active |
|
646 | 646 | def addabort(self, category, callback): |
|
647 | 647 | """add a callback to be called when the transaction is aborted. |
|
648 | 648 | |
|
649 | 649 | The transaction will be given as the first argument to the callback. |
|
650 | 650 | |
|
651 | 651 | Category is a unique identifier to allow overwriting an old callback |
|
652 | 652 | with a newer callback. |
|
653 | 653 | """ |
|
654 | 654 | self._abortcallback[category] = callback |
|
655 | 655 | |
|
656 | 656 | @active |
|
657 | 657 | def addvalidator(self, category, callback): |
|
658 | 658 | """adds a callback to be called when validating the transaction. |
|
659 | 659 | |
|
660 | 660 | The transaction will be given as the first argument to the callback. |
|
661 | 661 | |
|
662 | 662 | callback should raise exception if to abort transaction""" |
|
663 | 663 | self._validatecallback[category] = callback |
|
664 | 664 | |
|
665 | 665 | @active |
|
666 | 666 | def close(self): |
|
667 | 667 | '''commit the transaction''' |
|
668 | 668 | if self._count == 1: |
|
669 | 669 | for category in sorted(self._validatecallback): |
|
670 | 670 | self._validatecallback[category](self) |
|
671 | 671 | self._validatecallback = None # Help prevent cycles. |
|
672 | 672 | self._generatefiles(group=GEN_GROUP_PRE_FINALIZE) |
|
673 | 673 | while self._finalizecallback: |
|
674 | 674 | callbacks = self._finalizecallback |
|
675 | 675 | self._finalizecallback = {} |
|
676 | 676 | categories = sorted(callbacks) |
|
677 | 677 | for cat in categories: |
|
678 | 678 | callbacks[cat](self) |
|
679 | 679 | # Prevent double usage and help clear cycles. |
|
680 | 680 | self._finalizecallback = None |
|
681 | 681 | self._generatefiles(group=GEN_GROUP_POST_FINALIZE) |
|
682 | 682 | |
|
683 | 683 | self._count -= 1 |
|
684 | 684 | if self._count != 0: |
|
685 | 685 | return |
|
686 | 686 | self._file.close() |
|
687 | 687 | self._backupsfile.close() |
|
688 | 688 | # cleanup temporary files |
|
689 | 689 | for l, f, b, c in self._backupentries: |
|
690 | 690 | if l not in self._vfsmap and c: |
|
691 | 691 | self._report( |
|
692 | 692 | b"couldn't remove %s: unknown cache location %s\n" % (b, l) |
|
693 | 693 | ) |
|
694 | 694 | continue |
|
695 | 695 | vfs = self._vfsmap[l] |
|
696 | 696 | if not f and b and vfs.exists(b): |
|
697 | 697 | try: |
|
698 | 698 | vfs.unlink(b) |
|
699 | 699 | except (IOError, OSError, error.Abort) as inst: |
|
700 | 700 | if not c: |
|
701 | 701 | raise |
|
702 | 702 | # Abort may be raise by read only opener |
|
703 | 703 | self._report( |
|
704 | 704 | b"couldn't remove %s: %s\n" % (vfs.join(b), inst) |
|
705 | 705 | ) |
|
706 | 706 | self._offsetmap = {} |
|
707 | 707 | self._newfiles = set() |
|
708 | 708 | self._writeundo() |
|
709 | 709 | if self._after: |
|
710 | 710 | self._after() |
|
711 | 711 | self._after = None # Help prevent cycles. |
|
712 | 712 | if self._opener.isfile(self._backupjournal): |
|
713 | 713 | self._opener.unlink(self._backupjournal) |
|
714 | 714 | if self._opener.isfile(self._journal): |
|
715 | 715 | self._opener.unlink(self._journal) |
|
716 | 716 | for l, _f, b, c in self._backupentries: |
|
717 | 717 | if l not in self._vfsmap and c: |
|
718 | 718 | self._report( |
|
719 | 719 | b"couldn't remove %s: unknown cache location" |
|
720 | 720 | b"%s\n" % (b, l) |
|
721 | 721 | ) |
|
722 | 722 | continue |
|
723 | 723 | vfs = self._vfsmap[l] |
|
724 | 724 | if b and vfs.exists(b): |
|
725 | 725 | try: |
|
726 | 726 | vfs.unlink(b) |
|
727 | 727 | except (IOError, OSError, error.Abort) as inst: |
|
728 | 728 | if not c: |
|
729 | 729 | raise |
|
730 | 730 | # Abort may be raise by read only opener |
|
731 | 731 | self._report( |
|
732 | 732 | b"couldn't remove %s: %s\n" % (vfs.join(b), inst) |
|
733 | 733 | ) |
|
734 | 734 | self._backupentries = [] |
|
735 | 735 | self._journal = None |
|
736 | 736 | |
|
737 | 737 | self._releasefn(self, True) # notify success of closing transaction |
|
738 | 738 | self._releasefn = None # Help prevent cycles. |
|
739 | 739 | |
|
740 | 740 | # run post close action |
|
741 | 741 | categories = sorted(self._postclosecallback) |
|
742 | 742 | for cat in categories: |
|
743 | 743 | self._postclosecallback[cat](self) |
|
744 | 744 | # Prevent double usage and help clear cycles. |
|
745 | 745 | self._postclosecallback = None |
|
746 | 746 | |
|
747 | 747 | @active |
|
748 | 748 | def abort(self): |
|
749 | 749 | """abort the transaction (generally called on error, or when the |
|
750 | 750 | transaction is not explicitly committed before going out of |
|
751 | 751 | scope)""" |
|
752 | 752 | self._abort() |
|
753 | 753 | |
|
754 | 754 | @active |
|
755 | 755 | def add_journal(self, vfs_id, path): |
|
756 | 756 | self._journal_files.append((vfs_id, path)) |
|
757 | 757 | |
|
758 | 758 | def _writeundo(self): |
|
759 | 759 | """write transaction data for possible future undo call""" |
|
760 | 760 | if self._undoname is None: |
|
761 | 761 | return |
|
762 | 762 | cleanup_undo_files( |
|
763 | 763 | self._report, |
|
764 | 764 | self._vfsmap, |
|
765 | 765 | undo_prefix=self._undoname, |
|
766 | 766 | ) |
|
767 | 767 | |
|
768 | 768 | def undoname(fn: bytes) -> bytes: |
|
769 | 769 | base, name = os.path.split(fn) |
|
770 | 770 | assert name.startswith(self._journal) |
|
771 | 771 | new_name = name.replace(self._journal, self._undoname, 1) |
|
772 | 772 | return os.path.join(base, new_name) |
|
773 | 773 | |
|
774 | 774 | undo_backup_path = b"%s.backupfiles" % self._undoname |
|
775 | 775 | undobackupfile = self._opener.open(undo_backup_path, b'w') |
|
776 | 776 | undobackupfile.write(b'%d\n' % version) |
|
777 | 777 | for l, f, b, c in self._backupentries: |
|
778 | 778 | if not f: # temporary file |
|
779 | 779 | continue |
|
780 | 780 | if not b: |
|
781 | 781 | u = b'' |
|
782 | 782 | else: |
|
783 | 783 | if l not in self._vfsmap and c: |
|
784 | 784 | self._report( |
|
785 | 785 | b"couldn't remove %s: unknown cache location" |
|
786 | 786 | b"%s\n" % (b, l) |
|
787 | 787 | ) |
|
788 | 788 | continue |
|
789 | 789 | vfs = self._vfsmap[l] |
|
790 | 790 | u = undoname(b) |
|
791 | 791 | util.copyfile(vfs.join(b), vfs.join(u), hardlink=True) |
|
792 | 792 | undobackupfile.write(b"%s\0%s\0%s\0%d\n" % (l, f, u, c)) |
|
793 | 793 | undobackupfile.close() |
|
794 | 794 | for vfs, src in self._journal_files: |
|
795 | 795 | dest = undoname(src) |
|
796 | 796 | # if src and dest refer to a same file, vfs.rename is a no-op, |
|
797 | 797 | # leaving both src and dest on disk. delete dest to make sure |
|
798 | 798 | # the rename couldn't be such a no-op. |
|
799 | 799 | vfs.tryunlink(dest) |
|
800 | 800 | try: |
|
801 | 801 | vfs.rename(src, dest) |
|
802 | 802 | except FileNotFoundError: # journal file does not yet exist |
|
803 | 803 | pass |
|
804 | 804 | |
|
805 | 805 | def _abort(self): |
|
806 | 806 | entries = self.readjournal() |
|
807 | 807 | self._count = 0 |
|
808 | 808 | self._usages = 0 |
|
809 | 809 | self._file.close() |
|
810 | 810 | self._backupsfile.close() |
|
811 | 811 | |
|
812 | 812 | quick = self._can_quick_abort(entries) |
|
813 | 813 | try: |
|
814 | 814 | if not quick: |
|
815 | 815 | self._report(_(b"transaction abort!\n")) |
|
816 | 816 | for cat in sorted(self._abortcallback): |
|
817 | 817 | self._abortcallback[cat](self) |
|
818 | 818 | # Prevent double usage and help clear cycles. |
|
819 | 819 | self._abortcallback = None |
|
820 | 820 | if quick: |
|
821 | 821 | self._do_quick_abort(entries) |
|
822 | 822 | else: |
|
823 | 823 | self._do_full_abort(entries) |
|
824 | 824 | finally: |
|
825 | 825 | self._journal = None |
|
826 | 826 | self._releasefn(self, False) # notify failure of transaction |
|
827 | 827 | self._releasefn = None # Help prevent cycles. |
|
828 | 828 | |
|
829 | 829 | def _can_quick_abort(self, entries): |
|
830 | 830 | """False if any semantic content have been written on disk |
|
831 | 831 | |
|
832 | 832 | True if nothing, except temporary files has been writen on disk.""" |
|
833 | 833 | if entries: |
|
834 | 834 | return False |
|
835 | 835 | for e in self._backupentries: |
|
836 | 836 | if e[1]: |
|
837 | 837 | return False |
|
838 | 838 | return True |
|
839 | 839 | |
|
840 | 840 | def _do_quick_abort(self, entries): |
|
841 | 841 | """(Silently) do a quick cleanup (see _can_quick_abort)""" |
|
842 | 842 | assert self._can_quick_abort(entries) |
|
843 | 843 | tmp_files = [e for e in self._backupentries if not e[1]] |
|
844 | 844 | for vfs_id, old_path, tmp_path, xxx in tmp_files: |
|
845 | 845 | vfs = self._vfsmap[vfs_id] |
|
846 | 846 | try: |
|
847 | 847 | vfs.unlink(tmp_path) |
|
848 | 848 | except FileNotFoundError: |
|
849 | 849 | pass |
|
850 | 850 | if self._backupjournal: |
|
851 | 851 | self._opener.unlink(self._backupjournal) |
|
852 | 852 | if self._journal: |
|
853 | 853 | self._opener.unlink(self._journal) |
|
854 | 854 | |
|
855 | 855 | def _do_full_abort(self, entries): |
|
856 | 856 | """(Noisily) rollback all the change introduced by the transaction""" |
|
857 | 857 | try: |
|
858 | 858 | _playback( |
|
859 | 859 | self._journal, |
|
860 | 860 | self._report, |
|
861 | 861 | self._opener, |
|
862 | 862 | self._vfsmap, |
|
863 | 863 | entries, |
|
864 | 864 | self._backupentries, |
|
865 | 865 | False, |
|
866 | 866 | checkambigfiles=self._checkambigfiles, |
|
867 | 867 | ) |
|
868 | 868 | self._report(_(b"rollback completed\n")) |
|
869 | 869 | except BaseException as exc: |
|
870 | 870 | self._report(_(b"rollback failed - please run hg recover\n")) |
|
871 | 871 | self._report( |
|
872 | 872 | _(b"(failure reason: %s)\n") % stringutil.forcebytestr(exc) |
|
873 | 873 | ) |
|
874 | 874 | |
|
875 | 875 | |
|
876 | 876 | BAD_VERSION_MSG = _( |
|
877 | 877 | b"journal was created by a different version of Mercurial\n" |
|
878 | 878 | ) |
|
879 | 879 | |
|
880 | 880 | |
|
881 | 881 | def read_backup_files(report, fp): |
|
882 | 882 | """parse an (already open) backup file an return contained backup entries |
|
883 | 883 | |
|
884 | 884 | entries are in the form: (location, file, backupfile, xxx) |
|
885 | 885 | |
|
886 | 886 | :location: the vfs identifier (vfsmap's key) |
|
887 | 887 | :file: original file path (in the vfs) |
|
888 | 888 | :backupfile: path of the backup (in the vfs) |
|
889 | 889 | :cache: a boolean currently always set to False |
|
890 | 890 | """ |
|
891 | 891 | lines = fp.readlines() |
|
892 | 892 | backupentries = [] |
|
893 | 893 | if lines: |
|
894 | 894 | ver = lines[0][:-1] |
|
895 | 895 | if ver != (b'%d' % version): |
|
896 | 896 | report(BAD_VERSION_MSG) |
|
897 | 897 | else: |
|
898 | 898 | for line in lines[1:]: |
|
899 | 899 | if line: |
|
900 | 900 | # Shave off the trailing newline |
|
901 | 901 | line = line[:-1] |
|
902 | 902 | l, f, b, c = line.split(b'\0') |
|
903 | 903 | backupentries.append((l, f, b, bool(c))) |
|
904 | 904 | return backupentries |
|
905 | 905 | |
|
906 | 906 | |
|
907 | 907 | def rollback( |
|
908 | 908 | opener, |
|
909 | 909 | vfsmap, |
|
910 | 910 | file, |
|
911 | 911 | report, |
|
912 | 912 | checkambigfiles=None, |
|
913 | 913 | skip_journal_pattern=None, |
|
914 | 914 | ): |
|
915 | 915 | """Rolls back the transaction contained in the given file |
|
916 | 916 | |
|
917 | 917 | Reads the entries in the specified file, and the corresponding |
|
918 | 918 | '*.backupfiles' file, to recover from an incomplete transaction. |
|
919 | 919 | |
|
920 | 920 | * `file`: a file containing a list of entries, specifying where |
|
921 | 921 | to truncate each file. The file should contain a list of |
|
922 | 922 | file\0offset pairs, delimited by newlines. The corresponding |
|
923 | 923 | '*.backupfiles' file should contain a list of file\0backupfile |
|
924 | 924 | pairs, delimited by \0. |
|
925 | 925 | |
|
926 | 926 | `checkambigfiles` is a set of (path, vfs-location) tuples, |
|
927 | 927 | which determine whether file stat ambiguity should be avoided at |
|
928 | 928 | restoring corresponded files. |
|
929 | 929 | """ |
|
930 | 930 | entries = [] |
|
931 | 931 | backupentries = [] |
|
932 | 932 | |
|
933 | 933 | with opener.open(file) as fp: |
|
934 | 934 | lines = fp.readlines() |
|
935 | 935 | for l in lines: |
|
936 | 936 | try: |
|
937 | 937 | f, o = l.split(b'\0') |
|
938 | 938 | entries.append((f, int(o))) |
|
939 | 939 | except ValueError: |
|
940 | 940 | report( |
|
941 | 941 | _(b"couldn't read journal entry %r!\n") % pycompat.bytestr(l) |
|
942 | 942 | ) |
|
943 | 943 | |
|
944 | 944 | backupjournal = b"%s.backupfiles" % file |
|
945 | 945 | if opener.exists(backupjournal): |
|
946 | 946 | with opener.open(backupjournal) as fp: |
|
947 | 947 | backupentries = read_backup_files(report, fp) |
|
948 | 948 | if skip_journal_pattern is not None: |
|
949 | 949 | keep = lambda x: not skip_journal_pattern.match(x[1]) |
|
950 | 950 | backupentries = [x for x in backupentries if keep(x)] |
|
951 | 951 | |
|
952 | 952 | _playback( |
|
953 | 953 | file, |
|
954 | 954 | report, |
|
955 | 955 | opener, |
|
956 | 956 | vfsmap, |
|
957 | 957 | entries, |
|
958 | 958 | backupentries, |
|
959 | 959 | checkambigfiles=checkambigfiles, |
|
960 | 960 | ) |
@@ -1,531 +1,531 b'' | |||
|
1 | 1 | #require repofncache |
|
2 | 2 | |
|
3 | 3 | An extension which will set fncache chunksize to 1 byte to make sure that logic |
|
4 | 4 | does not break |
|
5 | 5 | |
|
6 | 6 | $ cat > chunksize.py <<EOF |
|
7 | 7 | > from mercurial import store |
|
8 | 8 | > store.fncache_chunksize = 1 |
|
9 | 9 | > EOF |
|
10 | 10 | |
|
11 | 11 | $ cat >> $HGRCPATH <<EOF |
|
12 | 12 | > [extensions] |
|
13 | 13 | > chunksize = $TESTTMP/chunksize.py |
|
14 | 14 | > EOF |
|
15 | 15 | |
|
16 | 16 | Init repo1: |
|
17 | 17 | |
|
18 | 18 | $ hg init repo1 |
|
19 | 19 | $ cd repo1 |
|
20 | 20 | $ echo "some text" > a |
|
21 | 21 | $ hg add |
|
22 | 22 | adding a |
|
23 | 23 | $ hg ci -m first |
|
24 | 24 | $ cat .hg/store/fncache | sort |
|
25 | 25 | data/a.i |
|
26 | 26 | |
|
27 | 27 | Testing a.i/b: |
|
28 | 28 | |
|
29 | 29 | $ mkdir a.i |
|
30 | 30 | $ echo "some other text" > a.i/b |
|
31 | 31 | $ hg add |
|
32 | 32 | adding a.i/b |
|
33 | 33 | $ hg ci -m second |
|
34 | 34 | $ cat .hg/store/fncache | sort |
|
35 | 35 | data/a.i |
|
36 | 36 | data/a.i.hg/b.i |
|
37 | 37 | |
|
38 | 38 | Testing a.i.hg/c: |
|
39 | 39 | |
|
40 | 40 | $ mkdir a.i.hg |
|
41 | 41 | $ echo "yet another text" > a.i.hg/c |
|
42 | 42 | $ hg add |
|
43 | 43 | adding a.i.hg/c |
|
44 | 44 | $ hg ci -m third |
|
45 | 45 | $ cat .hg/store/fncache | sort |
|
46 | 46 | data/a.i |
|
47 | 47 | data/a.i.hg.hg/c.i |
|
48 | 48 | data/a.i.hg/b.i |
|
49 | 49 | |
|
50 | 50 | Testing verify: |
|
51 | 51 | |
|
52 | 52 | $ hg verify -q |
|
53 | 53 | |
|
54 | 54 | $ rm .hg/store/fncache |
|
55 | 55 | |
|
56 | 56 | $ hg verify |
|
57 | 57 | checking changesets |
|
58 | 58 | checking manifests |
|
59 | 59 | crosschecking files in changesets and manifests |
|
60 | 60 | checking files |
|
61 | 61 | warning: revlog 'data/a.i' not in fncache! |
|
62 | 62 | warning: revlog 'data/a.i.hg/c.i' not in fncache! |
|
63 | 63 | warning: revlog 'data/a.i/b.i' not in fncache! |
|
64 | 64 | checking dirstate |
|
65 | 65 | checked 3 changesets with 3 changes to 3 files |
|
66 | 66 | 3 warnings encountered! |
|
67 | 67 | hint: run "hg debugrebuildfncache" to recover from corrupt fncache |
|
68 | 68 | |
|
69 | 69 | Follow the hint to make sure it works |
|
70 | 70 | |
|
71 | 71 | $ hg debugrebuildfncache |
|
72 | 72 | adding data/a.i |
|
73 | 73 | adding data/a.i.hg/c.i |
|
74 | 74 | adding data/a.i/b.i |
|
75 | 75 | 3 items added, 0 removed from fncache |
|
76 | 76 | |
|
77 | 77 | $ hg verify -q |
|
78 | 78 | |
|
79 | 79 | $ cd .. |
|
80 | 80 | |
|
81 | 81 | Non store repo: |
|
82 | 82 | |
|
83 | 83 | $ hg --config format.usestore=False init foo |
|
84 | 84 | $ cd foo |
|
85 | 85 | $ mkdir tst.d |
|
86 | 86 | $ echo foo > tst.d/foo |
|
87 | 87 | $ hg ci -Amfoo |
|
88 | 88 | adding tst.d/foo |
|
89 | 89 | $ find .hg | sort |
|
90 | 90 | .hg |
|
91 | 91 | .hg/00changelog.i |
|
92 | 92 | .hg/00manifest.i |
|
93 | 93 | .hg/branch |
|
94 | 94 | .hg/cache |
|
95 | 95 | .hg/cache/branch2-served |
|
96 | 96 | .hg/cache/rbc-names-v1 |
|
97 | 97 | .hg/cache/rbc-revs-v1 |
|
98 | 98 | .hg/data |
|
99 | 99 | .hg/data/tst.d.hg |
|
100 | 100 | .hg/data/tst.d.hg/foo.i |
|
101 | 101 | .hg/dirstate |
|
102 | 102 | .hg/fsmonitor.state (fsmonitor !) |
|
103 | 103 | .hg/last-message.txt |
|
104 | 104 | .hg/phaseroots |
|
105 | 105 | .hg/requires |
|
106 | 106 | .hg/undo |
|
107 | .hg/undo.backup.branch | |
|
107 | .hg/undo.backup.branch.bck | |
|
108 | 108 | .hg/undo.backupfiles |
|
109 | 109 | .hg/undo.desc |
|
110 | 110 | .hg/wcache |
|
111 | 111 | .hg/wcache/checkisexec (execbit !) |
|
112 | 112 | .hg/wcache/checklink (symlink !) |
|
113 | 113 | .hg/wcache/checklink-target (symlink !) |
|
114 | 114 | .hg/wcache/manifestfulltextcache (reporevlogstore !) |
|
115 | 115 | $ cd .. |
|
116 | 116 | |
|
117 | 117 | Non fncache repo: |
|
118 | 118 | |
|
119 | 119 | $ hg --config format.usefncache=False init bar |
|
120 | 120 | $ cd bar |
|
121 | 121 | $ mkdir tst.d |
|
122 | 122 | $ echo foo > tst.d/Foo |
|
123 | 123 | $ hg ci -Amfoo |
|
124 | 124 | adding tst.d/Foo |
|
125 | 125 | $ find .hg | sort |
|
126 | 126 | .hg |
|
127 | 127 | .hg/00changelog.i |
|
128 | 128 | .hg/branch |
|
129 | 129 | .hg/cache |
|
130 | 130 | .hg/cache/branch2-served |
|
131 | 131 | .hg/cache/rbc-names-v1 |
|
132 | 132 | .hg/cache/rbc-revs-v1 |
|
133 | 133 | .hg/dirstate |
|
134 | 134 | .hg/fsmonitor.state (fsmonitor !) |
|
135 | 135 | .hg/last-message.txt |
|
136 | 136 | .hg/requires |
|
137 | 137 | .hg/store |
|
138 | 138 | .hg/store/00changelog.i |
|
139 | 139 | .hg/store/00manifest.i |
|
140 | 140 | .hg/store/data |
|
141 | 141 | .hg/store/data/tst.d.hg |
|
142 | 142 | .hg/store/data/tst.d.hg/_foo.i |
|
143 | 143 | .hg/store/phaseroots |
|
144 | 144 | .hg/store/requires |
|
145 | 145 | .hg/store/undo |
|
146 | 146 | .hg/store/undo.backupfiles |
|
147 | .hg/undo.backup.branch | |
|
147 | .hg/undo.backup.branch.bck | |
|
148 | 148 | .hg/undo.desc |
|
149 | 149 | .hg/wcache |
|
150 | 150 | .hg/wcache/checkisexec (execbit !) |
|
151 | 151 | .hg/wcache/checklink (symlink !) |
|
152 | 152 | .hg/wcache/checklink-target (symlink !) |
|
153 | 153 | .hg/wcache/manifestfulltextcache (reporevlogstore !) |
|
154 | 154 | $ cd .. |
|
155 | 155 | |
|
156 | 156 | Encoding of reserved / long paths in the store |
|
157 | 157 | |
|
158 | 158 | $ hg init r2 |
|
159 | 159 | $ cd r2 |
|
160 | 160 | $ cat <<EOF > .hg/hgrc |
|
161 | 161 | > [ui] |
|
162 | 162 | > portablefilenames = ignore |
|
163 | 163 | > EOF |
|
164 | 164 | |
|
165 | 165 | $ hg import -q --bypass - <<EOF |
|
166 | 166 | > # HG changeset patch |
|
167 | 167 | > # User test |
|
168 | 168 | > # Date 0 0 |
|
169 | 169 | > # Node ID 1c7a2f7cb77be1a0def34e4c7cabc562ad98fbd7 |
|
170 | 170 | > # Parent 0000000000000000000000000000000000000000 |
|
171 | 171 | > 1 |
|
172 | 172 | > |
|
173 | 173 | > diff --git a/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz b/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz |
|
174 | 174 | > new file mode 100644 |
|
175 | 175 | > --- /dev/null |
|
176 | 176 | > +++ b/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxxxxx-xxxxxxxxx-xxxxxxxxx-123456789-12.3456789-12345-ABCDEFGHIJKLMNOPRSTUVWXYZ-abcdefghjiklmnopqrstuvwxyz |
|
177 | 177 | > @@ -0,0 +1,1 @@ |
|
178 | 178 | > +foo |
|
179 | 179 | > diff --git a/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT b/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT |
|
180 | 180 | > new file mode 100644 |
|
181 | 181 | > --- /dev/null |
|
182 | 182 | > +++ b/AUX/SECOND/X.PRN/FOURTH/FI:FTH/SIXTH/SEVENTH/EIGHTH/NINETH/TENTH/ELEVENTH/LOREMIPSUM.TXT |
|
183 | 183 | > @@ -0,0 +1,1 @@ |
|
184 | 184 | > +foo |
|
185 | 185 | > diff --git a/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt |
|
186 | 186 | > new file mode 100644 |
|
187 | 187 | > --- /dev/null |
|
188 | 188 | > +++ b/Project Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt |
|
189 | 189 | > @@ -0,0 +1,1 @@ |
|
190 | 190 | > +foo |
|
191 | 191 | > diff --git a/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c b/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c |
|
192 | 192 | > new file mode 100644 |
|
193 | 193 | > --- /dev/null |
|
194 | 194 | > +++ b/bla.aux/prn/PRN/lpt/com3/nul/coma/foo.NUL/normal.c |
|
195 | 195 | > @@ -0,0 +1,1 @@ |
|
196 | 196 | > +foo |
|
197 | 197 | > diff --git a/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider b/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider |
|
198 | 198 | > new file mode 100644 |
|
199 | 199 | > --- /dev/null |
|
200 | 200 | > +++ b/enterprise/openesbaddons/contrib-imola/corba-bc/netbeansplugin/wsdlExtension/src/main/java/META-INF/services/org.netbeans.modules.xml.wsdl.bindingsupport.spi.ExtensibilityElementTemplateProvider |
|
201 | 201 | > @@ -0,0 +1,1 @@ |
|
202 | 202 | > +foo |
|
203 | 203 | > EOF |
|
204 | 204 | |
|
205 | 205 | $ find .hg/store -name *.i | sort |
|
206 | 206 | .hg/store/00changelog.i |
|
207 | 207 | .hg/store/00manifest.i |
|
208 | 208 | .hg/store/data/bla.aux/pr~6e/_p_r_n/lpt/co~6d3/nu~6c/coma/foo._n_u_l/normal.c.i |
|
209 | 209 | .hg/store/dh/12345678/12345678/12345678/12345678/12345678/12345678/12345678/12345/xxxxxx168e07b38e65eff86ab579afaaa8e30bfbe0f35f.i |
|
210 | 210 | .hg/store/dh/au~78/second/x.prn/fourth/fi~3afth/sixth/seventh/eighth/nineth/tenth/loremia20419e358ddff1bf8751e38288aff1d7c32ec05.i |
|
211 | 211 | .hg/store/dh/enterpri/openesba/contrib-/corba-bc/netbeans/wsdlexte/src/main/java/org.net7018f27961fdf338a598a40c4683429e7ffb9743.i |
|
212 | 212 | .hg/store/dh/project_/resource/anotherl/followed/andanoth/andthenanextremelylongfilename0d8e1f4187c650e2f1fdca9fd90f786bc0976b6b.i |
|
213 | 213 | |
|
214 | 214 | $ cd .. |
|
215 | 215 | |
|
216 | 216 | Aborting lock does not prevent fncache writes |
|
217 | 217 | |
|
218 | 218 | $ cat > exceptionext.py <<EOF |
|
219 | 219 | > import os |
|
220 | 220 | > from mercurial import commands, error, extensions |
|
221 | 221 | > |
|
222 | 222 | > def lockexception(orig, vfs, lockname, wait, releasefn, *args, **kwargs): |
|
223 | 223 | > def releasewrap(): |
|
224 | 224 | > l.held = False # ensure __del__ is a noop |
|
225 | 225 | > raise error.Abort(b"forced lock failure") |
|
226 | 226 | > l = orig(vfs, lockname, wait, releasewrap, *args, **kwargs) |
|
227 | 227 | > return l |
|
228 | 228 | > |
|
229 | 229 | > def reposetup(ui, repo): |
|
230 | 230 | > extensions.wrapfunction(repo, '_lock', lockexception) |
|
231 | 231 | > |
|
232 | 232 | > cmdtable = {} |
|
233 | 233 | > |
|
234 | 234 | > # wrap "commit" command to prevent wlock from being '__del__()'-ed |
|
235 | 235 | > # at the end of dispatching (for intentional "forced lcok failure") |
|
236 | 236 | > def commitwrap(orig, ui, repo, *pats, **opts): |
|
237 | 237 | > repo = repo.unfiltered() # to use replaced repo._lock certainly |
|
238 | 238 | > wlock = repo.wlock() |
|
239 | 239 | > try: |
|
240 | 240 | > return orig(ui, repo, *pats, **opts) |
|
241 | 241 | > finally: |
|
242 | 242 | > # multiple 'relase()' is needed for complete releasing wlock, |
|
243 | 243 | > # because "forced" abort at last releasing store lock |
|
244 | 244 | > # prevents wlock from being released at same 'lockmod.release()' |
|
245 | 245 | > for i in range(wlock.held): |
|
246 | 246 | > wlock.release() |
|
247 | 247 | > |
|
248 | 248 | > def extsetup(ui): |
|
249 | 249 | > extensions.wrapcommand(commands.table, b"commit", commitwrap) |
|
250 | 250 | > EOF |
|
251 | 251 | $ extpath=`pwd`/exceptionext.py |
|
252 | 252 | $ hg init fncachetxn |
|
253 | 253 | $ cd fncachetxn |
|
254 | 254 | $ printf "[extensions]\nexceptionext=$extpath\n" >> .hg/hgrc |
|
255 | 255 | $ touch y |
|
256 | 256 | $ hg ci -qAm y |
|
257 | 257 | abort: forced lock failure |
|
258 | 258 | [255] |
|
259 | 259 | $ cat .hg/store/fncache |
|
260 | 260 | data/y.i |
|
261 | 261 | |
|
262 | 262 | Aborting transaction prevents fncache change |
|
263 | 263 | |
|
264 | 264 | $ cat > ../exceptionext.py <<EOF |
|
265 | 265 | > import os |
|
266 | 266 | > from mercurial import commands, error, extensions, localrepo |
|
267 | 267 | > |
|
268 | 268 | > def wrapper(orig, self, *args, **kwargs): |
|
269 | 269 | > tr = orig(self, *args, **kwargs) |
|
270 | 270 | > def fail(tr): |
|
271 | 271 | > raise error.Abort(b"forced transaction failure") |
|
272 | 272 | > # zzz prefix to ensure it sorted after store.write |
|
273 | 273 | > tr.addfinalize(b'zzz-forcefails', fail) |
|
274 | 274 | > return tr |
|
275 | 275 | > |
|
276 | 276 | > def uisetup(ui): |
|
277 | 277 | > extensions.wrapfunction( |
|
278 | 278 | > localrepo.localrepository, b'transaction', wrapper) |
|
279 | 279 | > |
|
280 | 280 | > cmdtable = {} |
|
281 | 281 | > |
|
282 | 282 | > EOF |
|
283 | 283 | |
|
284 | 284 | Clean cached version |
|
285 | 285 | $ rm -f "${extpath}c" |
|
286 | 286 | $ rm -Rf "`dirname $extpath`/__pycache__" |
|
287 | 287 | |
|
288 | 288 | $ touch z |
|
289 | 289 | $ hg ci -qAm z |
|
290 | 290 | transaction abort! |
|
291 | 291 | rollback completed |
|
292 | 292 | abort: forced transaction failure |
|
293 | 293 | [255] |
|
294 | 294 | $ cat .hg/store/fncache |
|
295 | 295 | data/y.i |
|
296 | 296 | |
|
297 | 297 | Aborted transactions can be recovered later |
|
298 | 298 | |
|
299 | 299 | $ cat > ../exceptionext.py <<EOF |
|
300 | 300 | > import os |
|
301 | 301 | > import signal |
|
302 | 302 | > from mercurial import ( |
|
303 | 303 | > commands, |
|
304 | 304 | > error, |
|
305 | 305 | > extensions, |
|
306 | 306 | > localrepo, |
|
307 | 307 | > transaction, |
|
308 | 308 | > ) |
|
309 | 309 | > |
|
310 | 310 | > def trwrapper(orig, self, *args, **kwargs): |
|
311 | 311 | > tr = orig(self, *args, **kwargs) |
|
312 | 312 | > def fail(tr): |
|
313 | 313 | > os.kill(os.getpid(), signal.SIGKILL) |
|
314 | 314 | > # zzz prefix to ensure it sorted after store.write |
|
315 | 315 | > tr.addfinalize(b'zzz-forcefails', fail) |
|
316 | 316 | > return tr |
|
317 | 317 | > |
|
318 | 318 | > def uisetup(ui): |
|
319 | 319 | > extensions.wrapfunction(localrepo.localrepository, 'transaction', |
|
320 | 320 | > trwrapper) |
|
321 | 321 | > |
|
322 | 322 | > cmdtable = {} |
|
323 | 323 | > |
|
324 | 324 | > EOF |
|
325 | 325 | |
|
326 | 326 | Clean cached versions |
|
327 | 327 | $ rm -f "${extpath}c" |
|
328 | 328 | $ rm -Rf "`dirname $extpath`/__pycache__" |
|
329 | 329 | |
|
330 | 330 | $ hg up -q 1 |
|
331 | 331 | $ touch z |
|
332 | 332 | # Cannot rely on the return code value as chg use a different one. |
|
333 | 333 | # So we use a `|| echo` trick |
|
334 | 334 | # XXX-CHG fixing chg behavior would be nice here. |
|
335 | 335 | $ hg ci -qAm z || echo "He's Dead, Jim." 2>/dev/null |
|
336 | 336 | *Killed* (glob) (?) |
|
337 | 337 | He's Dead, Jim. |
|
338 | 338 | $ cat .hg/store/fncache | sort |
|
339 | 339 | data/y.i |
|
340 | 340 | data/z.i |
|
341 | 341 | $ hg recover --verify |
|
342 | 342 | rolling back interrupted transaction |
|
343 | 343 | checking changesets |
|
344 | 344 | checking manifests |
|
345 | 345 | crosschecking files in changesets and manifests |
|
346 | 346 | checking files |
|
347 | 347 | checking dirstate |
|
348 | 348 | checked 1 changesets with 1 changes to 1 files |
|
349 | 349 | $ cat .hg/store/fncache |
|
350 | 350 | data/y.i |
|
351 | 351 | |
|
352 | 352 | $ cd .. |
|
353 | 353 | |
|
354 | 354 | debugrebuildfncache does nothing unless repo has fncache requirement |
|
355 | 355 | |
|
356 | 356 | $ hg --config format.usefncache=false init nofncache |
|
357 | 357 | $ cd nofncache |
|
358 | 358 | $ hg debugrebuildfncache |
|
359 | 359 | (not rebuilding fncache because repository does not support fncache) |
|
360 | 360 | |
|
361 | 361 | $ cd .. |
|
362 | 362 | |
|
363 | 363 | debugrebuildfncache works on empty repository |
|
364 | 364 | |
|
365 | 365 | $ hg init empty |
|
366 | 366 | $ cd empty |
|
367 | 367 | $ hg debugrebuildfncache |
|
368 | 368 | fncache already up to date |
|
369 | 369 | $ cd .. |
|
370 | 370 | |
|
371 | 371 | debugrebuildfncache on an up to date repository no-ops |
|
372 | 372 | |
|
373 | 373 | $ hg init repo |
|
374 | 374 | $ cd repo |
|
375 | 375 | $ echo initial > foo |
|
376 | 376 | $ echo initial > .bar |
|
377 | 377 | $ hg commit -A -m initial |
|
378 | 378 | adding .bar |
|
379 | 379 | adding foo |
|
380 | 380 | |
|
381 | 381 | $ cat .hg/store/fncache | sort |
|
382 | 382 | data/.bar.i |
|
383 | 383 | data/foo.i |
|
384 | 384 | |
|
385 | 385 | $ hg debugrebuildfncache |
|
386 | 386 | fncache already up to date |
|
387 | 387 | |
|
388 | 388 | debugrebuildfncache restores deleted fncache file |
|
389 | 389 | |
|
390 | 390 | $ rm -f .hg/store/fncache |
|
391 | 391 | $ hg debugrebuildfncache |
|
392 | 392 | adding data/.bar.i |
|
393 | 393 | adding data/foo.i |
|
394 | 394 | 2 items added, 0 removed from fncache |
|
395 | 395 | |
|
396 | 396 | $ cat .hg/store/fncache | sort |
|
397 | 397 | data/.bar.i |
|
398 | 398 | data/foo.i |
|
399 | 399 | |
|
400 | 400 | Rebuild after rebuild should no-op |
|
401 | 401 | |
|
402 | 402 | $ hg debugrebuildfncache |
|
403 | 403 | fncache already up to date |
|
404 | 404 | |
|
405 | 405 | A single missing file should get restored, an extra file should be removed |
|
406 | 406 | |
|
407 | 407 | $ cat > .hg/store/fncache << EOF |
|
408 | 408 | > data/foo.i |
|
409 | 409 | > data/bad-entry.i |
|
410 | 410 | > EOF |
|
411 | 411 | |
|
412 | 412 | $ hg debugrebuildfncache |
|
413 | 413 | removing data/bad-entry.i |
|
414 | 414 | adding data/.bar.i |
|
415 | 415 | 1 items added, 1 removed from fncache |
|
416 | 416 | |
|
417 | 417 | $ cat .hg/store/fncache | sort |
|
418 | 418 | data/.bar.i |
|
419 | 419 | data/foo.i |
|
420 | 420 | |
|
421 | 421 | debugrebuildfncache recovers from truncated line in fncache |
|
422 | 422 | |
|
423 | 423 | $ printf a > .hg/store/fncache |
|
424 | 424 | $ hg debugrebuildfncache |
|
425 | 425 | fncache does not ends with a newline |
|
426 | 426 | adding data/.bar.i |
|
427 | 427 | adding data/foo.i |
|
428 | 428 | 2 items added, 0 removed from fncache |
|
429 | 429 | |
|
430 | 430 | $ cat .hg/store/fncache | sort |
|
431 | 431 | data/.bar.i |
|
432 | 432 | data/foo.i |
|
433 | 433 | |
|
434 | 434 | $ cd .. |
|
435 | 435 | |
|
436 | 436 | Try a simple variation without dotencode to ensure fncache is ignorant of encoding |
|
437 | 437 | |
|
438 | 438 | $ hg --config format.dotencode=false init nodotencode |
|
439 | 439 | $ cd nodotencode |
|
440 | 440 | $ echo initial > foo |
|
441 | 441 | $ echo initial > .bar |
|
442 | 442 | $ hg commit -A -m initial |
|
443 | 443 | adding .bar |
|
444 | 444 | adding foo |
|
445 | 445 | |
|
446 | 446 | $ cat .hg/store/fncache | sort |
|
447 | 447 | data/.bar.i |
|
448 | 448 | data/foo.i |
|
449 | 449 | |
|
450 | 450 | $ rm .hg/store/fncache |
|
451 | 451 | $ hg debugrebuildfncache |
|
452 | 452 | adding data/.bar.i |
|
453 | 453 | adding data/foo.i |
|
454 | 454 | 2 items added, 0 removed from fncache |
|
455 | 455 | |
|
456 | 456 | $ cat .hg/store/fncache | sort |
|
457 | 457 | data/.bar.i |
|
458 | 458 | data/foo.i |
|
459 | 459 | |
|
460 | 460 | $ cd .. |
|
461 | 461 | |
|
462 | 462 | In repositories that have accumulated a large number of files over time, the |
|
463 | 463 | fncache file is going to be large. If we possibly can avoid loading it, so much the better. |
|
464 | 464 | The cache should not loaded when committing changes to existing files, or when unbundling |
|
465 | 465 | changesets that only contain changes to existing files: |
|
466 | 466 | |
|
467 | 467 | $ cat > fncacheloadwarn.py << EOF |
|
468 | 468 | > from mercurial import extensions, localrepo |
|
469 | 469 | > |
|
470 | 470 | > def extsetup(ui): |
|
471 | 471 | > def wrapstore(orig, requirements, *args): |
|
472 | 472 | > store = orig(requirements, *args) |
|
473 | 473 | > if b'store' in requirements and b'fncache' in requirements: |
|
474 | 474 | > instrumentfncachestore(store, ui) |
|
475 | 475 | > return store |
|
476 | 476 | > extensions.wrapfunction(localrepo, 'makestore', wrapstore) |
|
477 | 477 | > |
|
478 | 478 | > def instrumentfncachestore(fncachestore, ui): |
|
479 | 479 | > class instrumentedfncache(type(fncachestore.fncache)): |
|
480 | 480 | > def _load(self): |
|
481 | 481 | > ui.warn(b'fncache load triggered!\n') |
|
482 | 482 | > super(instrumentedfncache, self)._load() |
|
483 | 483 | > fncachestore.fncache.__class__ = instrumentedfncache |
|
484 | 484 | > EOF |
|
485 | 485 | |
|
486 | 486 | $ fncachextpath=`pwd`/fncacheloadwarn.py |
|
487 | 487 | $ hg init nofncacheload |
|
488 | 488 | $ cd nofncacheload |
|
489 | 489 | $ printf "[extensions]\nfncacheloadwarn=$fncachextpath\n" >> .hg/hgrc |
|
490 | 490 | |
|
491 | 491 | A new file should trigger a load, as we'd want to update the fncache set in that case: |
|
492 | 492 | |
|
493 | 493 | $ touch foo |
|
494 | 494 | $ hg ci -qAm foo |
|
495 | 495 | fncache load triggered! |
|
496 | 496 | |
|
497 | 497 | But modifying that file should not: |
|
498 | 498 | |
|
499 | 499 | $ echo bar >> foo |
|
500 | 500 | $ hg ci -qm foo |
|
501 | 501 | |
|
502 | 502 | If a transaction has been aborted, the zero-size truncated index file will |
|
503 | 503 | not prevent the fncache from being loaded; rather than actually abort |
|
504 | 504 | a transaction, we simulate the situation by creating a zero-size index file: |
|
505 | 505 | |
|
506 | 506 | $ touch .hg/store/data/bar.i |
|
507 | 507 | $ touch bar |
|
508 | 508 | $ hg ci -qAm bar |
|
509 | 509 | fncache load triggered! |
|
510 | 510 | |
|
511 | 511 | Unbundling should follow the same rules; existing files should not cause a load: |
|
512 | 512 | |
|
513 | 513 | (loading during the clone is expected) |
|
514 | 514 | $ hg clone -q . tobundle |
|
515 | 515 | fncache load triggered! |
|
516 | 516 | fncache load triggered! |
|
517 | 517 | |
|
518 | 518 | $ echo 'new line' > tobundle/bar |
|
519 | 519 | $ hg -R tobundle ci -qm bar |
|
520 | 520 | $ hg -R tobundle bundle -q barupdated.hg |
|
521 | 521 | $ hg unbundle -q barupdated.hg |
|
522 | 522 | |
|
523 | 523 | but adding new files should: |
|
524 | 524 | |
|
525 | 525 | $ touch tobundle/newfile |
|
526 | 526 | $ hg -R tobundle ci -qAm newfile |
|
527 | 527 | $ hg -R tobundle bundle -q newfile.hg |
|
528 | 528 | $ hg unbundle -q newfile.hg |
|
529 | 529 | fncache load triggered! |
|
530 | 530 | |
|
531 | 531 | $ cd .. |
@@ -1,425 +1,425 b'' | |||
|
1 | 1 | #require hardlink reporevlogstore |
|
2 | 2 | |
|
3 | 3 | $ cat > nlinks.py <<EOF |
|
4 | 4 | > import sys |
|
5 | 5 | > from mercurial import pycompat, util |
|
6 | 6 | > for f in sorted(sys.stdin.readlines()): |
|
7 | 7 | > f = f[:-1] |
|
8 | 8 | > print(util.nlinks(pycompat.fsencode(f)), f) |
|
9 | 9 | > EOF |
|
10 | 10 | |
|
11 | 11 | $ nlinksdir() |
|
12 | 12 | > { |
|
13 | 13 | > find "$@" -type f | "$PYTHON" $TESTTMP/nlinks.py |
|
14 | 14 | > } |
|
15 | 15 | |
|
16 | 16 | Some implementations of cp can't create hardlinks (replaces 'cp -al' on Linux): |
|
17 | 17 | |
|
18 | 18 | $ cat > linkcp.py <<EOF |
|
19 | 19 | > import sys |
|
20 | 20 | > from mercurial import pycompat, util |
|
21 | 21 | > util.copyfiles(pycompat.fsencode(sys.argv[1]), |
|
22 | 22 | > pycompat.fsencode(sys.argv[2]), hardlink=True) |
|
23 | 23 | > EOF |
|
24 | 24 | |
|
25 | 25 | $ linkcp() |
|
26 | 26 | > { |
|
27 | 27 | > "$PYTHON" $TESTTMP/linkcp.py $1 $2 |
|
28 | 28 | > } |
|
29 | 29 | |
|
30 | 30 | Prepare repo r1: |
|
31 | 31 | |
|
32 | 32 | $ hg init r1 |
|
33 | 33 | $ cd r1 |
|
34 | 34 | |
|
35 | 35 | $ echo c1 > f1 |
|
36 | 36 | $ hg add f1 |
|
37 | 37 | $ hg ci -m0 |
|
38 | 38 | |
|
39 | 39 | $ mkdir d1 |
|
40 | 40 | $ cd d1 |
|
41 | 41 | $ echo c2 > f2 |
|
42 | 42 | $ hg add f2 |
|
43 | 43 | $ hg ci -m1 |
|
44 | 44 | $ cd ../.. |
|
45 | 45 | |
|
46 | 46 | $ nlinksdir r1/.hg/store |
|
47 | 47 | 1 r1/.hg/store/00changelog.i |
|
48 | 48 | 1 r1/.hg/store/00manifest.i |
|
49 | 49 | 1 r1/.hg/store/data/d1/f2.i |
|
50 | 50 | 1 r1/.hg/store/data/f1.i |
|
51 | 51 | 1 r1/.hg/store/fncache (repofncache !) |
|
52 | 52 | 1 r1/.hg/store/phaseroots |
|
53 | 53 | 1 r1/.hg/store/requires |
|
54 | 54 | 1 r1/.hg/store/undo |
|
55 | 1 r1/.hg/store/undo.backup.fncache (repofncache !) | |
|
55 | 1 r1/.hg/store/undo.backup.fncache.bck (repofncache !) | |
|
56 | 56 | 1 r1/.hg/store/undo.backupfiles |
|
57 | 57 | |
|
58 | 58 | |
|
59 | 59 | Create hardlinked clone r2: |
|
60 | 60 | |
|
61 | 61 | $ hg clone -U --debug r1 r2 --config progress.debug=true |
|
62 | 62 | linking: 1/7 files (14.29%) |
|
63 | 63 | linking: 2/7 files (28.57%) |
|
64 | 64 | linking: 3/7 files (42.86%) |
|
65 | 65 | linking: 4/7 files (57.14%) |
|
66 | 66 | linking: 5/7 files (71.43%) |
|
67 | 67 | linking: 6/7 files (85.71%) |
|
68 | 68 | linking: 7/7 files (100.00%) |
|
69 | 69 | linked 7 files |
|
70 | 70 | updating the branch cache |
|
71 | 71 | |
|
72 | 72 | Create non-hardlinked clone r3: |
|
73 | 73 | |
|
74 | 74 | $ hg clone --pull r1 r3 |
|
75 | 75 | requesting all changes |
|
76 | 76 | adding changesets |
|
77 | 77 | adding manifests |
|
78 | 78 | adding file changes |
|
79 | 79 | added 2 changesets with 2 changes to 2 files |
|
80 | 80 | new changesets 40d85e9847f2:7069c422939c |
|
81 | 81 | updating to branch default |
|
82 | 82 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
83 | 83 | |
|
84 | 84 | |
|
85 | 85 | Repos r1 and r2 should now contain hardlinked files: |
|
86 | 86 | |
|
87 | 87 | $ nlinksdir r1/.hg/store |
|
88 | 88 | 2 r1/.hg/store/00changelog.i |
|
89 | 89 | 2 r1/.hg/store/00manifest.i |
|
90 | 90 | 2 r1/.hg/store/data/d1/f2.i |
|
91 | 91 | 2 r1/.hg/store/data/f1.i |
|
92 | 92 | 1 r1/.hg/store/fncache (repofncache !) |
|
93 | 93 | 1 r1/.hg/store/phaseroots |
|
94 | 94 | 1 r1/.hg/store/requires |
|
95 | 95 | 1 r1/.hg/store/undo |
|
96 | 1 r1/.hg/store/undo.backup.fncache (repofncache !) | |
|
96 | 1 r1/.hg/store/undo.backup.fncache.bck (repofncache !) | |
|
97 | 97 | 1 r1/.hg/store/undo.backupfiles |
|
98 | 98 | |
|
99 | 99 | $ nlinksdir r2/.hg/store |
|
100 | 100 | 2 r2/.hg/store/00changelog.i |
|
101 | 101 | 2 r2/.hg/store/00manifest.i |
|
102 | 102 | 2 r2/.hg/store/data/d1/f2.i |
|
103 | 103 | 2 r2/.hg/store/data/f1.i |
|
104 | 104 | 1 r2/.hg/store/fncache (repofncache !) |
|
105 | 105 | 1 r2/.hg/store/requires |
|
106 | 106 | |
|
107 | 107 | Repo r3 should not be hardlinked: |
|
108 | 108 | |
|
109 | 109 | $ nlinksdir r3/.hg/store |
|
110 | 110 | 1 r3/.hg/store/00changelog.i |
|
111 | 111 | 1 r3/.hg/store/00manifest.i |
|
112 | 112 | 1 r3/.hg/store/data/d1/f2.i |
|
113 | 113 | 1 r3/.hg/store/data/f1.i |
|
114 | 114 | 1 r3/.hg/store/fncache (repofncache !) |
|
115 | 115 | 1 r3/.hg/store/phaseroots |
|
116 | 116 | 1 r3/.hg/store/requires |
|
117 | 117 | 1 r3/.hg/store/undo |
|
118 | 118 | 1 r3/.hg/store/undo.backupfiles |
|
119 | 119 | |
|
120 | 120 | |
|
121 | 121 | Create a non-inlined filelog in r3: |
|
122 | 122 | |
|
123 | 123 | $ cd r3/d1 |
|
124 | 124 | >>> f = open('data1', 'wb') |
|
125 | 125 | >>> for x in range(10000): |
|
126 | 126 | ... f.write(b"%d\n" % x) and None |
|
127 | 127 | >>> f.close() |
|
128 | 128 | $ for j in 0 1 2 3 4 5 6 7 8 9; do |
|
129 | 129 | > cat data1 >> f2 |
|
130 | 130 | > hg commit -m$j |
|
131 | 131 | > done |
|
132 | 132 | $ cd ../.. |
|
133 | 133 | |
|
134 | 134 | $ nlinksdir r3/.hg/store |
|
135 | 135 | 1 r3/.hg/store/00changelog.i |
|
136 | 136 | 1 r3/.hg/store/00manifest.i |
|
137 | 137 | 1 r3/.hg/store/data/d1/f2.d |
|
138 | 138 | 1 r3/.hg/store/data/d1/f2.i |
|
139 | 139 | 1 r3/.hg/store/data/f1.i |
|
140 | 140 | 1 r3/.hg/store/fncache (repofncache !) |
|
141 | 141 | 1 r3/.hg/store/phaseroots |
|
142 | 142 | 1 r3/.hg/store/requires |
|
143 | 143 | 1 r3/.hg/store/undo |
|
144 | 144 | 1 r3/.hg/store/undo.backupfiles |
|
145 | 145 | |
|
146 | 146 | Push to repo r1 should break up most hardlinks in r2: |
|
147 | 147 | |
|
148 | 148 | $ hg -R r2 verify -q |
|
149 | 149 | |
|
150 | 150 | $ cd r3 |
|
151 | 151 | $ hg push |
|
152 | 152 | pushing to $TESTTMP/r1 |
|
153 | 153 | searching for changes |
|
154 | 154 | adding changesets |
|
155 | 155 | adding manifests |
|
156 | 156 | adding file changes |
|
157 | 157 | added 10 changesets with 10 changes to 1 files |
|
158 | 158 | |
|
159 | 159 | $ cd .. |
|
160 | 160 | |
|
161 | 161 | $ nlinksdir r2/.hg/store |
|
162 | 162 | 1 r2/.hg/store/00changelog.i |
|
163 | 163 | 1 r2/.hg/store/00manifest.i |
|
164 | 164 | 1 r2/.hg/store/data/d1/f2.i |
|
165 | 165 | 2 r2/.hg/store/data/f1.i |
|
166 | 166 | [12] r2/\.hg/store/fncache (re) (repofncache !) |
|
167 | 167 | 1 r2/.hg/store/requires |
|
168 | 168 | |
|
169 | 169 | #if hardlink-whitelisted repofncache |
|
170 | 170 | $ nlinksdir r2/.hg/store/fncache |
|
171 | 171 | 1 r2/.hg/store/fncache |
|
172 | 172 | #endif |
|
173 | 173 | |
|
174 | 174 | $ hg -R r2 verify -q |
|
175 | 175 | |
|
176 | 176 | $ cd r1 |
|
177 | 177 | $ hg up |
|
178 | 178 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
179 | 179 | |
|
180 | 180 | Committing a change to f1 in r1 must break up hardlink f1.i in r2: |
|
181 | 181 | |
|
182 | 182 | $ echo c1c1 >> f1 |
|
183 | 183 | $ hg ci -m00 |
|
184 | 184 | $ cd .. |
|
185 | 185 | |
|
186 | 186 | $ nlinksdir r2/.hg/store |
|
187 | 187 | 1 r2/.hg/store/00changelog.i |
|
188 | 188 | 1 r2/.hg/store/00manifest.i |
|
189 | 189 | 1 r2/.hg/store/data/d1/f2.i |
|
190 | 190 | 1 r2/.hg/store/data/f1.i |
|
191 | 191 | 1 r2/.hg/store/fncache (repofncache !) |
|
192 | 192 | 1 r2/.hg/store/requires |
|
193 | 193 | |
|
194 | 194 | #if hardlink-whitelisted repofncache |
|
195 | 195 | $ nlinksdir r2/.hg/store/fncache |
|
196 | 196 | 1 r2/.hg/store/fncache |
|
197 | 197 | #endif |
|
198 | 198 | |
|
199 | 199 | Create a file which exec permissions we will change |
|
200 | 200 | $ cd r3 |
|
201 | 201 | $ echo "echo hello world" > f3 |
|
202 | 202 | $ hg add f3 |
|
203 | 203 | $ hg ci -mf3 |
|
204 | 204 | $ cd .. |
|
205 | 205 | |
|
206 | 206 | $ cd r3 |
|
207 | 207 | $ hg tip --template '{rev}:{node|short}\n' |
|
208 | 208 | 12:d3b77733a28a |
|
209 | 209 | $ echo bla > f1 |
|
210 | 210 | $ chmod +x f3 |
|
211 | 211 | $ hg ci -m1 |
|
212 | 212 | $ cd .. |
|
213 | 213 | |
|
214 | 214 | Create hardlinked copy r4 of r3 (on Linux, we would call 'cp -al'): |
|
215 | 215 | |
|
216 | 216 | $ linkcp r3 r4 |
|
217 | 217 | |
|
218 | 218 | 'checklink' is produced by hardlinking a symlink, which is undefined whether |
|
219 | 219 | the symlink should be followed or not. It does behave differently on Linux and |
|
220 | 220 | BSD. Just remove it so the test pass on both platforms. |
|
221 | 221 | |
|
222 | 222 | $ rm -f r4/.hg/wcache/checklink |
|
223 | 223 | |
|
224 | 224 | r4 has hardlinks in the working dir (not just inside .hg): |
|
225 | 225 | |
|
226 | 226 | $ nlinksdir r4 |
|
227 | 227 | 2 r4/.hg/00changelog.i |
|
228 | 228 | [24] r4/.hg/branch (re) |
|
229 | 229 | 2 r4/.hg/cache/branch2-base |
|
230 | 230 | 2 r4/.hg/cache/branch2-immutable |
|
231 | 231 | 2 r4/.hg/cache/branch2-served |
|
232 | 232 | 2 r4/.hg/cache/branch2-served.hidden |
|
233 | 233 | 2 r4/.hg/cache/branch2-visible |
|
234 | 234 | 2 r4/.hg/cache/branch2-visible-hidden |
|
235 | 235 | 2 r4/.hg/cache/rbc-names-v1 |
|
236 | 236 | 2 r4/.hg/cache/rbc-revs-v1 |
|
237 | 237 | 2 r4/.hg/cache/tags2 |
|
238 | 238 | 2 r4/.hg/cache/tags2-served |
|
239 | 239 | 2 r4/.hg/dirstate |
|
240 | 240 | 2 r4/.hg/fsmonitor.state (fsmonitor !) |
|
241 | 241 | 2 r4/.hg/hgrc |
|
242 | 242 | 2 r4/.hg/last-message.txt |
|
243 | 243 | 2 r4/.hg/requires |
|
244 | 244 | 2 r4/.hg/store/00changelog.i |
|
245 | 245 | 2 r4/.hg/store/00manifest.i |
|
246 | 246 | 2 r4/.hg/store/data/d1/f2.d |
|
247 | 247 | 2 r4/.hg/store/data/d1/f2.i |
|
248 | 248 | 2 r4/.hg/store/data/f1.i |
|
249 | 249 | 2 r4/.hg/store/data/f3.i |
|
250 | 250 | 2 r4/.hg/store/fncache (repofncache !) |
|
251 | 251 | 2 r4/.hg/store/phaseroots |
|
252 | 252 | 2 r4/.hg/store/requires |
|
253 | 253 | 2 r4/.hg/store/undo |
|
254 | 254 | 2 r4/.hg/store/undo.backupfiles |
|
255 | [24] r4/.hg/undo.backup.branch (re) | |
|
256 | 2 r4/\.hg/undo\.backup\.dirstate (re) | |
|
255 | [24] r4/.hg/undo.backup.branch.bck (re) | |
|
256 | 2 r4/\.hg/undo\.backup\.dirstate.bck (re) | |
|
257 | 257 | 2 r4/.hg/undo.desc |
|
258 | 258 | 2 r4/.hg/wcache/checkisexec (execbit !) |
|
259 | 259 | 2 r4/.hg/wcache/checklink-target (symlink !) |
|
260 | 260 | 2 r4/.hg/wcache/checknoexec (execbit !) |
|
261 | 261 | 2 r4/.hg/wcache/manifestfulltextcache (reporevlogstore !) |
|
262 | 262 | 2 r4/d1/data1 |
|
263 | 263 | 2 r4/d1/f2 |
|
264 | 264 | 2 r4/f1 |
|
265 | 265 | 2 r4/f3 |
|
266 | 266 | |
|
267 | 267 | Update back to revision 12 in r4 should break hardlink of file f1 and f3: |
|
268 | 268 | #if hardlink-whitelisted |
|
269 | $ nlinksdir r4/.hg/undo.backup.dirstate r4/.hg/dirstate | |
|
269 | $ nlinksdir r4/.hg/undo.backup.dirstate.bck r4/.hg/dirstate | |
|
270 | 270 | 2 r4/.hg/dirstate |
|
271 | 2 r4/.hg/undo.backup.dirstate | |
|
271 | 2 r4/.hg/undo.backup.dirstate.bck | |
|
272 | 272 | #endif |
|
273 | 273 | |
|
274 | 274 | |
|
275 | 275 | $ hg -R r4 up 12 |
|
276 | 276 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (execbit !) |
|
277 | 277 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-execbit !) |
|
278 | 278 | |
|
279 | 279 | $ nlinksdir r4 |
|
280 | 280 | 2 r4/.hg/00changelog.i |
|
281 | 281 | 1 r4/.hg/branch |
|
282 | 282 | 2 r4/.hg/cache/branch2-base |
|
283 | 283 | 2 r4/.hg/cache/branch2-immutable |
|
284 | 284 | 2 r4/.hg/cache/branch2-served |
|
285 | 285 | 2 r4/.hg/cache/branch2-served.hidden |
|
286 | 286 | 2 r4/.hg/cache/branch2-visible |
|
287 | 287 | 2 r4/.hg/cache/branch2-visible-hidden |
|
288 | 288 | 2 r4/.hg/cache/rbc-names-v1 |
|
289 | 289 | 2 r4/.hg/cache/rbc-revs-v1 |
|
290 | 290 | 2 r4/.hg/cache/tags2 |
|
291 | 291 | 2 r4/.hg/cache/tags2-served |
|
292 | 292 | 1 r4/.hg/dirstate |
|
293 | 293 | 1 r4/.hg/fsmonitor.state (fsmonitor !) |
|
294 | 294 | 2 r4/.hg/hgrc |
|
295 | 295 | 2 r4/.hg/last-message.txt |
|
296 | 296 | 2 r4/.hg/requires |
|
297 | 297 | 2 r4/.hg/store/00changelog.i |
|
298 | 298 | 2 r4/.hg/store/00manifest.i |
|
299 | 299 | 2 r4/.hg/store/data/d1/f2.d |
|
300 | 300 | 2 r4/.hg/store/data/d1/f2.i |
|
301 | 301 | 2 r4/.hg/store/data/f1.i |
|
302 | 302 | 2 r4/.hg/store/data/f3.i |
|
303 | 303 | 2 r4/.hg/store/fncache |
|
304 | 304 | 2 r4/.hg/store/phaseroots |
|
305 | 305 | 2 r4/.hg/store/requires |
|
306 | 306 | 2 r4/.hg/store/undo |
|
307 | 307 | 2 r4/.hg/store/undo.backupfiles |
|
308 | [23] r4/.hg/undo.backup.branch (re) | |
|
309 | 2 r4/\.hg/undo\.backup\.dirstate (re) | |
|
308 | [23] r4/.hg/undo.backup.branch.bck (re) | |
|
309 | 2 r4/\.hg/undo\.backup\.dirstate.bck (re) | |
|
310 | 310 | 2 r4/.hg/undo.desc |
|
311 | 311 | 2 r4/.hg/wcache/checkisexec (execbit !) |
|
312 | 312 | 2 r4/.hg/wcache/checklink-target (symlink !) |
|
313 | 313 | 2 r4/.hg/wcache/checknoexec (execbit !) |
|
314 | 314 | 1 r4/.hg/wcache/manifestfulltextcache (reporevlogstore !) |
|
315 | 315 | 2 r4/d1/data1 |
|
316 | 316 | 2 r4/d1/f2 |
|
317 | 317 | 1 r4/f1 |
|
318 | 318 | 1 r4/f3 (execbit !) |
|
319 | 319 | 2 r4/f3 (no-execbit !) |
|
320 | 320 | |
|
321 | 321 | #if hardlink-whitelisted |
|
322 | $ nlinksdir r4/.hg/undo.backup.dirstate r4/.hg/dirstate | |
|
322 | $ nlinksdir r4/.hg/undo.backup.dirstate.bck r4/.hg/dirstate | |
|
323 | 323 | 1 r4/.hg/dirstate |
|
324 | 2 r4/.hg/undo.backup.dirstate | |
|
324 | 2 r4/.hg/undo.backup.dirstate.bck | |
|
325 | 325 | #endif |
|
326 | 326 | |
|
327 | 327 | Test hardlinking outside hg: |
|
328 | 328 | |
|
329 | 329 | $ mkdir x |
|
330 | 330 | $ echo foo > x/a |
|
331 | 331 | |
|
332 | 332 | $ linkcp x y |
|
333 | 333 | $ echo bar >> y/a |
|
334 | 334 | |
|
335 | 335 | No diff if hardlink: |
|
336 | 336 | |
|
337 | 337 | $ diff x/a y/a |
|
338 | 338 | |
|
339 | 339 | Test mq hardlinking: |
|
340 | 340 | |
|
341 | 341 | $ echo "[extensions]" >> $HGRCPATH |
|
342 | 342 | $ echo "mq=" >> $HGRCPATH |
|
343 | 343 | |
|
344 | 344 | $ hg init a |
|
345 | 345 | $ cd a |
|
346 | 346 | |
|
347 | 347 | $ hg qimport -n foo - << EOF |
|
348 | 348 | > # HG changeset patch |
|
349 | 349 | > # Date 1 0 |
|
350 | 350 | > diff -r 2588a8b53d66 a |
|
351 | 351 | > --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
352 | 352 | > +++ b/a Wed Jul 23 15:54:29 2008 +0200 |
|
353 | 353 | > @@ -0,0 +1,1 @@ |
|
354 | 354 | > +a |
|
355 | 355 | > EOF |
|
356 | 356 | adding foo to series file |
|
357 | 357 | |
|
358 | 358 | $ hg qpush |
|
359 | 359 | applying foo |
|
360 | 360 | now at: foo |
|
361 | 361 | |
|
362 | 362 | $ cd .. |
|
363 | 363 | $ linkcp a b |
|
364 | 364 | $ cd b |
|
365 | 365 | |
|
366 | 366 | $ hg qimport -n bar - << EOF |
|
367 | 367 | > # HG changeset patch |
|
368 | 368 | > # Date 2 0 |
|
369 | 369 | > diff -r 2588a8b53d66 a |
|
370 | 370 | > --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
371 | 371 | > +++ b/b Wed Jul 23 15:54:29 2008 +0200 |
|
372 | 372 | > @@ -0,0 +1,1 @@ |
|
373 | 373 | > +b |
|
374 | 374 | > EOF |
|
375 | 375 | adding bar to series file |
|
376 | 376 | |
|
377 | 377 | $ hg qpush |
|
378 | 378 | applying bar |
|
379 | 379 | now at: bar |
|
380 | 380 | |
|
381 | 381 | $ cat .hg/patches/status |
|
382 | 382 | 430ed4828a74fa4047bc816a25500f7472ab4bfe:foo |
|
383 | 383 | 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c:bar |
|
384 | 384 | |
|
385 | 385 | $ cat .hg/patches/series |
|
386 | 386 | foo |
|
387 | 387 | bar |
|
388 | 388 | |
|
389 | 389 | $ cat ../a/.hg/patches/status |
|
390 | 390 | 430ed4828a74fa4047bc816a25500f7472ab4bfe:foo |
|
391 | 391 | |
|
392 | 392 | $ cat ../a/.hg/patches/series |
|
393 | 393 | foo |
|
394 | 394 | |
|
395 | 395 | Test tags hardlinking: |
|
396 | 396 | |
|
397 | 397 | $ hg qdel -r qbase:qtip |
|
398 | 398 | patch foo finalized without changeset message |
|
399 | 399 | patch bar finalized without changeset message |
|
400 | 400 | |
|
401 | 401 | $ hg tag -l lfoo |
|
402 | 402 | $ hg tag foo |
|
403 | 403 | |
|
404 | 404 | $ cd .. |
|
405 | 405 | $ linkcp b c |
|
406 | 406 | $ cd c |
|
407 | 407 | |
|
408 | 408 | $ hg tag -l -r 0 lbar |
|
409 | 409 | $ hg tag -r 0 bar |
|
410 | 410 | |
|
411 | 411 | $ cat .hgtags |
|
412 | 412 | 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c foo |
|
413 | 413 | 430ed4828a74fa4047bc816a25500f7472ab4bfe bar |
|
414 | 414 | |
|
415 | 415 | $ cat .hg/localtags |
|
416 | 416 | 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c lfoo |
|
417 | 417 | 430ed4828a74fa4047bc816a25500f7472ab4bfe lbar |
|
418 | 418 | |
|
419 | 419 | $ cat ../b/.hgtags |
|
420 | 420 | 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c foo |
|
421 | 421 | |
|
422 | 422 | $ cat ../b/.hg/localtags |
|
423 | 423 | 4e7abb4840c46a910f6d7b4d3c3fc7e5209e684c lfoo |
|
424 | 424 | |
|
425 | 425 | $ cd .. |
@@ -1,1463 +1,1463 b'' | |||
|
1 | 1 | commit hooks can see env vars |
|
2 | 2 | (and post-transaction one are run unlocked) |
|
3 | 3 | |
|
4 | 4 | |
|
5 | 5 | $ cat > $TESTTMP/txnabort.checkargs.py <<EOF |
|
6 | 6 | > from mercurial import pycompat |
|
7 | 7 | > def showargs(ui, repo, hooktype, **kwargs): |
|
8 | 8 | > kwargs = pycompat.byteskwargs(kwargs) |
|
9 | 9 | > ui.write(b'%s Python hook: %s\n' % (hooktype, |
|
10 | 10 | > b','.join(sorted(kwargs)))) |
|
11 | 11 | > EOF |
|
12 | 12 | |
|
13 | 13 | $ hg init a |
|
14 | 14 | $ cd a |
|
15 | 15 | $ cat > .hg/hgrc <<EOF |
|
16 | 16 | > [hooks] |
|
17 | 17 | > commit = sh -c "HG_LOCAL= HG_TAG= printenv.py --line commit" |
|
18 | 18 | > commit.b = sh -c "HG_LOCAL= HG_TAG= printenv.py --line commit.b" |
|
19 | 19 | > precommit = sh -c "HG_LOCAL= HG_NODE= HG_TAG= printenv.py --line precommit" |
|
20 | 20 | > pretxncommit = sh -c "HG_LOCAL= HG_TAG= printenv.py --line pretxncommit" |
|
21 | 21 | > pretxncommit.tip = hg -q tip |
|
22 | 22 | > pre-identify = sh -c "printenv.py --line pre-identify 1" |
|
23 | 23 | > pre-cat = sh -c "printenv.py --line pre-cat" |
|
24 | 24 | > post-cat = sh -c "printenv.py --line post-cat" |
|
25 | 25 | > pretxnopen = sh -c "HG_LOCAL= HG_TAG= printenv.py --line pretxnopen" |
|
26 | 26 | > pretxnclose = sh -c "HG_LOCAL= HG_TAG= printenv.py --line pretxnclose" |
|
27 | 27 | > txnclose = sh -c "HG_LOCAL= HG_TAG= printenv.py --line txnclose" |
|
28 | 28 | > txnabort.0 = python:$TESTTMP/txnabort.checkargs.py:showargs |
|
29 | 29 | > txnabort.1 = sh -c "HG_LOCAL= HG_TAG= printenv.py --line txnabort" |
|
30 | 30 | > txnclose.checklock = sh -c "hg debuglock > /dev/null" |
|
31 | 31 | > EOF |
|
32 | 32 | $ echo a > a |
|
33 | 33 | $ hg add a |
|
34 | 34 | $ hg commit -m a |
|
35 | 35 | precommit hook: HG_HOOKNAME=precommit |
|
36 | 36 | HG_HOOKTYPE=precommit |
|
37 | 37 | HG_PARENT1=0000000000000000000000000000000000000000 |
|
38 | 38 | |
|
39 | 39 | pretxnopen hook: HG_HOOKNAME=pretxnopen |
|
40 | 40 | HG_HOOKTYPE=pretxnopen |
|
41 | 41 | HG_TXNID=TXN:$ID$ |
|
42 | 42 | HG_TXNNAME=commit |
|
43 | 43 | |
|
44 | 44 | pretxncommit hook: HG_HOOKNAME=pretxncommit |
|
45 | 45 | HG_HOOKTYPE=pretxncommit |
|
46 | 46 | HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
47 | 47 | HG_PARENT1=0000000000000000000000000000000000000000 |
|
48 | 48 | HG_PENDING=$TESTTMP/a |
|
49 | 49 | |
|
50 | 50 | 0:cb9a9f314b8b |
|
51 | 51 | pretxnclose hook: HG_HOOKNAME=pretxnclose |
|
52 | 52 | HG_HOOKTYPE=pretxnclose |
|
53 | 53 | HG_PENDING=$TESTTMP/a |
|
54 | 54 | HG_PHASES_MOVED=1 |
|
55 | 55 | HG_TXNID=TXN:$ID$ |
|
56 | 56 | HG_TXNNAME=commit |
|
57 | 57 | |
|
58 | 58 | txnclose hook: HG_HOOKNAME=txnclose |
|
59 | 59 | HG_HOOKTYPE=txnclose |
|
60 | 60 | HG_PHASES_MOVED=1 |
|
61 | 61 | HG_TXNID=TXN:$ID$ |
|
62 | 62 | HG_TXNNAME=commit |
|
63 | 63 | |
|
64 | 64 | commit hook: HG_HOOKNAME=commit |
|
65 | 65 | HG_HOOKTYPE=commit |
|
66 | 66 | HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
67 | 67 | HG_PARENT1=0000000000000000000000000000000000000000 |
|
68 | 68 | |
|
69 | 69 | commit.b hook: HG_HOOKNAME=commit.b |
|
70 | 70 | HG_HOOKTYPE=commit |
|
71 | 71 | HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
72 | 72 | HG_PARENT1=0000000000000000000000000000000000000000 |
|
73 | 73 | |
|
74 | 74 | |
|
75 | 75 | $ hg clone . ../b |
|
76 | 76 | updating to branch default |
|
77 | 77 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
78 | 78 | $ cd ../b |
|
79 | 79 | |
|
80 | 80 | changegroup hooks can see env vars |
|
81 | 81 | |
|
82 | 82 | $ cat > .hg/hgrc <<EOF |
|
83 | 83 | > [hooks] |
|
84 | 84 | > prechangegroup = sh -c "printenv.py --line prechangegroup" |
|
85 | 85 | > changegroup = sh -c "printenv.py --line changegroup" |
|
86 | 86 | > incoming = sh -c "printenv.py --line incoming" |
|
87 | 87 | > EOF |
|
88 | 88 | |
|
89 | 89 | pretxncommit and commit hooks can see both parents of merge |
|
90 | 90 | |
|
91 | 91 | $ cd ../a |
|
92 | 92 | $ echo b >> a |
|
93 | 93 | $ hg commit -m a1 -d "1 0" |
|
94 | 94 | precommit hook: HG_HOOKNAME=precommit |
|
95 | 95 | HG_HOOKTYPE=precommit |
|
96 | 96 | HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
97 | 97 | |
|
98 | 98 | pretxnopen hook: HG_HOOKNAME=pretxnopen |
|
99 | 99 | HG_HOOKTYPE=pretxnopen |
|
100 | 100 | HG_TXNID=TXN:$ID$ |
|
101 | 101 | HG_TXNNAME=commit |
|
102 | 102 | |
|
103 | 103 | pretxncommit hook: HG_HOOKNAME=pretxncommit |
|
104 | 104 | HG_HOOKTYPE=pretxncommit |
|
105 | 105 | HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd |
|
106 | 106 | HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
107 | 107 | HG_PENDING=$TESTTMP/a |
|
108 | 108 | |
|
109 | 109 | 1:ab228980c14d |
|
110 | 110 | pretxnclose hook: HG_HOOKNAME=pretxnclose |
|
111 | 111 | HG_HOOKTYPE=pretxnclose |
|
112 | 112 | HG_PENDING=$TESTTMP/a |
|
113 | 113 | HG_TXNID=TXN:$ID$ |
|
114 | 114 | HG_TXNNAME=commit |
|
115 | 115 | |
|
116 | 116 | txnclose hook: HG_HOOKNAME=txnclose |
|
117 | 117 | HG_HOOKTYPE=txnclose |
|
118 | 118 | HG_TXNID=TXN:$ID$ |
|
119 | 119 | HG_TXNNAME=commit |
|
120 | 120 | |
|
121 | 121 | commit hook: HG_HOOKNAME=commit |
|
122 | 122 | HG_HOOKTYPE=commit |
|
123 | 123 | HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd |
|
124 | 124 | HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
125 | 125 | |
|
126 | 126 | commit.b hook: HG_HOOKNAME=commit.b |
|
127 | 127 | HG_HOOKTYPE=commit |
|
128 | 128 | HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd |
|
129 | 129 | HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
130 | 130 | |
|
131 | 131 | $ hg update -C 0 |
|
132 | 132 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
133 | 133 | $ echo b > b |
|
134 | 134 | $ hg add b |
|
135 | 135 | $ hg commit -m b -d '1 0' |
|
136 | 136 | precommit hook: HG_HOOKNAME=precommit |
|
137 | 137 | HG_HOOKTYPE=precommit |
|
138 | 138 | HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
139 | 139 | |
|
140 | 140 | pretxnopen hook: HG_HOOKNAME=pretxnopen |
|
141 | 141 | HG_HOOKTYPE=pretxnopen |
|
142 | 142 | HG_TXNID=TXN:$ID$ |
|
143 | 143 | HG_TXNNAME=commit |
|
144 | 144 | |
|
145 | 145 | pretxncommit hook: HG_HOOKNAME=pretxncommit |
|
146 | 146 | HG_HOOKTYPE=pretxncommit |
|
147 | 147 | HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 |
|
148 | 148 | HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
149 | 149 | HG_PENDING=$TESTTMP/a |
|
150 | 150 | |
|
151 | 151 | 2:ee9deb46ab31 |
|
152 | 152 | pretxnclose hook: HG_HOOKNAME=pretxnclose |
|
153 | 153 | HG_HOOKTYPE=pretxnclose |
|
154 | 154 | HG_PENDING=$TESTTMP/a |
|
155 | 155 | HG_TXNID=TXN:$ID$ |
|
156 | 156 | HG_TXNNAME=commit |
|
157 | 157 | |
|
158 | 158 | created new head |
|
159 | 159 | txnclose hook: HG_HOOKNAME=txnclose |
|
160 | 160 | HG_HOOKTYPE=txnclose |
|
161 | 161 | HG_TXNID=TXN:$ID$ |
|
162 | 162 | HG_TXNNAME=commit |
|
163 | 163 | |
|
164 | 164 | commit hook: HG_HOOKNAME=commit |
|
165 | 165 | HG_HOOKTYPE=commit |
|
166 | 166 | HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 |
|
167 | 167 | HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
168 | 168 | |
|
169 | 169 | commit.b hook: HG_HOOKNAME=commit.b |
|
170 | 170 | HG_HOOKTYPE=commit |
|
171 | 171 | HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 |
|
172 | 172 | HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
173 | 173 | |
|
174 | 174 | $ hg merge 1 |
|
175 | 175 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
176 | 176 | (branch merge, don't forget to commit) |
|
177 | 177 | $ hg commit -m merge -d '2 0' |
|
178 | 178 | precommit hook: HG_HOOKNAME=precommit |
|
179 | 179 | HG_HOOKTYPE=precommit |
|
180 | 180 | HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 |
|
181 | 181 | HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd |
|
182 | 182 | |
|
183 | 183 | pretxnopen hook: HG_HOOKNAME=pretxnopen |
|
184 | 184 | HG_HOOKTYPE=pretxnopen |
|
185 | 185 | HG_TXNID=TXN:$ID$ |
|
186 | 186 | HG_TXNNAME=commit |
|
187 | 187 | |
|
188 | 188 | pretxncommit hook: HG_HOOKNAME=pretxncommit |
|
189 | 189 | HG_HOOKTYPE=pretxncommit |
|
190 | 190 | HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 |
|
191 | 191 | HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 |
|
192 | 192 | HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd |
|
193 | 193 | HG_PENDING=$TESTTMP/a |
|
194 | 194 | |
|
195 | 195 | 3:07f3376c1e65 |
|
196 | 196 | pretxnclose hook: HG_HOOKNAME=pretxnclose |
|
197 | 197 | HG_HOOKTYPE=pretxnclose |
|
198 | 198 | HG_PENDING=$TESTTMP/a |
|
199 | 199 | HG_TXNID=TXN:$ID$ |
|
200 | 200 | HG_TXNNAME=commit |
|
201 | 201 | |
|
202 | 202 | txnclose hook: HG_HOOKNAME=txnclose |
|
203 | 203 | HG_HOOKTYPE=txnclose |
|
204 | 204 | HG_TXNID=TXN:$ID$ |
|
205 | 205 | HG_TXNNAME=commit |
|
206 | 206 | |
|
207 | 207 | commit hook: HG_HOOKNAME=commit |
|
208 | 208 | HG_HOOKTYPE=commit |
|
209 | 209 | HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 |
|
210 | 210 | HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 |
|
211 | 211 | HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd |
|
212 | 212 | |
|
213 | 213 | commit.b hook: HG_HOOKNAME=commit.b |
|
214 | 214 | HG_HOOKTYPE=commit |
|
215 | 215 | HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 |
|
216 | 216 | HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 |
|
217 | 217 | HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd |
|
218 | 218 | |
|
219 | 219 | |
|
220 | 220 | test generic hooks |
|
221 | 221 | |
|
222 | 222 | $ hg id |
|
223 | 223 | pre-identify hook: HG_ARGS=id |
|
224 | 224 | HG_HOOKNAME=pre-identify |
|
225 | 225 | HG_HOOKTYPE=pre-identify |
|
226 | 226 | HG_OPTS={'bookmarks': None, 'branch': None, 'id': None, 'insecure': None, 'num': None, 'remotecmd': '', 'rev': '', 'ssh': '', 'tags': None, 'template': ''} |
|
227 | 227 | HG_PATS=[] |
|
228 | 228 | |
|
229 | 229 | abort: pre-identify hook exited with status 1 |
|
230 | 230 | [40] |
|
231 | 231 | $ hg cat b |
|
232 | 232 | pre-cat hook: HG_ARGS=cat b |
|
233 | 233 | HG_HOOKNAME=pre-cat |
|
234 | 234 | HG_HOOKTYPE=pre-cat |
|
235 | 235 | HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': '', 'template': ''} |
|
236 | 236 | HG_PATS=['b'] |
|
237 | 237 | |
|
238 | 238 | b |
|
239 | 239 | post-cat hook: HG_ARGS=cat b |
|
240 | 240 | HG_HOOKNAME=post-cat |
|
241 | 241 | HG_HOOKTYPE=post-cat |
|
242 | 242 | HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': '', 'template': ''} |
|
243 | 243 | HG_PATS=['b'] |
|
244 | 244 | HG_RESULT=0 |
|
245 | 245 | |
|
246 | 246 | |
|
247 | 247 | $ cd ../b |
|
248 | 248 | $ hg pull ../a |
|
249 | 249 | pulling from ../a |
|
250 | 250 | searching for changes |
|
251 | 251 | prechangegroup hook: HG_HOOKNAME=prechangegroup |
|
252 | 252 | HG_HOOKTYPE=prechangegroup |
|
253 | 253 | HG_SOURCE=pull |
|
254 | 254 | HG_TXNID=TXN:$ID$ |
|
255 | 255 | HG_TXNNAME=pull |
|
256 | 256 | file:/*/$TESTTMP/a (glob) |
|
257 | 257 | HG_URL=file:$TESTTMP/a |
|
258 | 258 | |
|
259 | 259 | adding changesets |
|
260 | 260 | adding manifests |
|
261 | 261 | adding file changes |
|
262 | 262 | added 3 changesets with 2 changes to 2 files |
|
263 | 263 | new changesets ab228980c14d:07f3376c1e65 |
|
264 | 264 | changegroup hook: HG_HOOKNAME=changegroup |
|
265 | 265 | HG_HOOKTYPE=changegroup |
|
266 | 266 | HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd |
|
267 | 267 | HG_NODE_LAST=07f3376c1e655977439df2a814e3cc14b27abac2 |
|
268 | 268 | HG_SOURCE=pull |
|
269 | 269 | HG_TXNID=TXN:$ID$ |
|
270 | 270 | HG_TXNNAME=pull |
|
271 | 271 | file:/*/$TESTTMP/a (glob) |
|
272 | 272 | HG_URL=file:$TESTTMP/a |
|
273 | 273 | |
|
274 | 274 | incoming hook: HG_HOOKNAME=incoming |
|
275 | 275 | HG_HOOKTYPE=incoming |
|
276 | 276 | HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd |
|
277 | 277 | HG_SOURCE=pull |
|
278 | 278 | HG_TXNID=TXN:$ID$ |
|
279 | 279 | HG_TXNNAME=pull |
|
280 | 280 | file:/*/$TESTTMP/a (glob) |
|
281 | 281 | HG_URL=file:$TESTTMP/a |
|
282 | 282 | |
|
283 | 283 | incoming hook: HG_HOOKNAME=incoming |
|
284 | 284 | HG_HOOKTYPE=incoming |
|
285 | 285 | HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 |
|
286 | 286 | HG_SOURCE=pull |
|
287 | 287 | HG_TXNID=TXN:$ID$ |
|
288 | 288 | HG_TXNNAME=pull |
|
289 | 289 | file:/*/$TESTTMP/a (glob) |
|
290 | 290 | HG_URL=file:$TESTTMP/a |
|
291 | 291 | |
|
292 | 292 | incoming hook: HG_HOOKNAME=incoming |
|
293 | 293 | HG_HOOKTYPE=incoming |
|
294 | 294 | HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 |
|
295 | 295 | HG_SOURCE=pull |
|
296 | 296 | HG_TXNID=TXN:$ID$ |
|
297 | 297 | HG_TXNNAME=pull |
|
298 | 298 | file:/*/$TESTTMP/a (glob) |
|
299 | 299 | HG_URL=file:$TESTTMP/a |
|
300 | 300 | |
|
301 | 301 | (run 'hg update' to get a working copy) |
|
302 | 302 | |
|
303 | 303 | tag hooks can see env vars |
|
304 | 304 | |
|
305 | 305 | $ cd ../a |
|
306 | 306 | $ cat >> .hg/hgrc <<EOF |
|
307 | 307 | > pretag = sh -c "printenv.py --line pretag" |
|
308 | 308 | > tag = sh -c "HG_PARENT1= HG_PARENT2= printenv.py --line tag" |
|
309 | 309 | > EOF |
|
310 | 310 | $ hg tag -d '3 0' a |
|
311 | 311 | pretag hook: HG_HOOKNAME=pretag |
|
312 | 312 | HG_HOOKTYPE=pretag |
|
313 | 313 | HG_LOCAL=0 |
|
314 | 314 | HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 |
|
315 | 315 | HG_TAG=a |
|
316 | 316 | |
|
317 | 317 | precommit hook: HG_HOOKNAME=precommit |
|
318 | 318 | HG_HOOKTYPE=precommit |
|
319 | 319 | HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 |
|
320 | 320 | |
|
321 | 321 | pretxnopen hook: HG_HOOKNAME=pretxnopen |
|
322 | 322 | HG_HOOKTYPE=pretxnopen |
|
323 | 323 | HG_TXNID=TXN:$ID$ |
|
324 | 324 | HG_TXNNAME=commit |
|
325 | 325 | |
|
326 | 326 | pretxncommit hook: HG_HOOKNAME=pretxncommit |
|
327 | 327 | HG_HOOKTYPE=pretxncommit |
|
328 | 328 | HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
329 | 329 | HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 |
|
330 | 330 | HG_PENDING=$TESTTMP/a |
|
331 | 331 | |
|
332 | 332 | 4:539e4b31b6dc |
|
333 | 333 | pretxnclose hook: HG_HOOKNAME=pretxnclose |
|
334 | 334 | HG_HOOKTYPE=pretxnclose |
|
335 | 335 | HG_PENDING=$TESTTMP/a |
|
336 | 336 | HG_TXNID=TXN:$ID$ |
|
337 | 337 | HG_TXNNAME=commit |
|
338 | 338 | |
|
339 | 339 | tag hook: HG_HOOKNAME=tag |
|
340 | 340 | HG_HOOKTYPE=tag |
|
341 | 341 | HG_LOCAL=0 |
|
342 | 342 | HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 |
|
343 | 343 | HG_TAG=a |
|
344 | 344 | |
|
345 | 345 | txnclose hook: HG_HOOKNAME=txnclose |
|
346 | 346 | HG_HOOKTYPE=txnclose |
|
347 | 347 | HG_TXNID=TXN:$ID$ |
|
348 | 348 | HG_TXNNAME=commit |
|
349 | 349 | |
|
350 | 350 | commit hook: HG_HOOKNAME=commit |
|
351 | 351 | HG_HOOKTYPE=commit |
|
352 | 352 | HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
353 | 353 | HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 |
|
354 | 354 | |
|
355 | 355 | commit.b hook: HG_HOOKNAME=commit.b |
|
356 | 356 | HG_HOOKTYPE=commit |
|
357 | 357 | HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
358 | 358 | HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 |
|
359 | 359 | |
|
360 | 360 | $ hg tag -l la |
|
361 | 361 | pretag hook: HG_HOOKNAME=pretag |
|
362 | 362 | HG_HOOKTYPE=pretag |
|
363 | 363 | HG_LOCAL=1 |
|
364 | 364 | HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
365 | 365 | HG_TAG=la |
|
366 | 366 | |
|
367 | 367 | tag hook: HG_HOOKNAME=tag |
|
368 | 368 | HG_HOOKTYPE=tag |
|
369 | 369 | HG_LOCAL=1 |
|
370 | 370 | HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
371 | 371 | HG_TAG=la |
|
372 | 372 | |
|
373 | 373 | |
|
374 | 374 | pretag hook can forbid tagging |
|
375 | 375 | |
|
376 | 376 | $ cat >> .hg/hgrc <<EOF |
|
377 | 377 | > pretag.forbid = sh -c "printenv.py --line pretag.forbid 1" |
|
378 | 378 | > EOF |
|
379 | 379 | $ hg tag -d '4 0' fa |
|
380 | 380 | pretag hook: HG_HOOKNAME=pretag |
|
381 | 381 | HG_HOOKTYPE=pretag |
|
382 | 382 | HG_LOCAL=0 |
|
383 | 383 | HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
384 | 384 | HG_TAG=fa |
|
385 | 385 | |
|
386 | 386 | pretag.forbid hook: HG_HOOKNAME=pretag.forbid |
|
387 | 387 | HG_HOOKTYPE=pretag |
|
388 | 388 | HG_LOCAL=0 |
|
389 | 389 | HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
390 | 390 | HG_TAG=fa |
|
391 | 391 | |
|
392 | 392 | abort: pretag.forbid hook exited with status 1 |
|
393 | 393 | [40] |
|
394 | 394 | $ hg tag -l fla |
|
395 | 395 | pretag hook: HG_HOOKNAME=pretag |
|
396 | 396 | HG_HOOKTYPE=pretag |
|
397 | 397 | HG_LOCAL=1 |
|
398 | 398 | HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
399 | 399 | HG_TAG=fla |
|
400 | 400 | |
|
401 | 401 | pretag.forbid hook: HG_HOOKNAME=pretag.forbid |
|
402 | 402 | HG_HOOKTYPE=pretag |
|
403 | 403 | HG_LOCAL=1 |
|
404 | 404 | HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
405 | 405 | HG_TAG=fla |
|
406 | 406 | |
|
407 | 407 | abort: pretag.forbid hook exited with status 1 |
|
408 | 408 | [40] |
|
409 | 409 | |
|
410 | 410 | pretxncommit hook can see changeset, can roll back txn, changeset no |
|
411 | 411 | more there after |
|
412 | 412 | |
|
413 | 413 | $ cat >> .hg/hgrc <<EOF |
|
414 | 414 | > pretxncommit.forbid0 = sh -c "hg tip -q" |
|
415 | 415 | > pretxncommit.forbid1 = sh -c "printenv.py --line pretxncommit.forbid 1" |
|
416 | 416 | > EOF |
|
417 | 417 | $ echo z > z |
|
418 | 418 | $ hg add z |
|
419 | 419 | $ hg -q tip |
|
420 | 420 | 4:539e4b31b6dc |
|
421 | 421 | $ hg commit -m 'fail' -d '4 0' |
|
422 | 422 | precommit hook: HG_HOOKNAME=precommit |
|
423 | 423 | HG_HOOKTYPE=precommit |
|
424 | 424 | HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
425 | 425 | |
|
426 | 426 | pretxnopen hook: HG_HOOKNAME=pretxnopen |
|
427 | 427 | HG_HOOKTYPE=pretxnopen |
|
428 | 428 | HG_TXNID=TXN:$ID$ |
|
429 | 429 | HG_TXNNAME=commit |
|
430 | 430 | |
|
431 | 431 | pretxncommit hook: HG_HOOKNAME=pretxncommit |
|
432 | 432 | HG_HOOKTYPE=pretxncommit |
|
433 | 433 | HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 |
|
434 | 434 | HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
435 | 435 | HG_PENDING=$TESTTMP/a |
|
436 | 436 | |
|
437 | 437 | 5:6f611f8018c1 |
|
438 | 438 | 5:6f611f8018c1 |
|
439 | 439 | pretxncommit.forbid hook: HG_HOOKNAME=pretxncommit.forbid1 |
|
440 | 440 | HG_HOOKTYPE=pretxncommit |
|
441 | 441 | HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 |
|
442 | 442 | HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
443 | 443 | HG_PENDING=$TESTTMP/a |
|
444 | 444 | |
|
445 | 445 | transaction abort! |
|
446 | 446 | txnabort Python hook: changes,txnid,txnname |
|
447 | 447 | txnabort hook: HG_HOOKNAME=txnabort.1 |
|
448 | 448 | HG_HOOKTYPE=txnabort |
|
449 | 449 | HG_TXNID=TXN:$ID$ |
|
450 | 450 | HG_TXNNAME=commit |
|
451 | 451 | |
|
452 | 452 | rollback completed |
|
453 | 453 | abort: pretxncommit.forbid1 hook exited with status 1 |
|
454 | 454 | [40] |
|
455 | 455 | $ hg -q tip |
|
456 | 456 | 4:539e4b31b6dc |
|
457 | 457 | |
|
458 | 458 | (Check that no 'changelog.i.a' file were left behind) |
|
459 | 459 | |
|
460 | 460 | $ ls -1 .hg/store/ |
|
461 | 461 | 00changelog.i |
|
462 | 462 | 00manifest.i |
|
463 | 463 | data |
|
464 | 464 | fncache (repofncache !) |
|
465 | 465 | phaseroots |
|
466 | 466 | requires |
|
467 | 467 | undo |
|
468 | undo.backup.fncache (repofncache !) | |
|
468 | undo.backup.fncache.bck (repofncache !) | |
|
469 | 469 | undo.backupfiles |
|
470 | 470 | |
|
471 | 471 | |
|
472 | 472 | precommit hook can prevent commit |
|
473 | 473 | |
|
474 | 474 | $ cat >> .hg/hgrc <<EOF |
|
475 | 475 | > precommit.forbid = sh -c "printenv.py --line precommit.forbid 1" |
|
476 | 476 | > EOF |
|
477 | 477 | $ hg commit -m 'fail' -d '4 0' |
|
478 | 478 | precommit hook: HG_HOOKNAME=precommit |
|
479 | 479 | HG_HOOKTYPE=precommit |
|
480 | 480 | HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
481 | 481 | |
|
482 | 482 | precommit.forbid hook: HG_HOOKNAME=precommit.forbid |
|
483 | 483 | HG_HOOKTYPE=precommit |
|
484 | 484 | HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
485 | 485 | |
|
486 | 486 | abort: precommit.forbid hook exited with status 1 |
|
487 | 487 | [40] |
|
488 | 488 | $ hg -q tip |
|
489 | 489 | 4:539e4b31b6dc |
|
490 | 490 | |
|
491 | 491 | preupdate hook can prevent update |
|
492 | 492 | |
|
493 | 493 | $ cat >> .hg/hgrc <<EOF |
|
494 | 494 | > preupdate = sh -c "printenv.py --line preupdate" |
|
495 | 495 | > EOF |
|
496 | 496 | $ hg update 1 |
|
497 | 497 | preupdate hook: HG_HOOKNAME=preupdate |
|
498 | 498 | HG_HOOKTYPE=preupdate |
|
499 | 499 | HG_PARENT1=ab228980c14d |
|
500 | 500 | |
|
501 | 501 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
502 | 502 | |
|
503 | 503 | update hook |
|
504 | 504 | |
|
505 | 505 | $ cat >> .hg/hgrc <<EOF |
|
506 | 506 | > update = sh -c "printenv.py --line update" |
|
507 | 507 | > EOF |
|
508 | 508 | $ hg update |
|
509 | 509 | preupdate hook: HG_HOOKNAME=preupdate |
|
510 | 510 | HG_HOOKTYPE=preupdate |
|
511 | 511 | HG_PARENT1=539e4b31b6dc |
|
512 | 512 | |
|
513 | 513 | update hook: HG_ERROR=0 |
|
514 | 514 | HG_HOOKNAME=update |
|
515 | 515 | HG_HOOKTYPE=update |
|
516 | 516 | HG_PARENT1=539e4b31b6dc |
|
517 | 517 | |
|
518 | 518 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
519 | 519 | |
|
520 | 520 | pushkey hook |
|
521 | 521 | |
|
522 | 522 | $ cat >> .hg/hgrc <<EOF |
|
523 | 523 | > pushkey = sh -c "printenv.py --line pushkey" |
|
524 | 524 | > EOF |
|
525 | 525 | $ cd ../b |
|
526 | 526 | $ hg bookmark -r null foo |
|
527 | 527 | $ hg push -B foo ../a |
|
528 | 528 | pushing to ../a |
|
529 | 529 | searching for changes |
|
530 | 530 | no changes found |
|
531 | 531 | pretxnopen hook: HG_HOOKNAME=pretxnopen |
|
532 | 532 | HG_HOOKTYPE=pretxnopen |
|
533 | 533 | HG_TXNID=TXN:$ID$ |
|
534 | 534 | HG_TXNNAME=push |
|
535 | 535 | |
|
536 | 536 | pretxnclose hook: HG_BOOKMARK_MOVED=1 |
|
537 | 537 | HG_BUNDLE2=1 |
|
538 | 538 | HG_HOOKNAME=pretxnclose |
|
539 | 539 | HG_HOOKTYPE=pretxnclose |
|
540 | 540 | HG_PENDING=$TESTTMP/a |
|
541 | 541 | HG_SOURCE=push |
|
542 | 542 | HG_TXNID=TXN:$ID$ |
|
543 | 543 | HG_TXNNAME=push |
|
544 | 544 | HG_URL=file:$TESTTMP/a |
|
545 | 545 | |
|
546 | 546 | pushkey hook: HG_BUNDLE2=1 |
|
547 | 547 | HG_HOOKNAME=pushkey |
|
548 | 548 | HG_HOOKTYPE=pushkey |
|
549 | 549 | HG_KEY=foo |
|
550 | 550 | HG_NAMESPACE=bookmarks |
|
551 | 551 | HG_NEW=0000000000000000000000000000000000000000 |
|
552 | 552 | HG_PUSHKEYCOMPAT=1 |
|
553 | 553 | HG_SOURCE=push |
|
554 | 554 | HG_TXNID=TXN:$ID$ |
|
555 | 555 | HG_TXNNAME=push |
|
556 | 556 | HG_URL=file:$TESTTMP/a |
|
557 | 557 | |
|
558 | 558 | txnclose hook: HG_BOOKMARK_MOVED=1 |
|
559 | 559 | HG_BUNDLE2=1 |
|
560 | 560 | HG_HOOKNAME=txnclose |
|
561 | 561 | HG_HOOKTYPE=txnclose |
|
562 | 562 | HG_SOURCE=push |
|
563 | 563 | HG_TXNID=TXN:$ID$ |
|
564 | 564 | HG_TXNNAME=push |
|
565 | 565 | HG_URL=file:$TESTTMP/a |
|
566 | 566 | |
|
567 | 567 | exporting bookmark foo |
|
568 | 568 | [1] |
|
569 | 569 | $ cd ../a |
|
570 | 570 | |
|
571 | 571 | listkeys hook |
|
572 | 572 | |
|
573 | 573 | $ cat >> .hg/hgrc <<EOF |
|
574 | 574 | > listkeys = sh -c "printenv.py --line listkeys" |
|
575 | 575 | > EOF |
|
576 | 576 | $ hg bookmark -r null bar |
|
577 | 577 | pretxnopen hook: HG_HOOKNAME=pretxnopen |
|
578 | 578 | HG_HOOKTYPE=pretxnopen |
|
579 | 579 | HG_TXNID=TXN:$ID$ |
|
580 | 580 | HG_TXNNAME=bookmark |
|
581 | 581 | |
|
582 | 582 | pretxnclose hook: HG_BOOKMARK_MOVED=1 |
|
583 | 583 | HG_HOOKNAME=pretxnclose |
|
584 | 584 | HG_HOOKTYPE=pretxnclose |
|
585 | 585 | HG_PENDING=$TESTTMP/a |
|
586 | 586 | HG_TXNID=TXN:$ID$ |
|
587 | 587 | HG_TXNNAME=bookmark |
|
588 | 588 | |
|
589 | 589 | txnclose hook: HG_BOOKMARK_MOVED=1 |
|
590 | 590 | HG_HOOKNAME=txnclose |
|
591 | 591 | HG_HOOKTYPE=txnclose |
|
592 | 592 | HG_TXNID=TXN:$ID$ |
|
593 | 593 | HG_TXNNAME=bookmark |
|
594 | 594 | |
|
595 | 595 | $ cd ../b |
|
596 | 596 | $ hg pull -B bar ../a |
|
597 | 597 | pulling from ../a |
|
598 | 598 | listkeys hook: HG_HOOKNAME=listkeys |
|
599 | 599 | HG_HOOKTYPE=listkeys |
|
600 | 600 | HG_NAMESPACE=bookmarks |
|
601 | 601 | HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} |
|
602 | 602 | |
|
603 | 603 | no changes found |
|
604 | 604 | adding remote bookmark bar |
|
605 | 605 | $ cd ../a |
|
606 | 606 | |
|
607 | 607 | test that prepushkey can prevent incoming keys |
|
608 | 608 | |
|
609 | 609 | $ cat >> .hg/hgrc <<EOF |
|
610 | 610 | > prepushkey = sh -c "printenv.py --line prepushkey.forbid 1" |
|
611 | 611 | > EOF |
|
612 | 612 | $ cd ../b |
|
613 | 613 | $ hg bookmark -r null baz |
|
614 | 614 | $ hg push -B baz ../a |
|
615 | 615 | pushing to ../a |
|
616 | 616 | searching for changes |
|
617 | 617 | listkeys hook: HG_HOOKNAME=listkeys |
|
618 | 618 | HG_HOOKTYPE=listkeys |
|
619 | 619 | HG_NAMESPACE=phases |
|
620 | 620 | HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'} |
|
621 | 621 | |
|
622 | 622 | listkeys hook: HG_HOOKNAME=listkeys |
|
623 | 623 | HG_HOOKTYPE=listkeys |
|
624 | 624 | HG_NAMESPACE=bookmarks |
|
625 | 625 | HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} |
|
626 | 626 | |
|
627 | 627 | no changes found |
|
628 | 628 | pretxnopen hook: HG_HOOKNAME=pretxnopen |
|
629 | 629 | HG_HOOKTYPE=pretxnopen |
|
630 | 630 | HG_TXNID=TXN:$ID$ |
|
631 | 631 | HG_TXNNAME=push |
|
632 | 632 | |
|
633 | 633 | prepushkey.forbid hook: HG_BUNDLE2=1 |
|
634 | 634 | HG_HOOKNAME=prepushkey |
|
635 | 635 | HG_HOOKTYPE=prepushkey |
|
636 | 636 | HG_KEY=baz |
|
637 | 637 | HG_NAMESPACE=bookmarks |
|
638 | 638 | HG_NEW=0000000000000000000000000000000000000000 |
|
639 | 639 | HG_PUSHKEYCOMPAT=1 |
|
640 | 640 | HG_SOURCE=push |
|
641 | 641 | HG_TXNID=TXN:$ID$ |
|
642 | 642 | HG_TXNNAME=push |
|
643 | 643 | HG_URL=file:$TESTTMP/a |
|
644 | 644 | |
|
645 | 645 | txnabort Python hook: bundle2,changes,source,txnid,txnname,url |
|
646 | 646 | txnabort hook: HG_BUNDLE2=1 |
|
647 | 647 | HG_HOOKNAME=txnabort.1 |
|
648 | 648 | HG_HOOKTYPE=txnabort |
|
649 | 649 | HG_SOURCE=push |
|
650 | 650 | HG_TXNID=TXN:$ID$ |
|
651 | 651 | HG_TXNNAME=push |
|
652 | 652 | HG_URL=file:$TESTTMP/a |
|
653 | 653 | |
|
654 | 654 | abort: prepushkey hook exited with status 1 |
|
655 | 655 | [40] |
|
656 | 656 | $ cd ../a |
|
657 | 657 | |
|
658 | 658 | test that prelistkeys can prevent listing keys |
|
659 | 659 | |
|
660 | 660 | $ cat >> .hg/hgrc <<EOF |
|
661 | 661 | > prelistkeys = sh -c "printenv.py --line prelistkeys.forbid 1" |
|
662 | 662 | > EOF |
|
663 | 663 | $ hg bookmark -r null quux |
|
664 | 664 | pretxnopen hook: HG_HOOKNAME=pretxnopen |
|
665 | 665 | HG_HOOKTYPE=pretxnopen |
|
666 | 666 | HG_TXNID=TXN:$ID$ |
|
667 | 667 | HG_TXNNAME=bookmark |
|
668 | 668 | |
|
669 | 669 | pretxnclose hook: HG_BOOKMARK_MOVED=1 |
|
670 | 670 | HG_HOOKNAME=pretxnclose |
|
671 | 671 | HG_HOOKTYPE=pretxnclose |
|
672 | 672 | HG_PENDING=$TESTTMP/a |
|
673 | 673 | HG_TXNID=TXN:$ID$ |
|
674 | 674 | HG_TXNNAME=bookmark |
|
675 | 675 | |
|
676 | 676 | txnclose hook: HG_BOOKMARK_MOVED=1 |
|
677 | 677 | HG_HOOKNAME=txnclose |
|
678 | 678 | HG_HOOKTYPE=txnclose |
|
679 | 679 | HG_TXNID=TXN:$ID$ |
|
680 | 680 | HG_TXNNAME=bookmark |
|
681 | 681 | |
|
682 | 682 | $ cd ../b |
|
683 | 683 | $ hg pull -B quux ../a |
|
684 | 684 | pulling from ../a |
|
685 | 685 | prelistkeys.forbid hook: HG_HOOKNAME=prelistkeys |
|
686 | 686 | HG_HOOKTYPE=prelistkeys |
|
687 | 687 | HG_NAMESPACE=bookmarks |
|
688 | 688 | |
|
689 | 689 | abort: prelistkeys hook exited with status 1 |
|
690 | 690 | [40] |
|
691 | 691 | $ cd ../a |
|
692 | 692 | $ rm .hg/hgrc |
|
693 | 693 | |
|
694 | 694 | prechangegroup hook can prevent incoming changes |
|
695 | 695 | |
|
696 | 696 | $ cd ../b |
|
697 | 697 | $ hg -q tip |
|
698 | 698 | 3:07f3376c1e65 |
|
699 | 699 | $ cat > .hg/hgrc <<EOF |
|
700 | 700 | > [hooks] |
|
701 | 701 | > prechangegroup.forbid = sh -c "printenv.py --line prechangegroup.forbid 1" |
|
702 | 702 | > EOF |
|
703 | 703 | $ hg pull ../a |
|
704 | 704 | pulling from ../a |
|
705 | 705 | searching for changes |
|
706 | 706 | prechangegroup.forbid hook: HG_HOOKNAME=prechangegroup.forbid |
|
707 | 707 | HG_HOOKTYPE=prechangegroup |
|
708 | 708 | HG_SOURCE=pull |
|
709 | 709 | HG_TXNID=TXN:$ID$ |
|
710 | 710 | HG_TXNNAME=pull |
|
711 | 711 | file:/*/$TESTTMP/a (glob) |
|
712 | 712 | HG_URL=file:$TESTTMP/a |
|
713 | 713 | |
|
714 | 714 | abort: prechangegroup.forbid hook exited with status 1 |
|
715 | 715 | [40] |
|
716 | 716 | |
|
717 | 717 | pretxnchangegroup hook can see incoming changes, can roll back txn, |
|
718 | 718 | incoming changes no longer there after |
|
719 | 719 | |
|
720 | 720 | $ cat > .hg/hgrc <<EOF |
|
721 | 721 | > [hooks] |
|
722 | 722 | > pretxnchangegroup.forbid0 = hg tip -q |
|
723 | 723 | > pretxnchangegroup.forbid1 = sh -c "printenv.py --line pretxnchangegroup.forbid 1" |
|
724 | 724 | > EOF |
|
725 | 725 | $ hg pull ../a |
|
726 | 726 | pulling from ../a |
|
727 | 727 | searching for changes |
|
728 | 728 | adding changesets |
|
729 | 729 | adding manifests |
|
730 | 730 | adding file changes |
|
731 | 731 | 4:539e4b31b6dc |
|
732 | 732 | pretxnchangegroup.forbid hook: HG_HOOKNAME=pretxnchangegroup.forbid1 |
|
733 | 733 | HG_HOOKTYPE=pretxnchangegroup |
|
734 | 734 | HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
735 | 735 | HG_NODE_LAST=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
736 | 736 | HG_PENDING=$TESTTMP/b |
|
737 | 737 | HG_SOURCE=pull |
|
738 | 738 | HG_TXNID=TXN:$ID$ |
|
739 | 739 | HG_TXNNAME=pull |
|
740 | 740 | file:/*/$TESTTMP/a (glob) |
|
741 | 741 | HG_URL=file:$TESTTMP/a |
|
742 | 742 | |
|
743 | 743 | transaction abort! |
|
744 | 744 | rollback completed |
|
745 | 745 | abort: pretxnchangegroup.forbid1 hook exited with status 1 |
|
746 | 746 | [40] |
|
747 | 747 | $ hg -q tip |
|
748 | 748 | 3:07f3376c1e65 |
|
749 | 749 | |
|
750 | 750 | outgoing hooks can see env vars |
|
751 | 751 | |
|
752 | 752 | $ rm .hg/hgrc |
|
753 | 753 | $ cat > ../a/.hg/hgrc <<EOF |
|
754 | 754 | > [hooks] |
|
755 | 755 | > preoutgoing = sh -c "printenv.py --line preoutgoing" |
|
756 | 756 | > outgoing = sh -c "printenv.py --line outgoing" |
|
757 | 757 | > EOF |
|
758 | 758 | $ hg pull ../a |
|
759 | 759 | pulling from ../a |
|
760 | 760 | searching for changes |
|
761 | 761 | preoutgoing hook: HG_HOOKNAME=preoutgoing |
|
762 | 762 | HG_HOOKTYPE=preoutgoing |
|
763 | 763 | HG_SOURCE=pull |
|
764 | 764 | |
|
765 | 765 | outgoing hook: HG_HOOKNAME=outgoing |
|
766 | 766 | HG_HOOKTYPE=outgoing |
|
767 | 767 | HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
768 | 768 | HG_SOURCE=pull |
|
769 | 769 | |
|
770 | 770 | adding changesets |
|
771 | 771 | adding manifests |
|
772 | 772 | adding file changes |
|
773 | 773 | adding remote bookmark quux |
|
774 | 774 | added 1 changesets with 1 changes to 1 files |
|
775 | 775 | new changesets 539e4b31b6dc |
|
776 | 776 | (run 'hg update' to get a working copy) |
|
777 | 777 | $ hg rollback |
|
778 | 778 | repository tip rolled back to revision 3 (undo pull) |
|
779 | 779 | |
|
780 | 780 | preoutgoing hook can prevent outgoing changes |
|
781 | 781 | |
|
782 | 782 | $ cat >> ../a/.hg/hgrc <<EOF |
|
783 | 783 | > preoutgoing.forbid = sh -c "printenv.py --line preoutgoing.forbid 1" |
|
784 | 784 | > EOF |
|
785 | 785 | $ hg pull ../a |
|
786 | 786 | pulling from ../a |
|
787 | 787 | searching for changes |
|
788 | 788 | preoutgoing hook: HG_HOOKNAME=preoutgoing |
|
789 | 789 | HG_HOOKTYPE=preoutgoing |
|
790 | 790 | HG_SOURCE=pull |
|
791 | 791 | |
|
792 | 792 | preoutgoing.forbid hook: HG_HOOKNAME=preoutgoing.forbid |
|
793 | 793 | HG_HOOKTYPE=preoutgoing |
|
794 | 794 | HG_SOURCE=pull |
|
795 | 795 | |
|
796 | 796 | abort: preoutgoing.forbid hook exited with status 1 |
|
797 | 797 | [40] |
|
798 | 798 | |
|
799 | 799 | outgoing hooks work for local clones |
|
800 | 800 | |
|
801 | 801 | $ cd .. |
|
802 | 802 | $ cat > a/.hg/hgrc <<EOF |
|
803 | 803 | > [hooks] |
|
804 | 804 | > preoutgoing = sh -c "printenv.py --line preoutgoing" |
|
805 | 805 | > outgoing = sh -c "printenv.py --line outgoing" |
|
806 | 806 | > EOF |
|
807 | 807 | $ hg clone a c |
|
808 | 808 | preoutgoing hook: HG_HOOKNAME=preoutgoing |
|
809 | 809 | HG_HOOKTYPE=preoutgoing |
|
810 | 810 | HG_SOURCE=clone |
|
811 | 811 | |
|
812 | 812 | outgoing hook: HG_HOOKNAME=outgoing |
|
813 | 813 | HG_HOOKTYPE=outgoing |
|
814 | 814 | HG_NODE=0000000000000000000000000000000000000000 |
|
815 | 815 | HG_SOURCE=clone |
|
816 | 816 | |
|
817 | 817 | updating to branch default |
|
818 | 818 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
819 | 819 | $ rm -rf c |
|
820 | 820 | |
|
821 | 821 | preoutgoing hook can prevent outgoing changes for local clones |
|
822 | 822 | |
|
823 | 823 | $ cat >> a/.hg/hgrc <<EOF |
|
824 | 824 | > preoutgoing.forbid = sh -c "printenv.py --line preoutgoing.forbid 1" |
|
825 | 825 | > EOF |
|
826 | 826 | $ hg clone a zzz |
|
827 | 827 | preoutgoing hook: HG_HOOKNAME=preoutgoing |
|
828 | 828 | HG_HOOKTYPE=preoutgoing |
|
829 | 829 | HG_SOURCE=clone |
|
830 | 830 | |
|
831 | 831 | preoutgoing.forbid hook: HG_HOOKNAME=preoutgoing.forbid |
|
832 | 832 | HG_HOOKTYPE=preoutgoing |
|
833 | 833 | HG_SOURCE=clone |
|
834 | 834 | |
|
835 | 835 | abort: preoutgoing.forbid hook exited with status 1 |
|
836 | 836 | [40] |
|
837 | 837 | |
|
838 | 838 | $ cd "$TESTTMP/b" |
|
839 | 839 | |
|
840 | 840 | $ cat > hooktests.py <<EOF |
|
841 | 841 | > from mercurial import ( |
|
842 | 842 | > error, |
|
843 | 843 | > pycompat, |
|
844 | 844 | > ) |
|
845 | 845 | > |
|
846 | 846 | > uncallable = 0 |
|
847 | 847 | > |
|
848 | 848 | > def printargs(ui, args): |
|
849 | 849 | > a = list(pycompat.byteskwargs(args).items()) |
|
850 | 850 | > a.sort() |
|
851 | 851 | > ui.write(b'hook args:\n') |
|
852 | 852 | > for k, v in a: |
|
853 | 853 | > ui.write(b' %s %s\n' % (k, v)) |
|
854 | 854 | > |
|
855 | 855 | > def passhook(ui, repo, **args): |
|
856 | 856 | > printargs(ui, args) |
|
857 | 857 | > |
|
858 | 858 | > def failhook(ui, repo, **args): |
|
859 | 859 | > printargs(ui, args) |
|
860 | 860 | > return True |
|
861 | 861 | > |
|
862 | 862 | > class LocalException(Exception): |
|
863 | 863 | > pass |
|
864 | 864 | > |
|
865 | 865 | > def raisehook(**args): |
|
866 | 866 | > raise LocalException('exception from hook') |
|
867 | 867 | > |
|
868 | 868 | > def aborthook(**args): |
|
869 | 869 | > raise error.Abort(b'raise abort from hook') |
|
870 | 870 | > |
|
871 | 871 | > def brokenhook(**args): |
|
872 | 872 | > return 1 + {} |
|
873 | 873 | > |
|
874 | 874 | > def verbosehook(ui, **args): |
|
875 | 875 | > ui.note(b'verbose output from hook\n') |
|
876 | 876 | > |
|
877 | 877 | > def printtags(ui, repo, **args): |
|
878 | 878 | > ui.write(b'[%s]\n' % b', '.join(sorted(repo.tags()))) |
|
879 | 879 | > |
|
880 | 880 | > class container(object): |
|
881 | 881 | > unreachable = 1 |
|
882 | 882 | > EOF |
|
883 | 883 | |
|
884 | 884 | $ cat > syntaxerror.py << NO_CHECK_EOF |
|
885 | 885 | > (foo |
|
886 | 886 | > NO_CHECK_EOF |
|
887 | 887 | |
|
888 | 888 | test python hooks |
|
889 | 889 | |
|
890 | 890 | #if windows |
|
891 | 891 | $ PYTHONPATH="$TESTTMP/b;$PYTHONPATH" |
|
892 | 892 | #else |
|
893 | 893 | $ PYTHONPATH="$TESTTMP/b:$PYTHONPATH" |
|
894 | 894 | #endif |
|
895 | 895 | $ export PYTHONPATH |
|
896 | 896 | |
|
897 | 897 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
898 | 898 | $ echo 'preoutgoing.broken = python:hooktests.brokenhook' >> ../a/.hg/hgrc |
|
899 | 899 | $ hg pull ../a 2>&1 | grep 'raised an exception' |
|
900 | 900 | error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict' |
|
901 | 901 | |
|
902 | 902 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
903 | 903 | $ echo 'preoutgoing.raise = python:hooktests.raisehook' >> ../a/.hg/hgrc |
|
904 | 904 | $ hg pull ../a 2>&1 | grep 'raised an exception' |
|
905 | 905 | error: preoutgoing.raise hook raised an exception: exception from hook |
|
906 | 906 | |
|
907 | 907 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
908 | 908 | $ echo 'preoutgoing.abort = python:hooktests.aborthook' >> ../a/.hg/hgrc |
|
909 | 909 | $ hg pull ../a |
|
910 | 910 | pulling from ../a |
|
911 | 911 | searching for changes |
|
912 | 912 | error: preoutgoing.abort hook failed: raise abort from hook |
|
913 | 913 | abort: raise abort from hook |
|
914 | 914 | [255] |
|
915 | 915 | |
|
916 | 916 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
917 | 917 | $ echo 'preoutgoing.fail = python:hooktests.failhook' >> ../a/.hg/hgrc |
|
918 | 918 | $ hg pull ../a |
|
919 | 919 | pulling from ../a |
|
920 | 920 | searching for changes |
|
921 | 921 | hook args: |
|
922 | 922 | hooktype preoutgoing |
|
923 | 923 | source pull |
|
924 | 924 | abort: preoutgoing.fail hook failed |
|
925 | 925 | [40] |
|
926 | 926 | |
|
927 | 927 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
928 | 928 | $ echo 'preoutgoing.uncallable = python:hooktests.uncallable' >> ../a/.hg/hgrc |
|
929 | 929 | $ hg pull ../a |
|
930 | 930 | pulling from ../a |
|
931 | 931 | searching for changes |
|
932 | 932 | abort: preoutgoing.uncallable hook is invalid: "hooktests.uncallable" is not callable |
|
933 | 933 | [255] |
|
934 | 934 | |
|
935 | 935 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
936 | 936 | $ echo 'preoutgoing.nohook = python:hooktests.nohook' >> ../a/.hg/hgrc |
|
937 | 937 | $ hg pull ../a |
|
938 | 938 | pulling from ../a |
|
939 | 939 | searching for changes |
|
940 | 940 | abort: preoutgoing.nohook hook is invalid: "hooktests.nohook" is not defined |
|
941 | 941 | [255] |
|
942 | 942 | |
|
943 | 943 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
944 | 944 | $ echo 'preoutgoing.nomodule = python:nomodule' >> ../a/.hg/hgrc |
|
945 | 945 | $ hg pull ../a |
|
946 | 946 | pulling from ../a |
|
947 | 947 | searching for changes |
|
948 | 948 | abort: preoutgoing.nomodule hook is invalid: "nomodule" not in a module |
|
949 | 949 | [255] |
|
950 | 950 | |
|
951 | 951 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
952 | 952 | $ echo 'preoutgoing.badmodule = python:nomodule.nowhere' >> ../a/.hg/hgrc |
|
953 | 953 | $ hg pull ../a |
|
954 | 954 | pulling from ../a |
|
955 | 955 | searching for changes |
|
956 | 956 | abort: preoutgoing.badmodule hook is invalid: import of "nomodule" failed |
|
957 | 957 | (run with --traceback for stack trace) |
|
958 | 958 | [255] |
|
959 | 959 | |
|
960 | 960 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
961 | 961 | $ echo 'preoutgoing.unreachable = python:hooktests.container.unreachable' >> ../a/.hg/hgrc |
|
962 | 962 | $ hg pull ../a |
|
963 | 963 | pulling from ../a |
|
964 | 964 | searching for changes |
|
965 | 965 | abort: preoutgoing.unreachable hook is invalid: import of "hooktests.container" failed |
|
966 | 966 | (run with --traceback for stack trace) |
|
967 | 967 | [255] |
|
968 | 968 | |
|
969 | 969 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
970 | 970 | $ echo 'preoutgoing.syntaxerror = python:syntaxerror.syntaxerror' >> ../a/.hg/hgrc |
|
971 | 971 | $ hg pull ../a |
|
972 | 972 | pulling from ../a |
|
973 | 973 | searching for changes |
|
974 | 974 | abort: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed |
|
975 | 975 | (run with --traceback for stack trace) |
|
976 | 976 | [255] |
|
977 | 977 | |
|
978 | 978 | $ hg pull ../a --traceback 2>&1 | egrep 'pulling|searching|^exception|Traceback|SyntaxError|ImportError|ModuleNotFoundError|HookLoadError|abort' |
|
979 | 979 | pulling from ../a |
|
980 | 980 | searching for changes |
|
981 | 981 | exception from first failed import attempt: |
|
982 | 982 | Traceback (most recent call last): |
|
983 | 983 | SyntaxError: * (glob) |
|
984 | 984 | exception from second failed import attempt: |
|
985 | 985 | Traceback (most recent call last): |
|
986 | 986 | SyntaxError: * (glob) |
|
987 | 987 | Traceback (most recent call last): |
|
988 | 988 | ModuleNotFoundError: No module named 'hgext_syntaxerror' |
|
989 | 989 | Traceback (most recent call last): |
|
990 | 990 | SyntaxError: * (glob) |
|
991 | 991 | Traceback (most recent call last): |
|
992 | 992 | ModuleNotFoundError: No module named 'hgext_syntaxerror' |
|
993 | 993 | Traceback (most recent call last): |
|
994 | 994 | raise error.HookLoadError( (py38 !) |
|
995 | 995 | mercurial.error.HookLoadError: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed |
|
996 | 996 | abort: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed |
|
997 | 997 | |
|
998 | 998 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
999 | 999 | $ echo 'preoutgoing.pass = python:hooktests.passhook' >> ../a/.hg/hgrc |
|
1000 | 1000 | $ hg pull ../a |
|
1001 | 1001 | pulling from ../a |
|
1002 | 1002 | searching for changes |
|
1003 | 1003 | hook args: |
|
1004 | 1004 | hooktype preoutgoing |
|
1005 | 1005 | source pull |
|
1006 | 1006 | adding changesets |
|
1007 | 1007 | adding manifests |
|
1008 | 1008 | adding file changes |
|
1009 | 1009 | adding remote bookmark quux |
|
1010 | 1010 | added 1 changesets with 1 changes to 1 files |
|
1011 | 1011 | new changesets 539e4b31b6dc |
|
1012 | 1012 | (run 'hg update' to get a working copy) |
|
1013 | 1013 | |
|
1014 | 1014 | post- python hooks that fail to *run* don't cause an abort |
|
1015 | 1015 | $ rm ../a/.hg/hgrc |
|
1016 | 1016 | $ echo '[hooks]' > .hg/hgrc |
|
1017 | 1017 | $ echo 'post-pull.broken = python:hooktests.brokenhook' >> .hg/hgrc |
|
1018 | 1018 | $ hg pull ../a |
|
1019 | 1019 | pulling from ../a |
|
1020 | 1020 | searching for changes |
|
1021 | 1021 | no changes found |
|
1022 | 1022 | error: post-pull.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict' |
|
1023 | 1023 | (run with --traceback for stack trace) |
|
1024 | 1024 | |
|
1025 | 1025 | but post- python hooks that fail to *load* do |
|
1026 | 1026 | $ echo '[hooks]' > .hg/hgrc |
|
1027 | 1027 | $ echo 'post-pull.nomodule = python:nomodule' >> .hg/hgrc |
|
1028 | 1028 | $ hg pull ../a |
|
1029 | 1029 | pulling from ../a |
|
1030 | 1030 | searching for changes |
|
1031 | 1031 | no changes found |
|
1032 | 1032 | abort: post-pull.nomodule hook is invalid: "nomodule" not in a module |
|
1033 | 1033 | [255] |
|
1034 | 1034 | |
|
1035 | 1035 | $ echo '[hooks]' > .hg/hgrc |
|
1036 | 1036 | $ echo 'post-pull.badmodule = python:nomodule.nowhere' >> .hg/hgrc |
|
1037 | 1037 | $ hg pull ../a |
|
1038 | 1038 | pulling from ../a |
|
1039 | 1039 | searching for changes |
|
1040 | 1040 | no changes found |
|
1041 | 1041 | abort: post-pull.badmodule hook is invalid: import of "nomodule" failed |
|
1042 | 1042 | (run with --traceback for stack trace) |
|
1043 | 1043 | [255] |
|
1044 | 1044 | |
|
1045 | 1045 | $ echo '[hooks]' > .hg/hgrc |
|
1046 | 1046 | $ echo 'post-pull.nohook = python:hooktests.nohook' >> .hg/hgrc |
|
1047 | 1047 | $ hg pull ../a |
|
1048 | 1048 | pulling from ../a |
|
1049 | 1049 | searching for changes |
|
1050 | 1050 | no changes found |
|
1051 | 1051 | abort: post-pull.nohook hook is invalid: "hooktests.nohook" is not defined |
|
1052 | 1052 | [255] |
|
1053 | 1053 | |
|
1054 | 1054 | make sure --traceback works |
|
1055 | 1055 | |
|
1056 | 1056 | $ echo '[hooks]' > .hg/hgrc |
|
1057 | 1057 | $ echo 'commit.abort = python:hooktests.aborthook' >> .hg/hgrc |
|
1058 | 1058 | |
|
1059 | 1059 | $ echo aa > a |
|
1060 | 1060 | $ hg --traceback commit -d '0 0' -ma 2>&1 | grep '^Traceback' |
|
1061 | 1061 | Traceback (most recent call last): |
|
1062 | 1062 | |
|
1063 | 1063 | $ cd .. |
|
1064 | 1064 | $ hg init c |
|
1065 | 1065 | $ cd c |
|
1066 | 1066 | |
|
1067 | 1067 | $ cat > hookext.py <<EOF |
|
1068 | 1068 | > def autohook(ui, **args): |
|
1069 | 1069 | > ui.write(b'Automatically installed hook\n') |
|
1070 | 1070 | > |
|
1071 | 1071 | > def reposetup(ui, repo): |
|
1072 | 1072 | > repo.ui.setconfig(b"hooks", b"commit.auto", autohook) |
|
1073 | 1073 | > EOF |
|
1074 | 1074 | $ echo '[extensions]' >> .hg/hgrc |
|
1075 | 1075 | $ echo 'hookext = hookext.py' >> .hg/hgrc |
|
1076 | 1076 | |
|
1077 | 1077 | $ touch foo |
|
1078 | 1078 | $ hg add foo |
|
1079 | 1079 | $ hg ci -d '0 0' -m 'add foo' |
|
1080 | 1080 | Automatically installed hook |
|
1081 | 1081 | $ echo >> foo |
|
1082 | 1082 | $ hg ci --debug -d '0 0' -m 'change foo' |
|
1083 | 1083 | committing files: |
|
1084 | 1084 | foo |
|
1085 | 1085 | committing manifest |
|
1086 | 1086 | committing changelog |
|
1087 | 1087 | updating the branch cache |
|
1088 | 1088 | committed changeset 1:52998019f6252a2b893452765fcb0a47351a5708 |
|
1089 | 1089 | calling hook commit.auto: hgext_hookext.autohook |
|
1090 | 1090 | Automatically installed hook |
|
1091 | 1091 | |
|
1092 | 1092 | $ hg showconfig hooks |
|
1093 | 1093 | hooks.commit.auto=<function autohook at *> (glob) |
|
1094 | 1094 | |
|
1095 | 1095 | test python hook configured with python:[file]:[hook] syntax |
|
1096 | 1096 | |
|
1097 | 1097 | $ cd .. |
|
1098 | 1098 | $ mkdir d |
|
1099 | 1099 | $ cd d |
|
1100 | 1100 | $ hg init repo |
|
1101 | 1101 | $ mkdir hooks |
|
1102 | 1102 | |
|
1103 | 1103 | $ cd hooks |
|
1104 | 1104 | $ cat > testhooks.py <<EOF |
|
1105 | 1105 | > def testhook(ui, **args): |
|
1106 | 1106 | > ui.write(b'hook works\n') |
|
1107 | 1107 | > EOF |
|
1108 | 1108 | $ echo '[hooks]' > ../repo/.hg/hgrc |
|
1109 | 1109 | $ echo "pre-commit.test = python:`pwd`/testhooks.py:testhook" >> ../repo/.hg/hgrc |
|
1110 | 1110 | |
|
1111 | 1111 | $ cd ../repo |
|
1112 | 1112 | $ hg commit -d '0 0' |
|
1113 | 1113 | hook works |
|
1114 | 1114 | nothing changed |
|
1115 | 1115 | [1] |
|
1116 | 1116 | |
|
1117 | 1117 | $ echo '[hooks]' > .hg/hgrc |
|
1118 | 1118 | $ echo "update.ne = python:`pwd`/nonexistent.py:testhook" >> .hg/hgrc |
|
1119 | 1119 | $ echo "pre-identify.npmd = python:`pwd`/:no_python_module_dir" >> .hg/hgrc |
|
1120 | 1120 | |
|
1121 | 1121 | $ hg up null |
|
1122 | 1122 | loading update.ne hook failed: |
|
1123 | 1123 | abort: $ENOENT$: '$TESTTMP/d/repo/nonexistent.py' |
|
1124 | 1124 | [255] |
|
1125 | 1125 | |
|
1126 | 1126 | $ hg id |
|
1127 | 1127 | loading pre-identify.npmd hook failed: |
|
1128 | 1128 | abort: No module named 'repo' |
|
1129 | 1129 | [255] |
|
1130 | 1130 | |
|
1131 | 1131 | $ cd ../../b |
|
1132 | 1132 | |
|
1133 | 1133 | make sure --traceback works on hook import failure |
|
1134 | 1134 | |
|
1135 | 1135 | $ cat > importfail.py <<EOF |
|
1136 | 1136 | > import somebogusmodule |
|
1137 | 1137 | > # dereference something in the module to force demandimport to load it |
|
1138 | 1138 | > somebogusmodule.whatever |
|
1139 | 1139 | > EOF |
|
1140 | 1140 | |
|
1141 | 1141 | $ echo '[hooks]' > .hg/hgrc |
|
1142 | 1142 | $ echo 'precommit.importfail = python:importfail.whatever' >> .hg/hgrc |
|
1143 | 1143 | |
|
1144 | 1144 | $ echo a >> a |
|
1145 | 1145 | $ hg --traceback commit -ma 2>&1 | egrep '^exception|ImportError|ModuleNotFoundError|Traceback|HookLoadError|abort' |
|
1146 | 1146 | exception from first failed import attempt: |
|
1147 | 1147 | Traceback (most recent call last): |
|
1148 | 1148 | ModuleNotFoundError: No module named 'somebogusmodule' |
|
1149 | 1149 | exception from second failed import attempt: |
|
1150 | 1150 | Traceback (most recent call last): |
|
1151 | 1151 | ModuleNotFoundError: No module named 'somebogusmodule' |
|
1152 | 1152 | Traceback (most recent call last): |
|
1153 | 1153 | ModuleNotFoundError: No module named 'hgext_importfail' |
|
1154 | 1154 | Traceback (most recent call last): |
|
1155 | 1155 | ModuleNotFoundError: No module named 'somebogusmodule' |
|
1156 | 1156 | Traceback (most recent call last): |
|
1157 | 1157 | ModuleNotFoundError: No module named 'hgext_importfail' |
|
1158 | 1158 | Traceback (most recent call last): |
|
1159 | 1159 | raise error.HookLoadError( (py38 !) |
|
1160 | 1160 | mercurial.error.HookLoadError: precommit.importfail hook is invalid: import of "importfail" failed |
|
1161 | 1161 | abort: precommit.importfail hook is invalid: import of "importfail" failed |
|
1162 | 1162 | |
|
1163 | 1163 | Issue1827: Hooks Update & Commit not completely post operation |
|
1164 | 1164 | |
|
1165 | 1165 | commit and update hooks should run after command completion. The largefiles |
|
1166 | 1166 | use demonstrates a recursive wlock, showing the hook doesn't run until the |
|
1167 | 1167 | final release (and dirstate flush). |
|
1168 | 1168 | |
|
1169 | 1169 | $ echo '[hooks]' > .hg/hgrc |
|
1170 | 1170 | $ echo 'commit = hg id' >> .hg/hgrc |
|
1171 | 1171 | $ echo 'update = hg id' >> .hg/hgrc |
|
1172 | 1172 | $ echo bb > a |
|
1173 | 1173 | $ hg ci -ma |
|
1174 | 1174 | 223eafe2750c tip |
|
1175 | 1175 | $ hg up 0 --config extensions.largefiles= |
|
1176 | 1176 | The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !) |
|
1177 | 1177 | cb9a9f314b8b |
|
1178 | 1178 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
1179 | 1179 | |
|
1180 | 1180 | make sure --verbose (and --quiet/--debug etc.) are propagated to the local ui |
|
1181 | 1181 | that is passed to pre/post hooks |
|
1182 | 1182 | |
|
1183 | 1183 | $ echo '[hooks]' > .hg/hgrc |
|
1184 | 1184 | $ echo 'pre-identify = python:hooktests.verbosehook' >> .hg/hgrc |
|
1185 | 1185 | $ hg id |
|
1186 | 1186 | cb9a9f314b8b |
|
1187 | 1187 | $ hg id --verbose |
|
1188 | 1188 | calling hook pre-identify: hooktests.verbosehook |
|
1189 | 1189 | verbose output from hook |
|
1190 | 1190 | cb9a9f314b8b |
|
1191 | 1191 | |
|
1192 | 1192 | Ensure hooks can be prioritized |
|
1193 | 1193 | |
|
1194 | 1194 | $ echo '[hooks]' > .hg/hgrc |
|
1195 | 1195 | $ echo 'pre-identify.a = python:hooktests.verbosehook' >> .hg/hgrc |
|
1196 | 1196 | $ echo 'pre-identify.b = python:hooktests.verbosehook' >> .hg/hgrc |
|
1197 | 1197 | $ echo 'priority.pre-identify.b = 1' >> .hg/hgrc |
|
1198 | 1198 | $ echo 'pre-identify.c = python:hooktests.verbosehook' >> .hg/hgrc |
|
1199 | 1199 | $ hg id --verbose |
|
1200 | 1200 | calling hook pre-identify.b: hooktests.verbosehook |
|
1201 | 1201 | verbose output from hook |
|
1202 | 1202 | calling hook pre-identify.a: hooktests.verbosehook |
|
1203 | 1203 | verbose output from hook |
|
1204 | 1204 | calling hook pre-identify.c: hooktests.verbosehook |
|
1205 | 1205 | verbose output from hook |
|
1206 | 1206 | cb9a9f314b8b |
|
1207 | 1207 | |
|
1208 | 1208 | new tags must be visible in pretxncommit (issue3210) |
|
1209 | 1209 | |
|
1210 | 1210 | $ echo 'pretxncommit.printtags = python:hooktests.printtags' >> .hg/hgrc |
|
1211 | 1211 | $ hg tag -f foo |
|
1212 | 1212 | [a, foo, tip] |
|
1213 | 1213 | |
|
1214 | 1214 | post-init hooks must not crash (issue4983) |
|
1215 | 1215 | This also creates the `to` repo for the next test block. |
|
1216 | 1216 | |
|
1217 | 1217 | $ cd .. |
|
1218 | 1218 | $ cat << EOF >> hgrc-with-post-init-hook |
|
1219 | 1219 | > [hooks] |
|
1220 | 1220 | > post-init = sh -c "printenv.py --line post-init" |
|
1221 | 1221 | > EOF |
|
1222 | 1222 | $ HGRCPATH=hgrc-with-post-init-hook hg init to |
|
1223 | 1223 | post-init hook: HG_ARGS=init to |
|
1224 | 1224 | HG_HOOKNAME=post-init |
|
1225 | 1225 | HG_HOOKTYPE=post-init |
|
1226 | 1226 | HG_OPTS={'insecure': None, 'remotecmd': '', 'ssh': ''} |
|
1227 | 1227 | HG_PATS=['to'] |
|
1228 | 1228 | HG_RESULT=0 |
|
1229 | 1229 | |
|
1230 | 1230 | |
|
1231 | 1231 | new commits must be visible in pretxnchangegroup (issue3428) |
|
1232 | 1232 | |
|
1233 | 1233 | $ echo '[hooks]' >> to/.hg/hgrc |
|
1234 | 1234 | $ echo 'prechangegroup = hg --traceback tip' >> to/.hg/hgrc |
|
1235 | 1235 | $ echo 'pretxnchangegroup = hg --traceback tip' >> to/.hg/hgrc |
|
1236 | 1236 | $ echo a >> to/a |
|
1237 | 1237 | $ hg --cwd to ci -Ama |
|
1238 | 1238 | adding a |
|
1239 | 1239 | $ hg clone to from |
|
1240 | 1240 | updating to branch default |
|
1241 | 1241 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
1242 | 1242 | $ echo aa >> from/a |
|
1243 | 1243 | $ hg --cwd from ci -mb |
|
1244 | 1244 | $ hg --cwd from push |
|
1245 | 1245 | pushing to $TESTTMP/to |
|
1246 | 1246 | searching for changes |
|
1247 | 1247 | changeset: 0:cb9a9f314b8b |
|
1248 | 1248 | tag: tip |
|
1249 | 1249 | user: test |
|
1250 | 1250 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
1251 | 1251 | summary: a |
|
1252 | 1252 | |
|
1253 | 1253 | adding changesets |
|
1254 | 1254 | adding manifests |
|
1255 | 1255 | adding file changes |
|
1256 | 1256 | changeset: 1:9836a07b9b9d |
|
1257 | 1257 | tag: tip |
|
1258 | 1258 | user: test |
|
1259 | 1259 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
1260 | 1260 | summary: b |
|
1261 | 1261 | |
|
1262 | 1262 | added 1 changesets with 1 changes to 1 files |
|
1263 | 1263 | |
|
1264 | 1264 | pretxnclose hook failure should abort the transaction |
|
1265 | 1265 | |
|
1266 | 1266 | $ hg init txnfailure |
|
1267 | 1267 | $ cd txnfailure |
|
1268 | 1268 | $ touch a && hg commit -Aqm a |
|
1269 | 1269 | $ cat >> .hg/hgrc <<EOF |
|
1270 | 1270 | > [hooks] |
|
1271 | 1271 | > pretxnclose.error = exit 1 |
|
1272 | 1272 | > EOF |
|
1273 | 1273 | $ hg strip -r 0 --config extensions.strip= |
|
1274 | 1274 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
1275 | 1275 | saved backup bundle to * (glob) |
|
1276 | 1276 | transaction abort! |
|
1277 | 1277 | rollback completed |
|
1278 | 1278 | strip failed, backup bundle stored in * (glob) |
|
1279 | 1279 | abort: pretxnclose.error hook exited with status 1 |
|
1280 | 1280 | [40] |
|
1281 | 1281 | $ hg recover |
|
1282 | 1282 | no interrupted transaction available |
|
1283 | 1283 | [1] |
|
1284 | 1284 | $ cd .. |
|
1285 | 1285 | |
|
1286 | 1286 | check whether HG_PENDING makes pending changes only in related |
|
1287 | 1287 | repositories visible to an external hook. |
|
1288 | 1288 | |
|
1289 | 1289 | (emulate a transaction running concurrently by copied |
|
1290 | 1290 | .hg/store/00changelog.i.a in subsequent test) |
|
1291 | 1291 | |
|
1292 | 1292 | $ cat > $TESTTMP/savepending.sh <<EOF |
|
1293 | 1293 | > cp .hg/store/00changelog.i.a .hg/store/00changelog.i.a.saved |
|
1294 | 1294 | > exit 1 # to avoid adding new revision for subsequent tests |
|
1295 | 1295 | > EOF |
|
1296 | 1296 | $ cd a |
|
1297 | 1297 | $ hg tip -q |
|
1298 | 1298 | 4:539e4b31b6dc |
|
1299 | 1299 | $ hg --config hooks.pretxnclose="sh $TESTTMP/savepending.sh" commit -m "invisible" |
|
1300 | 1300 | transaction abort! |
|
1301 | 1301 | rollback completed |
|
1302 | 1302 | abort: pretxnclose hook exited with status 1 |
|
1303 | 1303 | [40] |
|
1304 | 1304 | $ cp .hg/store/00changelog.i.a.saved .hg/store/00changelog.i.a |
|
1305 | 1305 | |
|
1306 | 1306 | (check (in)visibility of new changeset while transaction running in |
|
1307 | 1307 | repo) |
|
1308 | 1308 | |
|
1309 | 1309 | $ cat > $TESTTMP/checkpending.sh <<EOF |
|
1310 | 1310 | > echo '@a' |
|
1311 | 1311 | > hg -R "$TESTTMP/a" tip -q |
|
1312 | 1312 | > echo '@a/nested' |
|
1313 | 1313 | > hg -R "$TESTTMP/a/nested" tip -q |
|
1314 | 1314 | > exit 1 # to avoid adding new revision for subsequent tests |
|
1315 | 1315 | > EOF |
|
1316 | 1316 | $ hg init nested |
|
1317 | 1317 | $ cd nested |
|
1318 | 1318 | $ echo a > a |
|
1319 | 1319 | $ hg add a |
|
1320 | 1320 | $ hg --config hooks.pretxnclose="sh $TESTTMP/checkpending.sh" commit -m '#0' |
|
1321 | 1321 | @a |
|
1322 | 1322 | 4:539e4b31b6dc |
|
1323 | 1323 | @a/nested |
|
1324 | 1324 | 0:bf5e395ced2c |
|
1325 | 1325 | transaction abort! |
|
1326 | 1326 | rollback completed |
|
1327 | 1327 | abort: pretxnclose hook exited with status 1 |
|
1328 | 1328 | [40] |
|
1329 | 1329 | |
|
1330 | 1330 | Hook from untrusted hgrc are reported as failure |
|
1331 | 1331 | ================================================ |
|
1332 | 1332 | |
|
1333 | 1333 | $ cat << EOF > $TESTTMP/untrusted.py |
|
1334 | 1334 | > from mercurial import scmutil, util |
|
1335 | 1335 | > def uisetup(ui): |
|
1336 | 1336 | > class untrustedui(ui.__class__): |
|
1337 | 1337 | > def _trusted(self, fp, f): |
|
1338 | 1338 | > if util.normpath(fp.name).endswith(b'untrusted/.hg/hgrc'): |
|
1339 | 1339 | > return False |
|
1340 | 1340 | > return super(untrustedui, self)._trusted(fp, f) |
|
1341 | 1341 | > ui.__class__ = untrustedui |
|
1342 | 1342 | > EOF |
|
1343 | 1343 | $ cat << EOF >> $HGRCPATH |
|
1344 | 1344 | > [extensions] |
|
1345 | 1345 | > untrusted=$TESTTMP/untrusted.py |
|
1346 | 1346 | > EOF |
|
1347 | 1347 | $ hg init untrusted |
|
1348 | 1348 | $ cd untrusted |
|
1349 | 1349 | |
|
1350 | 1350 | Non-blocking hook |
|
1351 | 1351 | ----------------- |
|
1352 | 1352 | |
|
1353 | 1353 | $ cat << EOF >> .hg/hgrc |
|
1354 | 1354 | > [hooks] |
|
1355 | 1355 | > txnclose.testing=echo txnclose hook called |
|
1356 | 1356 | > EOF |
|
1357 | 1357 | $ touch a && hg commit -Aqm a |
|
1358 | 1358 | warning: untrusted hook txnclose.testing not executed |
|
1359 | 1359 | $ hg log |
|
1360 | 1360 | changeset: 0:3903775176ed |
|
1361 | 1361 | tag: tip |
|
1362 | 1362 | user: test |
|
1363 | 1363 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
1364 | 1364 | summary: a |
|
1365 | 1365 | |
|
1366 | 1366 | |
|
1367 | 1367 | Non-blocking hook |
|
1368 | 1368 | ----------------- |
|
1369 | 1369 | |
|
1370 | 1370 | $ cat << EOF >> .hg/hgrc |
|
1371 | 1371 | > [hooks] |
|
1372 | 1372 | > pretxnclose.testing=echo pre-txnclose hook called |
|
1373 | 1373 | > EOF |
|
1374 | 1374 | $ touch b && hg commit -Aqm a |
|
1375 | 1375 | transaction abort! |
|
1376 | 1376 | rollback completed |
|
1377 | 1377 | abort: untrusted hook pretxnclose.testing not executed |
|
1378 | 1378 | (see 'hg help config.trusted') |
|
1379 | 1379 | [40] |
|
1380 | 1380 | $ hg log |
|
1381 | 1381 | changeset: 0:3903775176ed |
|
1382 | 1382 | tag: tip |
|
1383 | 1383 | user: test |
|
1384 | 1384 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
1385 | 1385 | summary: a |
|
1386 | 1386 | |
|
1387 | 1387 | |
|
1388 | 1388 | unsetup the test |
|
1389 | 1389 | ---------------- |
|
1390 | 1390 | |
|
1391 | 1391 | # touch the file to unconfuse chg with a diffrent mtime |
|
1392 | 1392 | $ sleep 1 |
|
1393 | 1393 | $ touch $TESTTMP/untrusted.py |
|
1394 | 1394 | $ cat << EOF >> $HGRCPATH |
|
1395 | 1395 | > [extensions] |
|
1396 | 1396 | > untrusted=! |
|
1397 | 1397 | > EOF |
|
1398 | 1398 | |
|
1399 | 1399 | HGPLAIN setting in hooks |
|
1400 | 1400 | ======================== |
|
1401 | 1401 | |
|
1402 | 1402 | $ cat << EOF >> .hg/hgrc |
|
1403 | 1403 | > [hooks] |
|
1404 | 1404 | > pre-version.testing-default=sh -c "echo '### default ###' plain: \${HGPLAIN:-'<unset>'}" |
|
1405 | 1405 | > pre-version.testing-yes=sh -c "echo '### yes #######' plain: \${HGPLAIN:-'<unset>'}" |
|
1406 | 1406 | > pre-version.testing-yes:run-with-plain=yes |
|
1407 | 1407 | > pre-version.testing-no=sh -c "echo '### no ########' plain: \${HGPLAIN:-'<unset>'}" |
|
1408 | 1408 | > pre-version.testing-no:run-with-plain=no |
|
1409 | 1409 | > pre-version.testing-auto=sh -c "echo '### auto ######' plain: \${HGPLAIN:-'<unset>'}" |
|
1410 | 1410 | > pre-version.testing-auto:run-with-plain=auto |
|
1411 | 1411 | > EOF |
|
1412 | 1412 | |
|
1413 | 1413 | $ (unset HGPLAIN; hg version --quiet) |
|
1414 | 1414 | ### default ### plain: 1 |
|
1415 | 1415 | ### yes ####### plain: 1 |
|
1416 | 1416 | ### no ######## plain: <unset> |
|
1417 | 1417 | ### auto ###### plain: <unset> |
|
1418 | 1418 | Mercurial Distributed SCM (*) (glob) |
|
1419 | 1419 | |
|
1420 | 1420 | $ HGPLAIN=1 hg version --quiet |
|
1421 | 1421 | ### default ### plain: 1 |
|
1422 | 1422 | ### yes ####### plain: 1 |
|
1423 | 1423 | ### no ######## plain: <unset> |
|
1424 | 1424 | ### auto ###### plain: 1 |
|
1425 | 1425 | Mercurial Distributed SCM (*) (glob) |
|
1426 | 1426 | |
|
1427 | 1427 | Test hook that change the underlying repo |
|
1428 | 1428 | ========================================= |
|
1429 | 1429 | |
|
1430 | 1430 | blackbox access the dirstate afterward and can see a changelog / dirstate |
|
1431 | 1431 | desync. |
|
1432 | 1432 | |
|
1433 | 1433 | |
|
1434 | 1434 | $ cd $TESTTMP |
|
1435 | 1435 | $ cat <<EOF >> $HGRCPATH |
|
1436 | 1436 | > [extensions] |
|
1437 | 1437 | > blackbox= |
|
1438 | 1438 | > [hooks] |
|
1439 | 1439 | > post-merge = hg commit -m "auto merge" |
|
1440 | 1440 | > EOF |
|
1441 | 1441 | |
|
1442 | 1442 | $ hg init t |
|
1443 | 1443 | $ cd t |
|
1444 | 1444 | $ touch ".hgignore" |
|
1445 | 1445 | $ hg commit -Am "initial" -d'0 0' |
|
1446 | 1446 | adding .hgignore |
|
1447 | 1447 | |
|
1448 | 1448 | $ echo This is file a1 > a |
|
1449 | 1449 | $ hg commit -Am "commit #1" -d'0 0' |
|
1450 | 1450 | adding a |
|
1451 | 1451 | |
|
1452 | 1452 | $ hg update 0 |
|
1453 | 1453 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
1454 | 1454 | $ echo This is file b1 > b |
|
1455 | 1455 | $ hg commit -Am "commit #2" -d'0 0' |
|
1456 | 1456 | adding b |
|
1457 | 1457 | created new head |
|
1458 | 1458 | |
|
1459 | 1459 | $ hg merge 1 |
|
1460 | 1460 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
1461 | 1461 | (branch merge, don't forget to commit) |
|
1462 | 1462 | |
|
1463 | 1463 | $ cd .. |
@@ -1,180 +1,180 b'' | |||
|
1 | 1 | #require unix-permissions |
|
2 | 2 | |
|
3 | 3 | test that new files created in .hg inherit the permissions from .hg/store |
|
4 | 4 | |
|
5 | 5 | $ mkdir dir |
|
6 | 6 | |
|
7 | 7 | just in case somebody has a strange $TMPDIR |
|
8 | 8 | |
|
9 | 9 | $ chmod g-s dir |
|
10 | 10 | $ cd dir |
|
11 | 11 | |
|
12 | 12 | $ cat >printmodes.py <<EOF |
|
13 | 13 | > import os |
|
14 | 14 | > import sys |
|
15 | 15 | > |
|
16 | 16 | > allnames = [] |
|
17 | 17 | > isdir = {} |
|
18 | 18 | > for root, dirs, files in os.walk(sys.argv[1]): |
|
19 | 19 | > for d in dirs: |
|
20 | 20 | > name = os.path.join(root, d) |
|
21 | 21 | > isdir[name] = 1 |
|
22 | 22 | > allnames.append(name) |
|
23 | 23 | > for f in files: |
|
24 | 24 | > name = os.path.join(root, f) |
|
25 | 25 | > allnames.append(name) |
|
26 | 26 | > allnames.sort() |
|
27 | 27 | > for name in allnames: |
|
28 | 28 | > suffix = name in isdir and '/' or '' |
|
29 | 29 | > print('%05o %s%s' % (os.lstat(name).st_mode & 0o7777, name, suffix)) |
|
30 | 30 | > EOF |
|
31 | 31 | |
|
32 | 32 | $ cat >mode.py <<EOF |
|
33 | 33 | > import os |
|
34 | 34 | > import sys |
|
35 | 35 | > print('%05o' % os.lstat(sys.argv[1]).st_mode) |
|
36 | 36 | > EOF |
|
37 | 37 | |
|
38 | 38 | $ umask 077 |
|
39 | 39 | |
|
40 | 40 | $ hg init repo |
|
41 | 41 | $ cd repo |
|
42 | 42 | |
|
43 | 43 | $ chmod 0770 .hg/store .hg/cache .hg/wcache |
|
44 | 44 | |
|
45 | 45 | before commit |
|
46 | 46 | store can be written by the group, other files cannot |
|
47 | 47 | store is setgid |
|
48 | 48 | |
|
49 | 49 | $ "$PYTHON" ../printmodes.py . |
|
50 | 50 | 00700 ./.hg/ |
|
51 | 51 | 00600 ./.hg/00changelog.i |
|
52 | 52 | 00770 ./.hg/cache/ |
|
53 | 53 | 00600 ./.hg/requires |
|
54 | 54 | 00770 ./.hg/store/ |
|
55 | 55 | 00600 ./.hg/store/requires |
|
56 | 56 | 00770 ./.hg/wcache/ |
|
57 | 57 | |
|
58 | 58 | $ mkdir dir |
|
59 | 59 | $ touch foo dir/bar |
|
60 | 60 | $ hg ci -qAm 'add files' |
|
61 | 61 | |
|
62 | 62 | after commit |
|
63 | 63 | working dir files can only be written by the owner |
|
64 | 64 | files created in .hg can be written by the group |
|
65 | 65 | (in particular, store/**, dirstate, branch cache file, undo files) |
|
66 | 66 | new directories are setgid |
|
67 | 67 | |
|
68 | 68 | $ "$PYTHON" ../printmodes.py . |
|
69 | 69 | 00700 ./.hg/ |
|
70 | 70 | 00600 ./.hg/00changelog.i |
|
71 | 71 | 00660 ./.hg/branch |
|
72 | 72 | 00770 ./.hg/cache/ |
|
73 | 73 | 00660 ./.hg/cache/branch2-served |
|
74 | 74 | 00660 ./.hg/cache/rbc-names-v1 |
|
75 | 75 | 00660 ./.hg/cache/rbc-revs-v1 |
|
76 | 76 | 00660 ./.hg/dirstate |
|
77 | 77 | 00660 ./.hg/fsmonitor.state (fsmonitor !) |
|
78 | 78 | 00660 ./.hg/last-message.txt |
|
79 | 79 | 00600 ./.hg/requires |
|
80 | 80 | 00770 ./.hg/store/ |
|
81 | 81 | 00660 ./.hg/store/00changelog.i |
|
82 | 82 | 00660 ./.hg/store/00manifest.i |
|
83 | 83 | 00770 ./.hg/store/data/ |
|
84 | 84 | 00770 ./.hg/store/data/dir/ |
|
85 | 85 | 00660 ./.hg/store/data/dir/bar.i (reporevlogstore !) |
|
86 | 86 | 00660 ./.hg/store/data/foo.i (reporevlogstore !) |
|
87 | 87 | 00770 ./.hg/store/data/dir/bar/ (reposimplestore !) |
|
88 | 88 | 00660 ./.hg/store/data/dir/bar/b80de5d138758541c5f05265ad144ab9fa86d1db (reposimplestore !) |
|
89 | 89 | 00660 ./.hg/store/data/dir/bar/index (reposimplestore !) |
|
90 | 90 | 00770 ./.hg/store/data/foo/ (reposimplestore !) |
|
91 | 91 | 00660 ./.hg/store/data/foo/b80de5d138758541c5f05265ad144ab9fa86d1db (reposimplestore !) |
|
92 | 92 | 00660 ./.hg/store/data/foo/index (reposimplestore !) |
|
93 | 93 | 00660 ./.hg/store/fncache (repofncache !) |
|
94 | 94 | 00660 ./.hg/store/phaseroots |
|
95 | 95 | 00600 ./.hg/store/requires |
|
96 | 96 | 00660 ./.hg/store/undo |
|
97 | 97 | 00660 ./.hg/store/undo.backupfiles |
|
98 | 00660 ./.hg/undo.backup.branch | |
|
98 | 00660 ./.hg/undo.backup.branch.bck | |
|
99 | 99 | 00660 ./.hg/undo.desc |
|
100 | 100 | 00770 ./.hg/wcache/ |
|
101 | 101 | 00711 ./.hg/wcache/checkisexec |
|
102 | 102 | 007.. ./.hg/wcache/checklink (re) |
|
103 | 103 | 00600 ./.hg/wcache/checklink-target |
|
104 | 104 | 00660 ./.hg/wcache/manifestfulltextcache (reporevlogstore !) |
|
105 | 105 | 00700 ./dir/ |
|
106 | 106 | 00600 ./dir/bar |
|
107 | 107 | 00600 ./foo |
|
108 | 108 | |
|
109 | 109 | $ umask 007 |
|
110 | 110 | $ hg init ../push |
|
111 | 111 | |
|
112 | 112 | before push |
|
113 | 113 | group can write everything |
|
114 | 114 | |
|
115 | 115 | $ "$PYTHON" ../printmodes.py ../push |
|
116 | 116 | 00770 ../push/.hg/ |
|
117 | 117 | 00660 ../push/.hg/00changelog.i |
|
118 | 118 | 00770 ../push/.hg/cache/ |
|
119 | 119 | 00660 ../push/.hg/requires |
|
120 | 120 | 00770 ../push/.hg/store/ |
|
121 | 121 | 00660 ../push/.hg/store/requires |
|
122 | 122 | 00770 ../push/.hg/wcache/ |
|
123 | 123 | |
|
124 | 124 | $ umask 077 |
|
125 | 125 | $ hg -q push ../push |
|
126 | 126 | |
|
127 | 127 | after push |
|
128 | 128 | group can still write everything |
|
129 | 129 | |
|
130 | 130 | $ "$PYTHON" ../printmodes.py ../push |
|
131 | 131 | 00770 ../push/.hg/ |
|
132 | 132 | 00660 ../push/.hg/00changelog.i |
|
133 | 133 | 00660 ../push/.hg/branch |
|
134 | 134 | 00770 ../push/.hg/cache/ |
|
135 | 135 | 00660 ../push/.hg/cache/branch2-base |
|
136 | 136 | 00660 ../push/.hg/cache/rbc-names-v1 |
|
137 | 137 | 00660 ../push/.hg/cache/rbc-revs-v1 |
|
138 | 138 | 00660 ../push/.hg/requires |
|
139 | 139 | 00770 ../push/.hg/store/ |
|
140 | 140 | 00660 ../push/.hg/store/00changelog.i |
|
141 | 141 | 00660 ../push/.hg/store/00manifest.i |
|
142 | 142 | 00770 ../push/.hg/store/data/ |
|
143 | 143 | 00770 ../push/.hg/store/data/dir/ |
|
144 | 144 | 00660 ../push/.hg/store/data/dir/bar.i (reporevlogstore !) |
|
145 | 145 | 00660 ../push/.hg/store/data/foo.i (reporevlogstore !) |
|
146 | 146 | 00770 ../push/.hg/store/data/dir/bar/ (reposimplestore !) |
|
147 | 147 | 00660 ../push/.hg/store/data/dir/bar/b80de5d138758541c5f05265ad144ab9fa86d1db (reposimplestore !) |
|
148 | 148 | 00660 ../push/.hg/store/data/dir/bar/index (reposimplestore !) |
|
149 | 149 | 00770 ../push/.hg/store/data/foo/ (reposimplestore !) |
|
150 | 150 | 00660 ../push/.hg/store/data/foo/b80de5d138758541c5f05265ad144ab9fa86d1db (reposimplestore !) |
|
151 | 151 | 00660 ../push/.hg/store/data/foo/index (reposimplestore !) |
|
152 | 152 | 00660 ../push/.hg/store/fncache (repofncache !) |
|
153 | 153 | 00660 ../push/.hg/store/requires |
|
154 | 154 | 00660 ../push/.hg/store/undo |
|
155 | 155 | 00660 ../push/.hg/store/undo.backupfiles |
|
156 | 00660 ../push/.hg/undo.backup.branch | |
|
156 | 00660 ../push/.hg/undo.backup.branch.bck | |
|
157 | 157 | 00660 ../push/.hg/undo.desc |
|
158 | 158 | 00770 ../push/.hg/wcache/ |
|
159 | 159 | |
|
160 | 160 | |
|
161 | 161 | Test that we don't lose the setgid bit when we call chmod. |
|
162 | 162 | Not all systems support setgid directories (e.g. HFS+), so |
|
163 | 163 | just check that directories have the same mode. |
|
164 | 164 | |
|
165 | 165 | $ cd .. |
|
166 | 166 | $ hg init setgid |
|
167 | 167 | $ cd setgid |
|
168 | 168 | $ chmod g+rwx .hg/store |
|
169 | 169 | $ chmod g+s .hg/store 2> /dev/null || true |
|
170 | 170 | $ mkdir dir |
|
171 | 171 | $ touch dir/file |
|
172 | 172 | $ hg ci -qAm 'add dir/file' |
|
173 | 173 | $ storemode=`"$PYTHON" ../mode.py .hg/store` |
|
174 | 174 | $ dirmode=`"$PYTHON" ../mode.py .hg/store/data/dir` |
|
175 | 175 | $ if [ "$storemode" != "$dirmode" ]; then |
|
176 | 176 | > echo "$storemode != $dirmode" |
|
177 | 177 | > fi |
|
178 | 178 | $ cd .. |
|
179 | 179 | |
|
180 | 180 | $ cd .. # g-s dir |
@@ -1,263 +1,263 b'' | |||
|
1 | 1 | Create user cache directory |
|
2 | 2 | |
|
3 | 3 | $ USERCACHE=`pwd`/cache; export USERCACHE |
|
4 | 4 | $ cat <<EOF >> ${HGRCPATH} |
|
5 | 5 | > [extensions] |
|
6 | 6 | > hgext.largefiles= |
|
7 | 7 | > [largefiles] |
|
8 | 8 | > usercache=${USERCACHE} |
|
9 | 9 | > EOF |
|
10 | 10 | $ mkdir -p ${USERCACHE} |
|
11 | 11 | |
|
12 | 12 | Create source repo, and commit adding largefile. |
|
13 | 13 | |
|
14 | 14 | $ hg init src |
|
15 | 15 | $ cd src |
|
16 | 16 | $ echo large > large |
|
17 | 17 | $ hg add --large large |
|
18 | 18 | $ hg commit -m 'add largefile' |
|
19 | 19 | $ hg rm large |
|
20 | 20 | $ hg commit -m 'branchhead without largefile' large |
|
21 | 21 | $ hg up -qr 0 |
|
22 | 22 | $ rm large |
|
23 | 23 | $ echo "0000000000000000000000000000000000000000" > .hglf/large |
|
24 | 24 | $ hg commit -m 'commit missing file with corrupt standin' large |
|
25 | 25 | abort: large: file not found! |
|
26 | 26 | [255] |
|
27 | 27 | $ hg up -Cqr 0 |
|
28 | 28 | $ cd .. |
|
29 | 29 | |
|
30 | 30 | Discard all cached largefiles in USERCACHE |
|
31 | 31 | |
|
32 | 32 | $ rm -rf ${USERCACHE} |
|
33 | 33 | |
|
34 | 34 | Create mirror repo, and pull from source without largefile: |
|
35 | 35 | "pull" is used instead of "clone" for suppression of (1) updating to |
|
36 | 36 | tip (= caching largefile from source repo), and (2) recording source |
|
37 | 37 | repo as "default" path in .hg/hgrc. |
|
38 | 38 | |
|
39 | 39 | $ hg init mirror |
|
40 | 40 | $ cd mirror |
|
41 | 41 | $ hg pull ../src |
|
42 | 42 | pulling from ../src |
|
43 | 43 | requesting all changes |
|
44 | 44 | adding changesets |
|
45 | 45 | adding manifests |
|
46 | 46 | adding file changes |
|
47 | 47 | added 2 changesets with 1 changes to 1 files |
|
48 | 48 | new changesets eb85d9124f3f:26c18ce05e4e |
|
49 | 49 | (run 'hg update' to get a working copy) |
|
50 | 50 | |
|
51 | 51 | Update working directory to "tip", which requires largefile("large"), |
|
52 | 52 | but there is no cache file for it. So, hg must treat it as |
|
53 | 53 | "missing"(!) file. |
|
54 | 54 | |
|
55 | 55 | $ hg update -r0 |
|
56 | 56 | getting changed largefiles |
|
57 | 57 | large: largefile 7f7097b041ccf68cc5561e9600da4655d21c6d18 not available from file:/*/$TESTTMP/mirror (glob) |
|
58 | 58 | 0 largefiles updated, 0 removed |
|
59 | 59 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
60 | 60 | $ hg status |
|
61 | 61 | ! large |
|
62 | 62 | |
|
63 | 63 | Update working directory to null: this cleanup .hg/largefiles/dirstate |
|
64 | 64 | |
|
65 | 65 | $ hg update null |
|
66 | 66 | getting changed largefiles |
|
67 | 67 | 0 largefiles updated, 0 removed |
|
68 | 68 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
69 | 69 | |
|
70 | 70 | Update working directory to tip, again. |
|
71 | 71 | |
|
72 | 72 | $ hg update -r0 |
|
73 | 73 | getting changed largefiles |
|
74 | 74 | large: largefile 7f7097b041ccf68cc5561e9600da4655d21c6d18 not available from file:/*/$TESTTMP/mirror (glob) |
|
75 | 75 | 0 largefiles updated, 0 removed |
|
76 | 76 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
77 | 77 | $ hg status |
|
78 | 78 | ! large |
|
79 | 79 | $ cd .. |
|
80 | 80 | |
|
81 | 81 | Verify that largefiles from pulled branchheads are fetched, also to an empty repo |
|
82 | 82 | |
|
83 | 83 | $ hg init mirror2 |
|
84 | 84 | $ hg -R mirror2 pull src -r0 |
|
85 | 85 | pulling from src |
|
86 | 86 | adding changesets |
|
87 | 87 | adding manifests |
|
88 | 88 | adding file changes |
|
89 | 89 | added 1 changesets with 1 changes to 1 files |
|
90 | 90 | new changesets eb85d9124f3f |
|
91 | 91 | (run 'hg update' to get a working copy) |
|
92 | 92 | |
|
93 | 93 | #if unix-permissions |
|
94 | 94 | |
|
95 | 95 | Portable way to print file permissions: |
|
96 | 96 | |
|
97 | 97 | $ cat > ls-l.py <<EOF |
|
98 | 98 | > #!$PYTHON |
|
99 | 99 | > import os |
|
100 | 100 | > import sys |
|
101 | 101 | > path = sys.argv[1] |
|
102 | 102 | > print('%03o' % (os.lstat(path).st_mode & 0o777)) |
|
103 | 103 | > EOF |
|
104 | 104 | $ chmod +x ls-l.py |
|
105 | 105 | |
|
106 | 106 | Test that files in .hg/largefiles inherit mode from .hg/store, not |
|
107 | 107 | from file in working copy: |
|
108 | 108 | |
|
109 | 109 | $ cd src |
|
110 | 110 | $ chmod 750 .hg/store |
|
111 | 111 | $ chmod 660 large |
|
112 | 112 | $ echo change >> large |
|
113 | 113 | $ hg commit -m change |
|
114 | 114 | created new head |
|
115 | 115 | $ ../ls-l.py .hg/largefiles/e151b474069de4ca6898f67ce2f2a7263adf8fea |
|
116 | 116 | 640 |
|
117 | 117 | |
|
118 | 118 | Test permission of with files in .hg/largefiles created by update: |
|
119 | 119 | |
|
120 | 120 | $ cd ../mirror |
|
121 | 121 | $ rm -r "$USERCACHE" .hg/largefiles # avoid links |
|
122 | 122 | $ chmod 750 .hg/store |
|
123 | 123 | $ hg pull ../src --update -q |
|
124 | 124 | $ ../ls-l.py .hg/largefiles/e151b474069de4ca6898f67ce2f2a7263adf8fea |
|
125 | 125 | 640 |
|
126 | 126 | |
|
127 | 127 | Test permission of files created by push: |
|
128 | 128 | |
|
129 | 129 | $ hg serve -R ../src -d -p $HGPORT --pid-file hg.pid \ |
|
130 | 130 | > --config "web.allow_push=*" --config web.push_ssl=no |
|
131 | 131 | $ cat hg.pid >> $DAEMON_PIDS |
|
132 | 132 | |
|
133 | 133 | $ echo change >> large |
|
134 | 134 | $ hg commit -m change |
|
135 | 135 | |
|
136 | 136 | $ rm -r "$USERCACHE" |
|
137 | 137 | |
|
138 | 138 | $ hg push -q http://localhost:$HGPORT/ |
|
139 | 139 | |
|
140 | 140 | $ ../ls-l.py ../src/.hg/largefiles/b734e14a0971e370408ab9bce8d56d8485e368a9 |
|
141 | 141 | 640 |
|
142 | 142 | |
|
143 | 143 | $ cd .. |
|
144 | 144 | |
|
145 | 145 | #endif |
|
146 | 146 | |
|
147 | 147 | Test issue 4053 (remove --after on a deleted, uncommitted file shouldn't say |
|
148 | 148 | it is missing, but a remove on a nonexistent unknown file still should. Same |
|
149 | 149 | for a forget.) |
|
150 | 150 | |
|
151 | 151 | $ cd src |
|
152 | 152 | $ touch x |
|
153 | 153 | $ hg add x |
|
154 | 154 | $ mv x y |
|
155 | 155 | $ hg remove -A x y ENOENT |
|
156 | 156 | ENOENT: * (glob) |
|
157 | 157 | not removing y: file is untracked |
|
158 | 158 | [1] |
|
159 | 159 | $ hg add y |
|
160 | 160 | $ mv y z |
|
161 | 161 | $ hg forget y z ENOENT |
|
162 | 162 | ENOENT: * (glob) |
|
163 | 163 | not removing z: file is already untracked |
|
164 | 164 | [1] |
|
165 | 165 | |
|
166 | 166 | Largefiles are accessible from the share's store |
|
167 | 167 | $ cd .. |
|
168 | 168 | $ hg share -q src share_dst --config extensions.share= |
|
169 | 169 | $ hg -R share_dst update -r0 |
|
170 | 170 | getting changed largefiles |
|
171 | 171 | 1 largefiles updated, 0 removed |
|
172 | 172 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
173 | 173 | |
|
174 | 174 | $ echo modified > share_dst/large |
|
175 | 175 | $ hg -R share_dst ci -m modified |
|
176 | 176 | created new head |
|
177 | 177 | |
|
178 | 178 | Only dirstate is in the local store for the share, and the largefile is in the |
|
179 | 179 | share source's local store. Avoid the extra largefiles added in the unix |
|
180 | 180 | conditional above. |
|
181 | 181 | $ hash=`hg -R share_dst cat share_dst/.hglf/large` |
|
182 | 182 | $ echo $hash |
|
183 | 183 | e2fb5f2139d086ded2cb600d5a91a196e76bf020 |
|
184 | 184 | |
|
185 | 185 | $ find share_dst/.hg/largefiles/* | sort |
|
186 | 186 | share_dst/.hg/largefiles/dirstate |
|
187 | share_dst/.hg/largefiles/undo.backup.dirstate | |
|
187 | share_dst/.hg/largefiles/undo.backup.dirstate.bck | |
|
188 | 188 | |
|
189 | 189 | $ find src/.hg/largefiles/* | egrep "(dirstate|$hash)" | sort |
|
190 | 190 | src/.hg/largefiles/dirstate |
|
191 | 191 | src/.hg/largefiles/e2fb5f2139d086ded2cb600d5a91a196e76bf020 |
|
192 | 192 | |
|
193 | 193 | Verify that backwards compatibility is maintained for old storage layout |
|
194 | 194 | $ mv src/.hg/largefiles/$hash share_dst/.hg/largefiles |
|
195 | 195 | $ hg verify --quiet --lfa -R share_dst --config largefiles.usercache= |
|
196 | 196 | |
|
197 | 197 | Inject corruption into the largefiles store and see how update handles that: |
|
198 | 198 | |
|
199 | 199 | $ cd src |
|
200 | 200 | $ hg up -qC tip |
|
201 | 201 | $ cat large |
|
202 | 202 | modified |
|
203 | 203 | $ rm large |
|
204 | 204 | $ cat .hglf/large |
|
205 | 205 | e2fb5f2139d086ded2cb600d5a91a196e76bf020 |
|
206 | 206 | $ mv .hg/largefiles/e2fb5f2139d086ded2cb600d5a91a196e76bf020 .. |
|
207 | 207 | $ echo corruption > .hg/largefiles/e2fb5f2139d086ded2cb600d5a91a196e76bf020 |
|
208 | 208 | $ hg up -C |
|
209 | 209 | getting changed largefiles |
|
210 | 210 | large: data corruption in $TESTTMP/src/.hg/largefiles/e2fb5f2139d086ded2cb600d5a91a196e76bf020 with hash 6a7bb2556144babe3899b25e5428123735bb1e27 |
|
211 | 211 | 0 largefiles updated, 0 removed |
|
212 | 212 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
213 | 213 | updated to "cd24c147f45c: modified" |
|
214 | 214 | [12] other heads for branch "default" (re) |
|
215 | 215 | $ hg st |
|
216 | 216 | ! large |
|
217 | 217 | ? z |
|
218 | 218 | $ rm .hg/largefiles/e2fb5f2139d086ded2cb600d5a91a196e76bf020 |
|
219 | 219 | |
|
220 | 220 | #if serve |
|
221 | 221 | |
|
222 | 222 | Test coverage of error handling from putlfile: |
|
223 | 223 | |
|
224 | 224 | $ mkdir $TESTTMP/mirrorcache |
|
225 | 225 | $ hg serve -R ../mirror -d -p $HGPORT1 --pid-file hg.pid --config largefiles.usercache=$TESTTMP/mirrorcache |
|
226 | 226 | $ cat hg.pid >> $DAEMON_PIDS |
|
227 | 227 | |
|
228 | 228 | $ hg push http://localhost:$HGPORT1 -f --config files.usercache=nocache |
|
229 | 229 | pushing to http://localhost:$HGPORT1/ |
|
230 | 230 | searching for changes |
|
231 | 231 | abort: remotestore: could not open file $TESTTMP/src/.hg/largefiles/e2fb5f2139d086ded2cb600d5a91a196e76bf020: HTTP Error 403: ssl required |
|
232 | 232 | [255] |
|
233 | 233 | |
|
234 | 234 | $ rm .hg/largefiles/e2fb5f2139d086ded2cb600d5a91a196e76bf020 |
|
235 | 235 | |
|
236 | 236 | Test coverage of 'missing from store': |
|
237 | 237 | |
|
238 | 238 | $ hg serve -R ../mirror -d -p $HGPORT2 --pid-file hg.pid --config largefiles.usercache=$TESTTMP/mirrorcache --config "web.allow_push=*" --config web.push_ssl=no |
|
239 | 239 | $ cat hg.pid >> $DAEMON_PIDS |
|
240 | 240 | |
|
241 | 241 | $ hg push http://localhost:$HGPORT2 -f --config largefiles.usercache=nocache |
|
242 | 242 | pushing to http://localhost:$HGPORT2/ |
|
243 | 243 | searching for changes |
|
244 | 244 | abort: largefile e2fb5f2139d086ded2cb600d5a91a196e76bf020 missing from store (needs to be uploaded) |
|
245 | 245 | [255] |
|
246 | 246 | |
|
247 | 247 | Verify that --lfrev controls which revisions are checked for largefiles to push |
|
248 | 248 | |
|
249 | 249 | $ hg push http://localhost:$HGPORT2 -f --config largefiles.usercache=nocache --lfrev tip |
|
250 | 250 | pushing to http://localhost:$HGPORT2/ |
|
251 | 251 | searching for changes |
|
252 | 252 | abort: largefile e2fb5f2139d086ded2cb600d5a91a196e76bf020 missing from store (needs to be uploaded) |
|
253 | 253 | [255] |
|
254 | 254 | |
|
255 | 255 | $ hg push http://localhost:$HGPORT2 -f --config largefiles.usercache=nocache --lfrev null |
|
256 | 256 | pushing to http://localhost:$HGPORT2/ |
|
257 | 257 | searching for changes |
|
258 | 258 | remote: adding changesets |
|
259 | 259 | remote: adding manifests |
|
260 | 260 | remote: adding file changes |
|
261 | 261 | remote: added 1 changesets with 1 changes to 1 files (+1 heads) |
|
262 | 262 | |
|
263 | 263 | #endif |
@@ -1,1260 +1,1258 b'' | |||
|
1 | 1 | =================================== |
|
2 | 2 | Test the persistent on-disk nodemap |
|
3 | 3 | =================================== |
|
4 | 4 | |
|
5 | 5 | |
|
6 | 6 | $ cat << EOF >> $HGRCPATH |
|
7 | 7 | > [format] |
|
8 | 8 | > use-share-safe=yes |
|
9 | 9 | > [extensions] |
|
10 | 10 | > share= |
|
11 | 11 | > EOF |
|
12 | 12 | |
|
13 | 13 | #if no-rust |
|
14 | 14 | |
|
15 | 15 | $ cat << EOF >> $HGRCPATH |
|
16 | 16 | > [format] |
|
17 | 17 | > use-persistent-nodemap=yes |
|
18 | 18 | > [devel] |
|
19 | 19 | > persistent-nodemap=yes |
|
20 | 20 | > EOF |
|
21 | 21 | |
|
22 | 22 | #endif |
|
23 | 23 | |
|
24 | 24 | $ hg init test-repo --config storage.revlog.persistent-nodemap.slow-path=allow |
|
25 | 25 | $ cd test-repo |
|
26 | 26 | |
|
27 | 27 | Check handling of the default slow-path value |
|
28 | 28 | |
|
29 | 29 | #if no-pure no-rust |
|
30 | 30 | |
|
31 | 31 | $ hg id |
|
32 | 32 | abort: accessing `persistent-nodemap` repository without associated fast implementation. |
|
33 | 33 | (check `hg help config.format.use-persistent-nodemap` for details) |
|
34 | 34 | [255] |
|
35 | 35 | |
|
36 | 36 | Unlock further check (we are here to test the feature) |
|
37 | 37 | |
|
38 | 38 | $ cat << EOF >> $HGRCPATH |
|
39 | 39 | > [storage] |
|
40 | 40 | > # to avoid spamming the test |
|
41 | 41 | > revlog.persistent-nodemap.slow-path=allow |
|
42 | 42 | > EOF |
|
43 | 43 | |
|
44 | 44 | #endif |
|
45 | 45 | |
|
46 | 46 | #if rust |
|
47 | 47 | |
|
48 | 48 | Regression test for a previous bug in Rust/C FFI for the `Revlog_CAPI` capsule: |
|
49 | 49 | in places where `mercurial/cext/revlog.c` function signatures use `Py_ssize_t` |
|
50 | 50 | (64 bits on Linux x86_64), corresponding declarations in `rust/hg-cpython/src/cindex.rs` |
|
51 | 51 | incorrectly used `libc::c_int` (32 bits). |
|
52 | 52 | As a result, -1 passed from Rust for the null revision became 4294967295 in C. |
|
53 | 53 | |
|
54 | 54 | $ hg log -r 00000000 |
|
55 | 55 | changeset: -1:000000000000 |
|
56 | 56 | tag: tip |
|
57 | 57 | user: |
|
58 | 58 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
59 | 59 | |
|
60 | 60 | |
|
61 | 61 | #endif |
|
62 | 62 | |
|
63 | 63 | |
|
64 | 64 | $ hg debugformat |
|
65 | 65 | format-variant repo |
|
66 | 66 | fncache: yes |
|
67 | 67 | dirstate-v2: no |
|
68 | 68 | tracked-hint: no |
|
69 | 69 | dotencode: yes |
|
70 | 70 | generaldelta: yes |
|
71 | 71 | share-safe: yes |
|
72 | 72 | sparserevlog: yes |
|
73 | 73 | persistent-nodemap: yes |
|
74 | 74 | copies-sdc: no |
|
75 | 75 | revlog-v2: no |
|
76 | 76 | changelog-v2: no |
|
77 | 77 | plain-cl-delta: yes |
|
78 | 78 | compression: zlib (no-zstd !) |
|
79 | 79 | compression: zstd (zstd !) |
|
80 | 80 | compression-level: default |
|
81 | 81 | $ hg debugbuilddag .+5000 --new-file |
|
82 | 82 | |
|
83 | 83 | $ hg debugnodemap --metadata |
|
84 | 84 | uid: ???????? (glob) |
|
85 | 85 | tip-rev: 5000 |
|
86 | 86 | tip-node: 6b02b8c7b96654c25e86ba69eda198d7e6ad8b3c |
|
87 | 87 | data-length: 121088 |
|
88 | 88 | data-unused: 0 |
|
89 | 89 | data-unused: 0.000% |
|
90 | 90 | $ f --size .hg/store/00changelog.n |
|
91 | 91 | .hg/store/00changelog.n: size=62 |
|
92 | 92 | |
|
93 | 93 | Simple lookup works |
|
94 | 94 | |
|
95 | 95 | $ ANYNODE=`hg log --template '{node|short}\n' --rev tip` |
|
96 | 96 | $ hg log -r "$ANYNODE" --template '{rev}\n' |
|
97 | 97 | 5000 |
|
98 | 98 | |
|
99 | 99 | |
|
100 | 100 | #if rust |
|
101 | 101 | |
|
102 | 102 | $ f --sha256 .hg/store/00changelog-*.nd |
|
103 | 103 | .hg/store/00changelog-????????.nd: sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd (glob) |
|
104 | 104 | |
|
105 | 105 | $ f --sha256 .hg/store/00manifest-*.nd |
|
106 | 106 | .hg/store/00manifest-????????.nd: sha256=97117b1c064ea2f86664a124589e47db0e254e8d34739b5c5cc5bf31c9da2b51 (glob) |
|
107 | 107 | $ hg debugnodemap --dump-new | f --sha256 --size |
|
108 | 108 | size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd |
|
109 | 109 | $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size |
|
110 | 110 | size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd |
|
111 | 111 | 0000: 00 00 00 91 00 00 00 20 00 00 00 bb 00 00 00 e7 |....... ........| |
|
112 | 112 | 0010: 00 00 00 66 00 00 00 a1 00 00 01 13 00 00 01 22 |...f..........."| |
|
113 | 113 | 0020: 00 00 00 23 00 00 00 fc 00 00 00 ba 00 00 00 5e |...#...........^| |
|
114 | 114 | 0030: 00 00 00 df 00 00 01 4e 00 00 01 65 00 00 00 ab |.......N...e....| |
|
115 | 115 | 0040: 00 00 00 a9 00 00 00 95 00 00 00 73 00 00 00 38 |...........s...8| |
|
116 | 116 | 0050: 00 00 00 cc 00 00 00 92 00 00 00 90 00 00 00 69 |...............i| |
|
117 | 117 | 0060: 00 00 00 ec 00 00 00 8d 00 00 01 4f 00 00 00 12 |...........O....| |
|
118 | 118 | 0070: 00 00 02 0c 00 00 00 77 00 00 00 9c 00 00 00 8f |.......w........| |
|
119 | 119 | 0080: 00 00 00 d5 00 00 00 6b 00 00 00 48 00 00 00 b3 |.......k...H....| |
|
120 | 120 | 0090: 00 00 00 e5 00 00 00 b5 00 00 00 8e 00 00 00 ad |................| |
|
121 | 121 | 00a0: 00 00 00 7b 00 00 00 7c 00 00 00 0b 00 00 00 2b |...{...|.......+| |
|
122 | 122 | 00b0: 00 00 00 c6 00 00 00 1e 00 00 01 08 00 00 00 11 |................| |
|
123 | 123 | 00c0: 00 00 01 30 00 00 00 26 00 00 01 9c 00 00 00 35 |...0...&.......5| |
|
124 | 124 | 00d0: 00 00 00 b8 00 00 01 31 00 00 00 2c 00 00 00 55 |.......1...,...U| |
|
125 | 125 | 00e0: 00 00 00 8a 00 00 00 9a 00 00 00 0c 00 00 01 1e |................| |
|
126 | 126 | 00f0: 00 00 00 a4 00 00 00 83 00 00 00 c9 00 00 00 8c |................| |
|
127 | 127 | |
|
128 | 128 | |
|
129 | 129 | #else |
|
130 | 130 | |
|
131 | 131 | $ f --sha256 .hg/store/00changelog-*.nd |
|
132 | 132 | .hg/store/00changelog-????????.nd: sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 (glob) |
|
133 | 133 | $ hg debugnodemap --dump-new | f --sha256 --size |
|
134 | 134 | size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 |
|
135 | 135 | $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size |
|
136 | 136 | size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 |
|
137 | 137 | 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
138 | 138 | 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
139 | 139 | 0020: ff ff ff ff ff ff f5 06 ff ff ff ff ff ff f3 e7 |................| |
|
140 | 140 | 0030: ff ff ef ca ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
141 | 141 | 0040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
142 | 142 | 0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ed 08 |................| |
|
143 | 143 | 0060: ff ff ed 66 ff ff ff ff ff ff ff ff ff ff ff ff |...f............| |
|
144 | 144 | 0070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
145 | 145 | 0080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
146 | 146 | 0090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f6 ed |................| |
|
147 | 147 | 00a0: ff ff ff ff ff ff fe 61 ff ff ff ff ff ff ff ff |.......a........| |
|
148 | 148 | 00b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
149 | 149 | 00c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
150 | 150 | 00d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| |
|
151 | 151 | 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f1 02 |................| |
|
152 | 152 | 00f0: ff ff ff ff ff ff ed 1b ff ff ff ff ff ff ff ff |................| |
|
153 | 153 | |
|
154 | 154 | #endif |
|
155 | 155 | |
|
156 | 156 | $ hg debugnodemap --check |
|
157 | 157 | revision in index: 5001 |
|
158 | 158 | revision in nodemap: 5001 |
|
159 | 159 | |
|
160 | 160 | add a new commit |
|
161 | 161 | |
|
162 | 162 | $ hg up |
|
163 | 163 | 5001 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
164 | 164 | $ echo foo > foo |
|
165 | 165 | $ hg add foo |
|
166 | 166 | |
|
167 | 167 | |
|
168 | 168 | Check slow-path config value handling |
|
169 | 169 | ------------------------------------- |
|
170 | 170 | |
|
171 | 171 | #if no-pure no-rust |
|
172 | 172 | |
|
173 | 173 | $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value" |
|
174 | 174 | unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value" |
|
175 | 175 | falling back to default value: abort |
|
176 | 176 | abort: accessing `persistent-nodemap` repository without associated fast implementation. |
|
177 | 177 | (check `hg help config.format.use-persistent-nodemap` for details) |
|
178 | 178 | [255] |
|
179 | 179 | |
|
180 | 180 | $ hg log -r . --config "storage.revlog.persistent-nodemap.slow-path=warn" |
|
181 | 181 | warning: accessing `persistent-nodemap` repository without associated fast implementation. |
|
182 | 182 | (check `hg help config.format.use-persistent-nodemap` for details) |
|
183 | 183 | changeset: 5000:6b02b8c7b966 |
|
184 | 184 | tag: tip |
|
185 | 185 | user: debugbuilddag |
|
186 | 186 | date: Thu Jan 01 01:23:20 1970 +0000 |
|
187 | 187 | summary: r5000 |
|
188 | 188 | |
|
189 | 189 | $ hg ci -m 'foo' --config "storage.revlog.persistent-nodemap.slow-path=abort" |
|
190 | 190 | abort: accessing `persistent-nodemap` repository without associated fast implementation. |
|
191 | 191 | (check `hg help config.format.use-persistent-nodemap` for details) |
|
192 | 192 | [255] |
|
193 | 193 | |
|
194 | 194 | #else |
|
195 | 195 | |
|
196 | 196 | $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value" |
|
197 | 197 | unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value" |
|
198 | 198 | falling back to default value: abort |
|
199 | 199 | 6b02b8c7b966+ tip |
|
200 | 200 | |
|
201 | 201 | #endif |
|
202 | 202 | |
|
203 | 203 | $ hg ci -m 'foo' |
|
204 | 204 | |
|
205 | 205 | #if no-pure no-rust |
|
206 | 206 | $ hg debugnodemap --metadata |
|
207 | 207 | uid: ???????? (glob) |
|
208 | 208 | tip-rev: 5001 |
|
209 | 209 | tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c |
|
210 | 210 | data-length: 121088 |
|
211 | 211 | data-unused: 0 |
|
212 | 212 | data-unused: 0.000% |
|
213 | 213 | #else |
|
214 | 214 | $ hg debugnodemap --metadata |
|
215 | 215 | uid: ???????? (glob) |
|
216 | 216 | tip-rev: 5001 |
|
217 | 217 | tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c |
|
218 | 218 | data-length: 121344 |
|
219 | 219 | data-unused: 256 |
|
220 | 220 | data-unused: 0.211% |
|
221 | 221 | #endif |
|
222 | 222 | |
|
223 | 223 | $ f --size .hg/store/00changelog.n |
|
224 | 224 | .hg/store/00changelog.n: size=62 |
|
225 | 225 | |
|
226 | 226 | (The pure code use the debug code that perform incremental update, the C code reencode from scratch) |
|
227 | 227 | |
|
228 | 228 | #if pure |
|
229 | 229 | $ f --sha256 .hg/store/00changelog-*.nd --size |
|
230 | 230 | .hg/store/00changelog-????????.nd: size=121344, sha256=cce54c5da5bde3ad72a4938673ed4064c86231b9c64376b082b163fdb20f8f66 (glob) |
|
231 | 231 | #endif |
|
232 | 232 | |
|
233 | 233 | #if rust |
|
234 | 234 | $ f --sha256 .hg/store/00changelog-*.nd --size |
|
235 | 235 | .hg/store/00changelog-????????.nd: size=121344, sha256=952b042fcf614ceb37b542b1b723e04f18f83efe99bee4e0f5ccd232ef470e58 (glob) |
|
236 | 236 | #endif |
|
237 | 237 | |
|
238 | 238 | #if no-pure no-rust |
|
239 | 239 | $ f --sha256 .hg/store/00changelog-*.nd --size |
|
240 | 240 | .hg/store/00changelog-????????.nd: size=121088, sha256=df7c06a035b96cb28c7287d349d603baef43240be7736fe34eea419a49702e17 (glob) |
|
241 | 241 | #endif |
|
242 | 242 | |
|
243 | 243 | $ hg debugnodemap --check |
|
244 | 244 | revision in index: 5002 |
|
245 | 245 | revision in nodemap: 5002 |
|
246 | 246 | |
|
247 | 247 | Test code path without mmap |
|
248 | 248 | --------------------------- |
|
249 | 249 | |
|
250 | 250 | $ echo bar > bar |
|
251 | 251 | $ hg add bar |
|
252 | 252 | $ hg ci -m 'bar' --config storage.revlog.persistent-nodemap.mmap=no |
|
253 | 253 | |
|
254 | 254 | $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=yes |
|
255 | 255 | revision in index: 5003 |
|
256 | 256 | revision in nodemap: 5003 |
|
257 | 257 | $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=no |
|
258 | 258 | revision in index: 5003 |
|
259 | 259 | revision in nodemap: 5003 |
|
260 | 260 | |
|
261 | 261 | |
|
262 | 262 | #if pure |
|
263 | 263 | $ hg debugnodemap --metadata |
|
264 | 264 | uid: ???????? (glob) |
|
265 | 265 | tip-rev: 5002 |
|
266 | 266 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd |
|
267 | 267 | data-length: 121600 |
|
268 | 268 | data-unused: 512 |
|
269 | 269 | data-unused: 0.421% |
|
270 | 270 | $ f --sha256 .hg/store/00changelog-*.nd --size |
|
271 | 271 | .hg/store/00changelog-????????.nd: size=121600, sha256=def52503d049ccb823974af313a98a935319ba61f40f3aa06a8be4d35c215054 (glob) |
|
272 | 272 | #endif |
|
273 | 273 | #if rust |
|
274 | 274 | $ hg debugnodemap --metadata |
|
275 | 275 | uid: ???????? (glob) |
|
276 | 276 | tip-rev: 5002 |
|
277 | 277 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd |
|
278 | 278 | data-length: 121600 |
|
279 | 279 | data-unused: 512 |
|
280 | 280 | data-unused: 0.421% |
|
281 | 281 | $ f --sha256 .hg/store/00changelog-*.nd --size |
|
282 | 282 | .hg/store/00changelog-????????.nd: size=121600, sha256=dacf5b5f1d4585fee7527d0e67cad5b1ba0930e6a0928f650f779aefb04ce3fb (glob) |
|
283 | 283 | #endif |
|
284 | 284 | #if no-pure no-rust |
|
285 | 285 | $ hg debugnodemap --metadata |
|
286 | 286 | uid: ???????? (glob) |
|
287 | 287 | tip-rev: 5002 |
|
288 | 288 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd |
|
289 | 289 | data-length: 121088 |
|
290 | 290 | data-unused: 0 |
|
291 | 291 | data-unused: 0.000% |
|
292 | 292 | $ f --sha256 .hg/store/00changelog-*.nd --size |
|
293 | 293 | .hg/store/00changelog-????????.nd: size=121088, sha256=59fcede3e3cc587755916ceed29e3c33748cd1aa7d2f91828ac83e7979d935e8 (glob) |
|
294 | 294 | #endif |
|
295 | 295 | |
|
296 | 296 | Test force warming the cache |
|
297 | 297 | |
|
298 | 298 | $ rm .hg/store/00changelog.n |
|
299 | 299 | $ hg debugnodemap --metadata |
|
300 | 300 | $ hg debugupdatecache |
|
301 | 301 | #if pure |
|
302 | 302 | $ hg debugnodemap --metadata |
|
303 | 303 | uid: ???????? (glob) |
|
304 | 304 | tip-rev: 5002 |
|
305 | 305 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd |
|
306 | 306 | data-length: 121088 |
|
307 | 307 | data-unused: 0 |
|
308 | 308 | data-unused: 0.000% |
|
309 | 309 | #else |
|
310 | 310 | $ hg debugnodemap --metadata |
|
311 | 311 | uid: ???????? (glob) |
|
312 | 312 | tip-rev: 5002 |
|
313 | 313 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd |
|
314 | 314 | data-length: 121088 |
|
315 | 315 | data-unused: 0 |
|
316 | 316 | data-unused: 0.000% |
|
317 | 317 | #endif |
|
318 | 318 | |
|
319 | 319 | Check out of sync nodemap |
|
320 | 320 | ========================= |
|
321 | 321 | |
|
322 | 322 | First copy old data on the side. |
|
323 | 323 | |
|
324 | 324 | $ mkdir ../tmp-copies |
|
325 | 325 | $ cp .hg/store/00changelog-????????.nd .hg/store/00changelog.n ../tmp-copies |
|
326 | 326 | |
|
327 | 327 | Nodemap lagging behind |
|
328 | 328 | ---------------------- |
|
329 | 329 | |
|
330 | 330 | make a new commit |
|
331 | 331 | |
|
332 | 332 | $ echo bar2 > bar |
|
333 | 333 | $ hg ci -m 'bar2' |
|
334 | 334 | $ NODE=`hg log -r tip -T '{node}\n'` |
|
335 | 335 | $ hg log -r "$NODE" -T '{rev}\n' |
|
336 | 336 | 5003 |
|
337 | 337 | |
|
338 | 338 | If the nodemap is lagging behind, it can catch up fine |
|
339 | 339 | |
|
340 | 340 | $ hg debugnodemap --metadata |
|
341 | 341 | uid: ???????? (glob) |
|
342 | 342 | tip-rev: 5003 |
|
343 | 343 | tip-node: c9329770f979ade2d16912267c38ba5f82fd37b3 |
|
344 | 344 | data-length: 121344 (pure !) |
|
345 | 345 | data-length: 121344 (rust !) |
|
346 | 346 | data-length: 121152 (no-rust no-pure !) |
|
347 | 347 | data-unused: 192 (pure !) |
|
348 | 348 | data-unused: 192 (rust !) |
|
349 | 349 | data-unused: 0 (no-rust no-pure !) |
|
350 | 350 | data-unused: 0.158% (pure !) |
|
351 | 351 | data-unused: 0.158% (rust !) |
|
352 | 352 | data-unused: 0.000% (no-rust no-pure !) |
|
353 | 353 | $ cp -f ../tmp-copies/* .hg/store/ |
|
354 | 354 | $ hg debugnodemap --metadata |
|
355 | 355 | uid: ???????? (glob) |
|
356 | 356 | tip-rev: 5002 |
|
357 | 357 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd |
|
358 | 358 | data-length: 121088 |
|
359 | 359 | data-unused: 0 |
|
360 | 360 | data-unused: 0.000% |
|
361 | 361 | $ hg log -r "$NODE" -T '{rev}\n' |
|
362 | 362 | 5003 |
|
363 | 363 | |
|
364 | 364 | changelog altered |
|
365 | 365 | ----------------- |
|
366 | 366 | |
|
367 | 367 | If the nodemap is not gated behind a requirements, an unaware client can alter |
|
368 | 368 | the repository so the revlog used to generate the nodemap is not longer |
|
369 | 369 | compatible with the persistent nodemap. We need to detect that. |
|
370 | 370 | |
|
371 | 371 | $ hg up "$NODE~5" |
|
372 | 372 | 0 files updated, 0 files merged, 4 files removed, 0 files unresolved |
|
373 | 373 | $ echo bar > babar |
|
374 | 374 | $ hg add babar |
|
375 | 375 | $ hg ci -m 'babar' |
|
376 | 376 | created new head |
|
377 | 377 | $ OTHERNODE=`hg log -r tip -T '{node}\n'` |
|
378 | 378 | $ hg log -r "$OTHERNODE" -T '{rev}\n' |
|
379 | 379 | 5004 |
|
380 | 380 | |
|
381 | 381 | $ hg --config extensions.strip= strip --rev "$NODE~1" --no-backup |
|
382 | 382 | |
|
383 | 383 | the nodemap should detect the changelog have been tampered with and recover. |
|
384 | 384 | |
|
385 | 385 | $ hg debugnodemap --metadata |
|
386 | 386 | uid: ???????? (glob) |
|
387 | 387 | tip-rev: 5002 |
|
388 | 388 | tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944 |
|
389 | 389 | data-length: 121536 (pure !) |
|
390 | 390 | data-length: 121088 (rust !) |
|
391 | 391 | data-length: 121088 (no-pure no-rust !) |
|
392 | 392 | data-unused: 448 (pure !) |
|
393 | 393 | data-unused: 0 (rust !) |
|
394 | 394 | data-unused: 0 (no-pure no-rust !) |
|
395 | 395 | data-unused: 0.000% (rust !) |
|
396 | 396 | data-unused: 0.369% (pure !) |
|
397 | 397 | data-unused: 0.000% (no-pure no-rust !) |
|
398 | 398 | |
|
399 | 399 | $ cp -f ../tmp-copies/* .hg/store/ |
|
400 | 400 | $ hg debugnodemap --metadata |
|
401 | 401 | uid: ???????? (glob) |
|
402 | 402 | tip-rev: 5002 |
|
403 | 403 | tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd |
|
404 | 404 | data-length: 121088 |
|
405 | 405 | data-unused: 0 |
|
406 | 406 | data-unused: 0.000% |
|
407 | 407 | $ hg log -r "$OTHERNODE" -T '{rev}\n' |
|
408 | 408 | 5002 |
|
409 | 409 | |
|
410 | 410 | missing data file |
|
411 | 411 | ----------------- |
|
412 | 412 | |
|
413 | 413 | $ UUID=`hg debugnodemap --metadata| grep 'uid:' | \ |
|
414 | 414 | > sed 's/uid: //'` |
|
415 | 415 | $ FILE=.hg/store/00changelog-"${UUID}".nd |
|
416 | 416 | $ mv $FILE ../tmp-data-file |
|
417 | 417 | $ cp .hg/store/00changelog.n ../tmp-docket |
|
418 | 418 | |
|
419 | 419 | mercurial don't crash |
|
420 | 420 | |
|
421 | 421 | $ hg log -r . |
|
422 | 422 | changeset: 5002:b355ef8adce0 |
|
423 | 423 | tag: tip |
|
424 | 424 | parent: 4998:d918ad6d18d3 |
|
425 | 425 | user: test |
|
426 | 426 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
427 | 427 | summary: babar |
|
428 | 428 | |
|
429 | 429 | $ hg debugnodemap --metadata |
|
430 | 430 | |
|
431 | 431 | $ hg debugupdatecache |
|
432 | 432 | $ hg debugnodemap --metadata |
|
433 | 433 | uid: * (glob) |
|
434 | 434 | tip-rev: 5002 |
|
435 | 435 | tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944 |
|
436 | 436 | data-length: 121088 |
|
437 | 437 | data-unused: 0 |
|
438 | 438 | data-unused: 0.000% |
|
439 | 439 | $ mv ../tmp-data-file $FILE |
|
440 | 440 | $ mv ../tmp-docket .hg/store/00changelog.n |
|
441 | 441 | |
|
442 | 442 | Check transaction related property |
|
443 | 443 | ================================== |
|
444 | 444 | |
|
445 | 445 | An up to date nodemap should be available to shell hooks, |
|
446 | 446 | |
|
447 | 447 | $ echo dsljfl > a |
|
448 | 448 | $ hg add a |
|
449 | 449 | $ hg ci -m a |
|
450 | 450 | $ hg debugnodemap --metadata |
|
451 | 451 | uid: ???????? (glob) |
|
452 | 452 | tip-rev: 5003 |
|
453 | 453 | tip-node: a52c5079765b5865d97b993b303a18740113bbb2 |
|
454 | 454 | data-length: 121088 |
|
455 | 455 | data-unused: 0 |
|
456 | 456 | data-unused: 0.000% |
|
457 | 457 | $ echo babar2 > babar |
|
458 | 458 | $ hg ci -m 'babar2' --config "hooks.pretxnclose.nodemap-test=hg debugnodemap --metadata" |
|
459 | 459 | uid: ???????? (glob) |
|
460 | 460 | tip-rev: 5004 |
|
461 | 461 | tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984 |
|
462 | 462 | data-length: 121280 (pure !) |
|
463 | 463 | data-length: 121280 (rust !) |
|
464 | 464 | data-length: 121088 (no-pure no-rust !) |
|
465 | 465 | data-unused: 192 (pure !) |
|
466 | 466 | data-unused: 192 (rust !) |
|
467 | 467 | data-unused: 0 (no-pure no-rust !) |
|
468 | 468 | data-unused: 0.158% (pure !) |
|
469 | 469 | data-unused: 0.158% (rust !) |
|
470 | 470 | data-unused: 0.000% (no-pure no-rust !) |
|
471 | 471 | $ hg debugnodemap --metadata |
|
472 | 472 | uid: ???????? (glob) |
|
473 | 473 | tip-rev: 5004 |
|
474 | 474 | tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984 |
|
475 | 475 | data-length: 121280 (pure !) |
|
476 | 476 | data-length: 121280 (rust !) |
|
477 | 477 | data-length: 121088 (no-pure no-rust !) |
|
478 | 478 | data-unused: 192 (pure !) |
|
479 | 479 | data-unused: 192 (rust !) |
|
480 | 480 | data-unused: 0 (no-pure no-rust !) |
|
481 | 481 | data-unused: 0.158% (pure !) |
|
482 | 482 | data-unused: 0.158% (rust !) |
|
483 | 483 | data-unused: 0.000% (no-pure no-rust !) |
|
484 | 484 | |
|
485 | 485 | Another process does not see the pending nodemap content during run. |
|
486 | 486 | |
|
487 | 487 | $ echo qpoasp > a |
|
488 | 488 | $ hg ci -m a2 \ |
|
489 | 489 | > --config "hooks.pretxnclose=sh \"$RUNTESTDIR/testlib/wait-on-file\" 20 sync-repo-read sync-txn-pending" \ |
|
490 | 490 | > --config "hooks.txnclose=touch sync-txn-close" > output.txt 2>&1 & |
|
491 | 491 | |
|
492 | 492 | (read the repository while the commit transaction is pending) |
|
493 | 493 | |
|
494 | 494 | $ sh "$RUNTESTDIR/testlib/wait-on-file" 20 sync-txn-pending && \ |
|
495 | 495 | > hg debugnodemap --metadata && \ |
|
496 | 496 | > sh "$RUNTESTDIR/testlib/wait-on-file" 20 sync-txn-close sync-repo-read |
|
497 | 497 | uid: ???????? (glob) |
|
498 | 498 | tip-rev: 5004 |
|
499 | 499 | tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984 |
|
500 | 500 | data-length: 121280 (pure !) |
|
501 | 501 | data-length: 121280 (rust !) |
|
502 | 502 | data-length: 121088 (no-pure no-rust !) |
|
503 | 503 | data-unused: 192 (pure !) |
|
504 | 504 | data-unused: 192 (rust !) |
|
505 | 505 | data-unused: 0 (no-pure no-rust !) |
|
506 | 506 | data-unused: 0.158% (pure !) |
|
507 | 507 | data-unused: 0.158% (rust !) |
|
508 | 508 | data-unused: 0.000% (no-pure no-rust !) |
|
509 | 509 | $ hg debugnodemap --metadata |
|
510 | 510 | uid: ???????? (glob) |
|
511 | 511 | tip-rev: 5005 |
|
512 | 512 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
513 | 513 | data-length: 121536 (pure !) |
|
514 | 514 | data-length: 121536 (rust !) |
|
515 | 515 | data-length: 121088 (no-pure no-rust !) |
|
516 | 516 | data-unused: 448 (pure !) |
|
517 | 517 | data-unused: 448 (rust !) |
|
518 | 518 | data-unused: 0 (no-pure no-rust !) |
|
519 | 519 | data-unused: 0.369% (pure !) |
|
520 | 520 | data-unused: 0.369% (rust !) |
|
521 | 521 | data-unused: 0.000% (no-pure no-rust !) |
|
522 | 522 | |
|
523 | 523 | $ cat output.txt |
|
524 | 524 | |
|
525 | 525 | Check that a failing transaction will properly revert the data |
|
526 | 526 | |
|
527 | 527 | $ echo plakfe > a |
|
528 | 528 | $ f --size --sha256 .hg/store/00changelog-*.nd |
|
529 | 529 | .hg/store/00changelog-????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !) |
|
530 | 530 | .hg/store/00changelog-????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !) |
|
531 | 531 | .hg/store/00changelog-????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !) |
|
532 | 532 | $ hg ci -m a3 --config "extensions.abort=$RUNTESTDIR/testlib/crash_transaction_late.py" |
|
533 | 533 | transaction abort! |
|
534 | 534 | rollback completed |
|
535 | 535 | abort: This is a late abort |
|
536 | 536 | [255] |
|
537 | 537 | $ hg debugnodemap --metadata |
|
538 | 538 | uid: ???????? (glob) |
|
539 | 539 | tip-rev: 5005 |
|
540 | 540 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
541 | 541 | data-length: 121536 (pure !) |
|
542 | 542 | data-length: 121536 (rust !) |
|
543 | 543 | data-length: 121088 (no-pure no-rust !) |
|
544 | 544 | data-unused: 448 (pure !) |
|
545 | 545 | data-unused: 448 (rust !) |
|
546 | 546 | data-unused: 0 (no-pure no-rust !) |
|
547 | 547 | data-unused: 0.369% (pure !) |
|
548 | 548 | data-unused: 0.369% (rust !) |
|
549 | 549 | data-unused: 0.000% (no-pure no-rust !) |
|
550 | 550 | $ f --size --sha256 .hg/store/00changelog-*.nd |
|
551 | 551 | .hg/store/00changelog-????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !) |
|
552 | 552 | .hg/store/00changelog-????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !) |
|
553 | 553 | .hg/store/00changelog-????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !) |
|
554 | 554 | |
|
555 | 555 | Check that removing content does not confuse the nodemap |
|
556 | 556 | -------------------------------------------------------- |
|
557 | 557 | |
|
558 | 558 | removing data with rollback |
|
559 | 559 | |
|
560 | 560 | $ echo aso > a |
|
561 | 561 | $ hg ci -m a4 |
|
562 | 562 | $ hg rollback |
|
563 | 563 | repository tip rolled back to revision 5005 (undo commit) |
|
564 | 564 | working directory now based on revision 5005 |
|
565 | 565 | $ hg id -r . |
|
566 | 566 | 90d5d3ba2fc4 tip |
|
567 | 567 | |
|
568 | 568 | removing data with strip |
|
569 | 569 | |
|
570 | 570 | $ echo aso > a |
|
571 | 571 | $ hg ci -m a4 |
|
572 | 572 | $ hg --config extensions.strip= strip -r . --no-backup |
|
573 | 573 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
574 | 574 | $ hg id -r . --traceback |
|
575 | 575 | 90d5d3ba2fc4 tip |
|
576 | 576 | |
|
577 | 577 | (be a good citizen and regenerate the nodemap) |
|
578 | 578 | $ hg debugupdatecaches |
|
579 | 579 | $ hg debugnodemap --metadata |
|
580 | 580 | uid: * (glob) |
|
581 | 581 | tip-rev: 5005 |
|
582 | 582 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
583 | 583 | data-length: 121088 |
|
584 | 584 | data-unused: 0 |
|
585 | 585 | data-unused: 0.000% |
|
586 | 586 | |
|
587 | 587 | Check race condition when multiple process write new data to the repository |
|
588 | 588 | --------------------------------------------------------------------------- |
|
589 | 589 | |
|
590 | 590 | In this test, we check that two writers touching the repositories will not |
|
591 | 591 | overwrite each other data. This test is prompted by the existent of issue6554. |
|
592 | 592 | Where a writer ended up using and outdated docket to update the repository. See |
|
593 | 593 | the dedicated extension for details on the race windows and read/write schedule |
|
594 | 594 | necessary to end up in this situation: testlib/persistent-nodemap-race-ext.py |
|
595 | 595 | |
|
596 | 596 | The issue was initially observed on a server with a high push trafic, but it |
|
597 | 597 | can be reproduced using a share and two commiting process which seems simpler. |
|
598 | 598 | |
|
599 | 599 | The test is Rust only as the other implementation does not use the same |
|
600 | 600 | read/write patterns. |
|
601 | 601 | |
|
602 | 602 | $ cd .. |
|
603 | 603 | |
|
604 | 604 | #if rust |
|
605 | 605 | |
|
606 | 606 | $ cp -R test-repo race-repo |
|
607 | 607 | $ hg share race-repo ./other-wc --config format.use-share-safe=yes |
|
608 | 608 | updating working directory |
|
609 | 609 | 5001 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
610 | 610 | $ hg debugformat -R ./race-repo | egrep 'share-safe|persistent-nodemap' |
|
611 | 611 | share-safe: yes |
|
612 | 612 | persistent-nodemap: yes |
|
613 | 613 | $ hg debugformat -R ./other-wc/ | egrep 'share-safe|persistent-nodemap' |
|
614 | 614 | share-safe: yes |
|
615 | 615 | persistent-nodemap: yes |
|
616 | 616 | $ hg -R ./other-wc update 'min(head())' |
|
617 | 617 | 3 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
618 | 618 | $ hg -R ./race-repo debugnodemap --metadata |
|
619 | 619 | uid: 43c37dde |
|
620 | 620 | tip-rev: 5005 |
|
621 | 621 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
622 | 622 | data-length: 121088 |
|
623 | 623 | data-unused: 0 |
|
624 | 624 | data-unused: 0.000% |
|
625 | 625 | $ hg -R ./race-repo log -G -r 'head()' |
|
626 | 626 | @ changeset: 5005:90d5d3ba2fc4 |
|
627 | 627 | | tag: tip |
|
628 | 628 | ~ user: test |
|
629 | 629 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
630 | 630 | summary: a2 |
|
631 | 631 | |
|
632 | 632 | o changeset: 5001:16395c3cf7e2 |
|
633 | 633 | | user: test |
|
634 | 634 | ~ date: Thu Jan 01 00:00:00 1970 +0000 |
|
635 | 635 | summary: foo |
|
636 | 636 | |
|
637 | 637 | $ hg -R ./other-wc log -G -r 'head()' |
|
638 | 638 | o changeset: 5005:90d5d3ba2fc4 |
|
639 | 639 | | tag: tip |
|
640 | 640 | ~ user: test |
|
641 | 641 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
642 | 642 | summary: a2 |
|
643 | 643 | |
|
644 | 644 | @ changeset: 5001:16395c3cf7e2 |
|
645 | 645 | | user: test |
|
646 | 646 | ~ date: Thu Jan 01 00:00:00 1970 +0000 |
|
647 | 647 | summary: foo |
|
648 | 648 | |
|
649 | 649 | $ echo left-side-race > race-repo/left-side-race |
|
650 | 650 | $ hg -R ./race-repo/ add race-repo/left-side-race |
|
651 | 651 | |
|
652 | 652 | $ echo right-side-race > ./other-wc/right-side-race |
|
653 | 653 | $ hg -R ./other-wc/ add ./other-wc/right-side-race |
|
654 | 654 | |
|
655 | 655 | $ mkdir sync-files |
|
656 | 656 | $ mkdir outputs |
|
657 | 657 | $ ( |
|
658 | 658 | > hg -R ./race-repo/ commit -m left-side-commit \ |
|
659 | 659 | > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \ |
|
660 | 660 | > --config 'devel.nodemap-race.role=left'; |
|
661 | 661 | > touch sync-files/left-done |
|
662 | 662 | > ) > outputs/left.txt 2>&1 & |
|
663 | 663 | $ ( |
|
664 | 664 | > hg -R ./other-wc/ commit -m right-side-commit \ |
|
665 | 665 | > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \ |
|
666 | 666 | > --config 'devel.nodemap-race.role=right'; |
|
667 | 667 | > touch sync-files/right-done |
|
668 | 668 | > ) > outputs/right.txt 2>&1 & |
|
669 | 669 | $ ( |
|
670 | 670 | > hg -R ./race-repo/ check-nodemap-race \ |
|
671 | 671 | > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \ |
|
672 | 672 | > --config 'devel.nodemap-race.role=reader'; |
|
673 | 673 | > touch sync-files/reader-done |
|
674 | 674 | > ) > outputs/reader.txt 2>&1 & |
|
675 | 675 | $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/left-done |
|
676 | 676 | $ cat outputs/left.txt |
|
677 | 677 | docket-details: |
|
678 | 678 | uid: 43c37dde |
|
679 | 679 | actual-tip: 5005 |
|
680 | 680 | tip-rev: 5005 |
|
681 | 681 | data-length: 121088 |
|
682 | 682 | nodemap-race: left side locked and ready to commit |
|
683 | 683 | docket-details: |
|
684 | 684 | uid: 43c37dde |
|
685 | 685 | actual-tip: 5005 |
|
686 | 686 | tip-rev: 5005 |
|
687 | 687 | data-length: 121088 |
|
688 | 688 | finalized changelog write |
|
689 | 689 | persisting changelog nodemap |
|
690 | 690 | new data start at 121088 |
|
691 | 691 | persisted changelog nodemap |
|
692 | 692 | docket-details: |
|
693 | 693 | uid: 43c37dde |
|
694 | 694 | actual-tip: 5006 |
|
695 | 695 | tip-rev: 5006 |
|
696 | 696 | data-length: 121280 |
|
697 | 697 | $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/right-done |
|
698 | 698 | $ cat outputs/right.txt |
|
699 | 699 | nodemap-race: right side start of the locking sequence |
|
700 | 700 | nodemap-race: right side reading changelog |
|
701 | 701 | nodemap-race: right side reading of changelog is done |
|
702 | 702 | docket-details: |
|
703 | 703 | uid: 43c37dde |
|
704 | 704 | actual-tip: 5006 |
|
705 | 705 | tip-rev: 5005 |
|
706 | 706 | data-length: 121088 |
|
707 | 707 | nodemap-race: right side ready to wait for the lock |
|
708 | 708 | nodemap-race: right side locked and ready to commit |
|
709 | 709 | docket-details: |
|
710 | 710 | uid: 43c37dde |
|
711 | 711 | actual-tip: 5006 |
|
712 | 712 | tip-rev: 5006 |
|
713 | 713 | data-length: 121280 |
|
714 | 714 | right ready to write, waiting for reader |
|
715 | 715 | right proceeding with writing its changelog index and nodemap |
|
716 | 716 | finalized changelog write |
|
717 | 717 | persisting changelog nodemap |
|
718 | 718 | new data start at 121280 |
|
719 | 719 | persisted changelog nodemap |
|
720 | 720 | docket-details: |
|
721 | 721 | uid: 43c37dde |
|
722 | 722 | actual-tip: 5007 |
|
723 | 723 | tip-rev: 5007 |
|
724 | 724 | data-length: 121536 |
|
725 | 725 | $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/reader-done |
|
726 | 726 | $ cat outputs/reader.txt |
|
727 | 727 | reader: reading changelog |
|
728 | 728 | reader ready to read the changelog, waiting for right |
|
729 | 729 | reader: nodemap docket read |
|
730 | 730 | record-data-length: 121280 |
|
731 | 731 | actual-data-length: 121280 |
|
732 | 732 | file-actual-length: 121536 |
|
733 | 733 | reader: changelog read |
|
734 | 734 | docket-details: |
|
735 | 735 | uid: 43c37dde |
|
736 | 736 | actual-tip: 5006 |
|
737 | 737 | tip-rev: 5006 |
|
738 | 738 | data-length: 121280 |
|
739 | 739 | tip-rev: 5006 |
|
740 | 740 | tip-node: 492901161367 |
|
741 | 741 | node-rev: 5006 |
|
742 | 742 | |
|
743 | 743 | $ hg -R ./race-repo log -G -r 'head()' |
|
744 | 744 | o changeset: 5007:ac4a2abde241 |
|
745 | 745 | | tag: tip |
|
746 | 746 | ~ parent: 5001:16395c3cf7e2 |
|
747 | 747 | user: test |
|
748 | 748 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
749 | 749 | summary: right-side-commit |
|
750 | 750 | |
|
751 | 751 | @ changeset: 5006:492901161367 |
|
752 | 752 | | user: test |
|
753 | 753 | ~ date: Thu Jan 01 00:00:00 1970 +0000 |
|
754 | 754 | summary: left-side-commit |
|
755 | 755 | |
|
756 | 756 | $ hg -R ./other-wc log -G -r 'head()' |
|
757 | 757 | @ changeset: 5007:ac4a2abde241 |
|
758 | 758 | | tag: tip |
|
759 | 759 | ~ parent: 5001:16395c3cf7e2 |
|
760 | 760 | user: test |
|
761 | 761 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
762 | 762 | summary: right-side-commit |
|
763 | 763 | |
|
764 | 764 | o changeset: 5006:492901161367 |
|
765 | 765 | | user: test |
|
766 | 766 | ~ date: Thu Jan 01 00:00:00 1970 +0000 |
|
767 | 767 | summary: left-side-commit |
|
768 | 768 | |
|
769 | 769 | #endif |
|
770 | 770 | |
|
771 | 771 | Test upgrade / downgrade |
|
772 | 772 | ======================== |
|
773 | 773 | |
|
774 | 774 | $ cd ./test-repo/ |
|
775 | 775 | |
|
776 | 776 | downgrading |
|
777 | 777 | |
|
778 | 778 | $ cat << EOF >> .hg/hgrc |
|
779 | 779 | > [format] |
|
780 | 780 | > use-persistent-nodemap=no |
|
781 | 781 | > EOF |
|
782 | 782 | $ hg debugformat -v |
|
783 | 783 | format-variant repo config default |
|
784 | 784 | fncache: yes yes yes |
|
785 | 785 | dirstate-v2: no no no |
|
786 | 786 | tracked-hint: no no no |
|
787 | 787 | dotencode: yes yes yes |
|
788 | 788 | generaldelta: yes yes yes |
|
789 | 789 | share-safe: yes yes yes |
|
790 | 790 | sparserevlog: yes yes yes |
|
791 | 791 | persistent-nodemap: yes no no |
|
792 | 792 | copies-sdc: no no no |
|
793 | 793 | revlog-v2: no no no |
|
794 | 794 | changelog-v2: no no no |
|
795 | 795 | plain-cl-delta: yes yes yes |
|
796 | 796 | compression: zlib zlib zlib (no-zstd !) |
|
797 | 797 | compression: zstd zstd zstd (zstd !) |
|
798 | 798 | compression-level: default default default |
|
799 | 799 | $ hg debugupgraderepo --run --no-backup --quiet |
|
800 | 800 | upgrade will perform the following actions: |
|
801 | 801 | |
|
802 | 802 | requirements |
|
803 | 803 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-zstd no-dirstate-v2 !) |
|
804 | 804 | preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd no-dirstate-v2 !) |
|
805 | 805 | preserved: dotencode, use-dirstate-v2, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !) |
|
806 | 806 | removed: persistent-nodemap |
|
807 | 807 | |
|
808 | 808 | processed revlogs: |
|
809 | 809 | - all-filelogs |
|
810 | 810 | - changelog |
|
811 | 811 | - manifest |
|
812 | 812 | |
|
813 | 813 | $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' |
|
814 | 814 | [1] |
|
815 | 815 | $ hg debugnodemap --metadata |
|
816 | 816 | |
|
817 | 817 | |
|
818 | 818 | upgrading |
|
819 | 819 | |
|
820 | 820 | $ cat << EOF >> .hg/hgrc |
|
821 | 821 | > [format] |
|
822 | 822 | > use-persistent-nodemap=yes |
|
823 | 823 | > EOF |
|
824 | 824 | $ hg debugformat -v |
|
825 | 825 | format-variant repo config default |
|
826 | 826 | fncache: yes yes yes |
|
827 | 827 | dirstate-v2: no no no |
|
828 | 828 | tracked-hint: no no no |
|
829 | 829 | dotencode: yes yes yes |
|
830 | 830 | generaldelta: yes yes yes |
|
831 | 831 | share-safe: yes yes yes |
|
832 | 832 | sparserevlog: yes yes yes |
|
833 | 833 | persistent-nodemap: no yes no |
|
834 | 834 | copies-sdc: no no no |
|
835 | 835 | revlog-v2: no no no |
|
836 | 836 | changelog-v2: no no no |
|
837 | 837 | plain-cl-delta: yes yes yes |
|
838 | 838 | compression: zlib zlib zlib (no-zstd !) |
|
839 | 839 | compression: zstd zstd zstd (zstd !) |
|
840 | 840 | compression-level: default default default |
|
841 | 841 | $ hg debugupgraderepo --run --no-backup --quiet |
|
842 | 842 | upgrade will perform the following actions: |
|
843 | 843 | |
|
844 | 844 | requirements |
|
845 | 845 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-zstd no-dirstate-v2 !) |
|
846 | 846 | preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd no-dirstate-v2 !) |
|
847 | 847 | preserved: dotencode, use-dirstate-v2, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !) |
|
848 | 848 | added: persistent-nodemap |
|
849 | 849 | |
|
850 | 850 | processed revlogs: |
|
851 | 851 | - all-filelogs |
|
852 | 852 | - changelog |
|
853 | 853 | - manifest |
|
854 | 854 | |
|
855 | 855 | $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' |
|
856 | 856 | 00changelog-*.nd (glob) |
|
857 | 857 | 00changelog.n |
|
858 | 858 | 00manifest-*.nd (glob) |
|
859 | 859 | 00manifest.n |
|
860 | 860 | |
|
861 | 861 | $ hg debugnodemap --metadata |
|
862 | 862 | uid: * (glob) |
|
863 | 863 | tip-rev: 5005 |
|
864 | 864 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
865 | 865 | data-length: 121088 |
|
866 | 866 | data-unused: 0 |
|
867 | 867 | data-unused: 0.000% |
|
868 | 868 | |
|
869 | 869 | Running unrelated upgrade |
|
870 | 870 | |
|
871 | 871 | $ hg debugupgraderepo --run --no-backup --quiet --optimize re-delta-all |
|
872 | 872 | upgrade will perform the following actions: |
|
873 | 873 | |
|
874 | 874 | requirements |
|
875 | 875 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (no-zstd no-dirstate-v2 !) |
|
876 | 876 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd no-dirstate-v2 !) |
|
877 | 877 | preserved: dotencode, use-dirstate-v2, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !) |
|
878 | 878 | |
|
879 | 879 | optimisations: re-delta-all |
|
880 | 880 | |
|
881 | 881 | processed revlogs: |
|
882 | 882 | - all-filelogs |
|
883 | 883 | - changelog |
|
884 | 884 | - manifest |
|
885 | 885 | |
|
886 | 886 | $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' |
|
887 | 887 | 00changelog-*.nd (glob) |
|
888 | 888 | 00changelog.n |
|
889 | 889 | 00manifest-*.nd (glob) |
|
890 | 890 | 00manifest.n |
|
891 | 891 | |
|
892 | 892 | $ hg debugnodemap --metadata |
|
893 | 893 | uid: * (glob) |
|
894 | 894 | tip-rev: 5005 |
|
895 | 895 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
896 | 896 | data-length: 121088 |
|
897 | 897 | data-unused: 0 |
|
898 | 898 | data-unused: 0.000% |
|
899 | 899 | |
|
900 | 900 | Persistent nodemap and local/streaming clone |
|
901 | 901 | ============================================ |
|
902 | 902 | |
|
903 | 903 | $ cd .. |
|
904 | 904 | |
|
905 | 905 | standard clone |
|
906 | 906 | -------------- |
|
907 | 907 | |
|
908 | 908 | The persistent nodemap should exist after a streaming clone |
|
909 | 909 | |
|
910 | 910 | $ hg clone --pull --quiet -U test-repo standard-clone |
|
911 | 911 | $ ls -1 standard-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' |
|
912 | 912 | 00changelog-*.nd (glob) |
|
913 | 913 | 00changelog.n |
|
914 | 914 | 00manifest-*.nd (glob) |
|
915 | 915 | 00manifest.n |
|
916 | 916 | $ hg -R standard-clone debugnodemap --metadata |
|
917 | 917 | uid: * (glob) |
|
918 | 918 | tip-rev: 5005 |
|
919 | 919 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
920 | 920 | data-length: 121088 |
|
921 | 921 | data-unused: 0 |
|
922 | 922 | data-unused: 0.000% |
|
923 | 923 | |
|
924 | 924 | |
|
925 | 925 | local clone |
|
926 | 926 | ------------ |
|
927 | 927 | |
|
928 | 928 | The persistent nodemap should exist after a streaming clone |
|
929 | 929 | |
|
930 | 930 | $ hg clone -U test-repo local-clone |
|
931 | 931 | $ ls -1 local-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' |
|
932 | 932 | 00changelog-*.nd (glob) |
|
933 | 933 | 00changelog.n |
|
934 | 934 | 00manifest-*.nd (glob) |
|
935 | 935 | 00manifest.n |
|
936 | 936 | $ hg -R local-clone debugnodemap --metadata |
|
937 | 937 | uid: * (glob) |
|
938 | 938 | tip-rev: 5005 |
|
939 | 939 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
940 | 940 | data-length: 121088 |
|
941 | 941 | data-unused: 0 |
|
942 | 942 | data-unused: 0.000% |
|
943 | 943 | |
|
944 | 944 | Test various corruption case |
|
945 | 945 | ============================ |
|
946 | 946 | |
|
947 | 947 | Missing datafile |
|
948 | 948 | ---------------- |
|
949 | 949 | |
|
950 | 950 | Test behavior with a missing datafile |
|
951 | 951 | |
|
952 | 952 | $ hg clone --quiet --pull test-repo corruption-test-repo |
|
953 | 953 | $ ls -1 corruption-test-repo/.hg/store/00changelog* |
|
954 | 954 | corruption-test-repo/.hg/store/00changelog-*.nd (glob) |
|
955 | 955 | corruption-test-repo/.hg/store/00changelog.d |
|
956 | 956 | corruption-test-repo/.hg/store/00changelog.i |
|
957 | 957 | corruption-test-repo/.hg/store/00changelog.n |
|
958 | 958 | $ rm corruption-test-repo/.hg/store/00changelog*.nd |
|
959 | 959 | $ hg log -R corruption-test-repo -r . |
|
960 | 960 | changeset: 5005:90d5d3ba2fc4 |
|
961 | 961 | tag: tip |
|
962 | 962 | user: test |
|
963 | 963 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
964 | 964 | summary: a2 |
|
965 | 965 | |
|
966 | 966 | $ ls -1 corruption-test-repo/.hg/store/00changelog* |
|
967 | 967 | corruption-test-repo/.hg/store/00changelog.d |
|
968 | 968 | corruption-test-repo/.hg/store/00changelog.i |
|
969 | 969 | corruption-test-repo/.hg/store/00changelog.n |
|
970 | 970 | |
|
971 | 971 | Truncated data file |
|
972 | 972 | ------------------- |
|
973 | 973 | |
|
974 | 974 | Test behavior with a too short datafile |
|
975 | 975 | |
|
976 | 976 | rebuild the missing data |
|
977 | 977 | $ hg -R corruption-test-repo debugupdatecache |
|
978 | 978 | $ ls -1 corruption-test-repo/.hg/store/00changelog* |
|
979 | 979 | corruption-test-repo/.hg/store/00changelog-*.nd (glob) |
|
980 | 980 | corruption-test-repo/.hg/store/00changelog.d |
|
981 | 981 | corruption-test-repo/.hg/store/00changelog.i |
|
982 | 982 | corruption-test-repo/.hg/store/00changelog.n |
|
983 | 983 | |
|
984 | 984 | truncate the file |
|
985 | 985 | |
|
986 | 986 | $ datafilepath=`ls corruption-test-repo/.hg/store/00changelog*.nd` |
|
987 | 987 | $ f -s $datafilepath |
|
988 | 988 | corruption-test-repo/.hg/store/00changelog-*.nd: size=121088 (glob) |
|
989 | 989 | $ dd if=$datafilepath bs=1000 count=10 of=$datafilepath-tmp |
|
990 | 990 | 10+0 records in |
|
991 | 991 | 10+0 records out |
|
992 | 992 | * bytes * (glob) |
|
993 | 993 | $ mv $datafilepath-tmp $datafilepath |
|
994 | 994 | $ f -s $datafilepath |
|
995 | 995 | corruption-test-repo/.hg/store/00changelog-*.nd: size=10000 (glob) |
|
996 | 996 | |
|
997 | 997 | Check that Mercurial reaction to this event |
|
998 | 998 | |
|
999 | 999 | $ hg -R corruption-test-repo log -r . --traceback |
|
1000 | 1000 | changeset: 5005:90d5d3ba2fc4 |
|
1001 | 1001 | tag: tip |
|
1002 | 1002 | user: test |
|
1003 | 1003 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
1004 | 1004 | summary: a2 |
|
1005 | 1005 | |
|
1006 | 1006 | |
|
1007 | 1007 | |
|
1008 | 1008 | stream clone |
|
1009 | 1009 | ============ |
|
1010 | 1010 | |
|
1011 | 1011 | The persistent nodemap should exist after a streaming clone |
|
1012 | 1012 | |
|
1013 | 1013 | Simple case |
|
1014 | 1014 | ----------- |
|
1015 | 1015 | |
|
1016 | 1016 | No race condition |
|
1017 | 1017 | |
|
1018 | 1018 | $ hg clone -U --stream ssh://user@dummy/test-repo stream-clone --debug | egrep '00(changelog|manifest)' |
|
1019 | 1019 | adding [s] 00manifest.n (62 bytes) |
|
1020 | 1020 | adding [s] 00manifest-*.nd (118 KB) (glob) |
|
1021 | 1021 | adding [s] 00changelog.n (62 bytes) |
|
1022 | 1022 | adding [s] 00changelog-*.nd (118 KB) (glob) |
|
1023 | 1023 | adding [s] 00manifest.d (452 KB) (no-zstd !) |
|
1024 | 1024 | adding [s] 00manifest.d (491 KB) (zstd no-bigendian !) |
|
1025 | 1025 | adding [s] 00manifest.d (492 KB) (zstd bigendian !) |
|
1026 | 1026 | adding [s] 00changelog.d (360 KB) (no-zstd !) |
|
1027 | 1027 | adding [s] 00changelog.d (368 KB) (zstd !) |
|
1028 | 1028 | adding [s] 00manifest.i (313 KB) |
|
1029 | 1029 | adding [s] 00changelog.i (313 KB) |
|
1030 | 1030 | $ ls -1 stream-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)' |
|
1031 | 1031 | 00changelog-*.nd (glob) |
|
1032 | 1032 | 00changelog.n |
|
1033 | 1033 | 00manifest-*.nd (glob) |
|
1034 | 1034 | 00manifest.n |
|
1035 | 1035 | $ hg -R stream-clone debugnodemap --metadata |
|
1036 | 1036 | uid: * (glob) |
|
1037 | 1037 | tip-rev: 5005 |
|
1038 | 1038 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
1039 | 1039 | data-length: 121088 |
|
1040 | 1040 | data-unused: 0 |
|
1041 | 1041 | data-unused: 0.000% |
|
1042 | 1042 | |
|
1043 | 1043 | new data appened |
|
1044 | 1044 | ----------------- |
|
1045 | 1045 | |
|
1046 | 1046 | Other commit happening on the server during the stream clone |
|
1047 | 1047 | |
|
1048 | 1048 | setup the step-by-step stream cloning |
|
1049 | 1049 | |
|
1050 | 1050 | $ HG_TEST_STREAM_WALKED_FILE_1="$TESTTMP/sync_file_walked_1" |
|
1051 | 1051 | $ export HG_TEST_STREAM_WALKED_FILE_1 |
|
1052 | 1052 | $ HG_TEST_STREAM_WALKED_FILE_2="$TESTTMP/sync_file_walked_2" |
|
1053 | 1053 | $ export HG_TEST_STREAM_WALKED_FILE_2 |
|
1054 | 1054 | $ HG_TEST_STREAM_WALKED_FILE_3="$TESTTMP/sync_file_walked_3" |
|
1055 | 1055 | $ export HG_TEST_STREAM_WALKED_FILE_3 |
|
1056 | 1056 | $ cat << EOF >> test-repo/.hg/hgrc |
|
1057 | 1057 | > [extensions] |
|
1058 | 1058 | > steps=$RUNTESTDIR/testlib/ext-stream-clone-steps.py |
|
1059 | 1059 | > EOF |
|
1060 | 1060 | |
|
1061 | 1061 | Check and record file state beforehand |
|
1062 | 1062 | |
|
1063 | 1063 | $ f --size test-repo/.hg/store/00changelog* |
|
1064 | 1064 | test-repo/.hg/store/00changelog-*.nd: size=121088 (glob) |
|
1065 | 1065 | test-repo/.hg/store/00changelog.d: size=376891 (zstd no-bigendian !) |
|
1066 | 1066 | test-repo/.hg/store/00changelog.d: size=376889 (zstd bigendian !) |
|
1067 | 1067 | test-repo/.hg/store/00changelog.d: size=368890 (no-zstd !) |
|
1068 | 1068 | test-repo/.hg/store/00changelog.i: size=320384 |
|
1069 | 1069 | test-repo/.hg/store/00changelog.n: size=62 |
|
1070 | 1070 | $ hg -R test-repo debugnodemap --metadata | tee server-metadata.txt |
|
1071 | 1071 | uid: * (glob) |
|
1072 | 1072 | tip-rev: 5005 |
|
1073 | 1073 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
1074 | 1074 | data-length: 121088 |
|
1075 | 1075 | data-unused: 0 |
|
1076 | 1076 | data-unused: 0.000% |
|
1077 | 1077 | |
|
1078 | 1078 | Prepare a commit |
|
1079 | 1079 | |
|
1080 | 1080 | $ echo foo >> test-repo/foo |
|
1081 | 1081 | $ hg -R test-repo/ add test-repo/foo |
|
1082 | 1082 | |
|
1083 | 1083 | Do a mix of clone and commit at the same time so that the file listed on disk differ at actual transfer time. |
|
1084 | 1084 | |
|
1085 | 1085 | $ (hg clone -U --stream ssh://user@dummy/test-repo stream-clone-race-1 --debug 2>> clone-output | egrep '00(changelog|manifest)' >> clone-output; touch $HG_TEST_STREAM_WALKED_FILE_3) & |
|
1086 | 1086 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1 |
|
1087 | 1087 | $ hg -R test-repo/ commit -m foo |
|
1088 | 1088 | $ touch $HG_TEST_STREAM_WALKED_FILE_2 |
|
1089 | 1089 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3 |
|
1090 | 1090 | $ cat clone-output |
|
1091 | 1091 | adding [s] 00manifest.n (62 bytes) |
|
1092 | 1092 | adding [s] 00manifest-*.nd (118 KB) (glob) |
|
1093 | 1093 | adding [s] 00changelog.n (62 bytes) |
|
1094 | 1094 | adding [s] 00changelog-*.nd (118 KB) (glob) |
|
1095 | 1095 | adding [s] 00manifest.d (452 KB) (no-zstd !) |
|
1096 | 1096 | adding [s] 00manifest.d (491 KB) (zstd no-bigendian !) |
|
1097 | 1097 | adding [s] 00manifest.d (492 KB) (zstd bigendian !) |
|
1098 | 1098 | adding [s] 00changelog.d (360 KB) (no-zstd !) |
|
1099 | 1099 | adding [s] 00changelog.d (368 KB) (zstd !) |
|
1100 | 1100 | adding [s] 00manifest.i (313 KB) |
|
1101 | 1101 | adding [s] 00changelog.i (313 KB) |
|
1102 | 1102 | |
|
1103 | 1103 | Check the result state |
|
1104 | 1104 | |
|
1105 | 1105 | $ f --size stream-clone-race-1/.hg/store/00changelog* |
|
1106 | 1106 | stream-clone-race-1/.hg/store/00changelog-*.nd: size=121088 (glob) |
|
1107 | 1107 | stream-clone-race-1/.hg/store/00changelog.d: size=368890 (no-zstd !) |
|
1108 | 1108 | stream-clone-race-1/.hg/store/00changelog.d: size=376891 (zstd no-bigendian !) |
|
1109 | 1109 | stream-clone-race-1/.hg/store/00changelog.d: size=376889 (zstd bigendian !) |
|
1110 | 1110 | stream-clone-race-1/.hg/store/00changelog.i: size=320384 |
|
1111 | 1111 | stream-clone-race-1/.hg/store/00changelog.n: size=62 |
|
1112 | 1112 | |
|
1113 | 1113 | $ hg -R stream-clone-race-1 debugnodemap --metadata | tee client-metadata.txt |
|
1114 | 1114 | uid: * (glob) |
|
1115 | 1115 | tip-rev: 5005 |
|
1116 | 1116 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
1117 | 1117 | data-length: 121088 |
|
1118 | 1118 | data-unused: 0 |
|
1119 | 1119 | data-unused: 0.000% |
|
1120 | 1120 | |
|
1121 | 1121 | We get a usable nodemap, so no rewrite would be needed and the metadata should be identical |
|
1122 | 1122 | (ie: the following diff should be empty) |
|
1123 | 1123 | |
|
1124 | 1124 | This isn't the case for the `no-rust` `no-pure` implementation as it use a very minimal nodemap implementation that unconditionnaly rewrite the nodemap "all the time". |
|
1125 | 1125 | |
|
1126 | 1126 | #if no-rust no-pure |
|
1127 | 1127 | $ diff -u server-metadata.txt client-metadata.txt |
|
1128 | 1128 | --- server-metadata.txt * (glob) |
|
1129 | 1129 | +++ client-metadata.txt * (glob) |
|
1130 | 1130 | @@ -1,4 +1,4 @@ |
|
1131 | 1131 | -uid: * (glob) |
|
1132 | 1132 | +uid: * (glob) |
|
1133 | 1133 | tip-rev: 5005 |
|
1134 | 1134 | tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe |
|
1135 | 1135 | data-length: 121088 |
|
1136 | 1136 | [1] |
|
1137 | 1137 | #else |
|
1138 | 1138 | $ diff -u server-metadata.txt client-metadata.txt |
|
1139 | 1139 | #endif |
|
1140 | 1140 | |
|
1141 | 1141 | |
|
1142 | 1142 | Clean up after the test. |
|
1143 | 1143 | |
|
1144 | 1144 | $ rm -f "$HG_TEST_STREAM_WALKED_FILE_1" |
|
1145 | 1145 | $ rm -f "$HG_TEST_STREAM_WALKED_FILE_2" |
|
1146 | 1146 | $ rm -f "$HG_TEST_STREAM_WALKED_FILE_3" |
|
1147 | 1147 | |
|
1148 | 1148 | full regeneration |
|
1149 | 1149 | ----------------- |
|
1150 | 1150 | |
|
1151 | 1151 | A full nodemap is generated |
|
1152 | 1152 | |
|
1153 | 1153 | (ideally this test would append enough data to make sure the nodemap data file |
|
1154 | 1154 | get changed, however to make thing simpler we will force the regeneration for |
|
1155 | 1155 | this test. |
|
1156 | 1156 | |
|
1157 | 1157 | Check the initial state |
|
1158 | 1158 | |
|
1159 | 1159 | $ f --size test-repo/.hg/store/00changelog* |
|
1160 | 1160 | test-repo/.hg/store/00changelog-*.nd: size=121344 (glob) (rust !) |
|
1161 | 1161 | test-repo/.hg/store/00changelog-*.nd: size=121344 (glob) (pure !) |
|
1162 | 1162 | test-repo/.hg/store/00changelog-*.nd: size=121152 (glob) (no-rust no-pure !) |
|
1163 | 1163 | test-repo/.hg/store/00changelog.d: size=376950 (zstd no-bigendian !) |
|
1164 | 1164 | test-repo/.hg/store/00changelog.d: size=376948 (zstd bigendian !) |
|
1165 | 1165 | test-repo/.hg/store/00changelog.d: size=368949 (no-zstd !) |
|
1166 | 1166 | test-repo/.hg/store/00changelog.i: size=320448 |
|
1167 | 1167 | test-repo/.hg/store/00changelog.n: size=62 |
|
1168 | 1168 | $ hg -R test-repo debugnodemap --metadata | tee server-metadata-2.txt |
|
1169 | 1169 | uid: * (glob) |
|
1170 | 1170 | tip-rev: 5006 |
|
1171 | 1171 | tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b |
|
1172 | 1172 | data-length: 121344 (rust !) |
|
1173 | 1173 | data-length: 121344 (pure !) |
|
1174 | 1174 | data-length: 121152 (no-rust no-pure !) |
|
1175 | 1175 | data-unused: 192 (rust !) |
|
1176 | 1176 | data-unused: 192 (pure !) |
|
1177 | 1177 | data-unused: 0 (no-rust no-pure !) |
|
1178 | 1178 | data-unused: 0.158% (rust !) |
|
1179 | 1179 | data-unused: 0.158% (pure !) |
|
1180 | 1180 | data-unused: 0.000% (no-rust no-pure !) |
|
1181 | 1181 | |
|
1182 | 1182 | Performe the mix of clone and full refresh of the nodemap, so that the files |
|
1183 | 1183 | (and filenames) are different between listing time and actual transfer time. |
|
1184 | 1184 | |
|
1185 | 1185 | $ (hg clone -U --stream ssh://user@dummy/test-repo stream-clone-race-2 --debug 2>> clone-output-2 | egrep '00(changelog|manifest)' >> clone-output-2; touch $HG_TEST_STREAM_WALKED_FILE_3) & |
|
1186 | 1186 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1 |
|
1187 | 1187 | $ rm test-repo/.hg/store/00changelog.n |
|
1188 | 1188 | $ rm test-repo/.hg/store/00changelog-*.nd |
|
1189 | 1189 | $ hg -R test-repo/ debugupdatecache |
|
1190 | 1190 | $ touch $HG_TEST_STREAM_WALKED_FILE_2 |
|
1191 | 1191 | $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3 |
|
1192 | 1192 | |
|
1193 | 1193 | (note: the stream clone code wronly pick the `undo.` files) |
|
1194 | 1194 | |
|
1195 | 1195 | $ cat clone-output-2 |
|
1196 | adding [s] undo.backup.00manifest.n (62 bytes) (known-bad-output !) | |
|
1197 | adding [s] undo.backup.00changelog.n (62 bytes) (known-bad-output !) | |
|
1198 | 1196 | adding [s] 00manifest.n (62 bytes) |
|
1199 | 1197 | adding [s] 00manifest-*.nd (118 KB) (glob) |
|
1200 | 1198 | adding [s] 00changelog.n (62 bytes) |
|
1201 | 1199 | adding [s] 00changelog-*.nd (118 KB) (glob) |
|
1202 | 1200 | adding [s] 00manifest.d (492 KB) (zstd !) |
|
1203 | 1201 | adding [s] 00manifest.d (452 KB) (no-zstd !) |
|
1204 | 1202 | adding [s] 00changelog.d (360 KB) (no-zstd !) |
|
1205 | 1203 | adding [s] 00changelog.d (368 KB) (zstd !) |
|
1206 | 1204 | adding [s] 00manifest.i (313 KB) |
|
1207 | 1205 | adding [s] 00changelog.i (313 KB) |
|
1208 | 1206 | |
|
1209 | 1207 | Check the result. |
|
1210 | 1208 | |
|
1211 | 1209 | $ f --size stream-clone-race-2/.hg/store/00changelog* |
|
1212 | 1210 | stream-clone-race-2/.hg/store/00changelog-*.nd: size=121344 (glob) (rust !) |
|
1213 | 1211 | stream-clone-race-2/.hg/store/00changelog-*.nd: size=121344 (glob) (pure !) |
|
1214 | 1212 | stream-clone-race-2/.hg/store/00changelog-*.nd: size=121152 (glob) (no-rust no-pure !) |
|
1215 | 1213 | stream-clone-race-2/.hg/store/00changelog.d: size=376950 (zstd no-bigendian !) |
|
1216 | 1214 | stream-clone-race-2/.hg/store/00changelog.d: size=376948 (zstd bigendian !) |
|
1217 | 1215 | stream-clone-race-2/.hg/store/00changelog.d: size=368949 (no-zstd !) |
|
1218 | 1216 | stream-clone-race-2/.hg/store/00changelog.i: size=320448 |
|
1219 | 1217 | stream-clone-race-2/.hg/store/00changelog.n: size=62 |
|
1220 | 1218 | |
|
1221 | 1219 | $ hg -R stream-clone-race-2 debugnodemap --metadata | tee client-metadata-2.txt |
|
1222 | 1220 | uid: * (glob) |
|
1223 | 1221 | tip-rev: 5006 |
|
1224 | 1222 | tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b |
|
1225 | 1223 | data-length: 121344 (rust !) |
|
1226 | 1224 | data-unused: 192 (rust !) |
|
1227 | 1225 | data-unused: 0.158% (rust !) |
|
1228 | 1226 | data-length: 121152 (no-rust no-pure !) |
|
1229 | 1227 | data-unused: 0 (no-rust no-pure !) |
|
1230 | 1228 | data-unused: 0.000% (no-rust no-pure !) |
|
1231 | 1229 | data-length: 121344 (pure !) |
|
1232 | 1230 | data-unused: 192 (pure !) |
|
1233 | 1231 | data-unused: 0.158% (pure !) |
|
1234 | 1232 | |
|
1235 | 1233 | We get a usable nodemap, so no rewrite would be needed and the metadata should be identical |
|
1236 | 1234 | (ie: the following diff should be empty) |
|
1237 | 1235 | |
|
1238 | 1236 | This isn't the case for the `no-rust` `no-pure` implementation as it use a very minimal nodemap implementation that unconditionnaly rewrite the nodemap "all the time". |
|
1239 | 1237 | |
|
1240 | 1238 | #if no-rust no-pure |
|
1241 | 1239 | $ diff -u server-metadata-2.txt client-metadata-2.txt |
|
1242 | 1240 | --- server-metadata-2.txt * (glob) |
|
1243 | 1241 | +++ client-metadata-2.txt * (glob) |
|
1244 | 1242 | @@ -1,4 +1,4 @@ |
|
1245 | 1243 | -uid: * (glob) |
|
1246 | 1244 | +uid: * (glob) |
|
1247 | 1245 | tip-rev: 5006 |
|
1248 | 1246 | tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b |
|
1249 | 1247 | data-length: 121152 |
|
1250 | 1248 | [1] |
|
1251 | 1249 | #else |
|
1252 | 1250 | $ diff -u server-metadata-2.txt client-metadata-2.txt |
|
1253 | 1251 | #endif |
|
1254 | 1252 | |
|
1255 | 1253 | Clean up after the test |
|
1256 | 1254 | |
|
1257 | 1255 | $ rm -f $HG_TEST_STREAM_WALKED_FILE_1 |
|
1258 | 1256 | $ rm -f $HG_TEST_STREAM_WALKED_FILE_2 |
|
1259 | 1257 | $ rm -f $HG_TEST_STREAM_WALKED_FILE_3 |
|
1260 | 1258 |
@@ -1,511 +1,510 b'' | |||
|
1 | 1 | #testcases abortcommand abortflag |
|
2 | 2 | #testcases continuecommand continueflag |
|
3 | 3 | |
|
4 | 4 | $ cat >> $HGRCPATH <<EOF |
|
5 | 5 | > [extensions] |
|
6 | 6 | > rebase= |
|
7 | 7 | > |
|
8 | 8 | > [phases] |
|
9 | 9 | > publish=False |
|
10 | 10 | > |
|
11 | 11 | > [alias] |
|
12 | 12 | > tglog = log -G --template "{rev}:{phase} '{desc}' {branches}\n" |
|
13 | 13 | > EOF |
|
14 | 14 | |
|
15 | 15 | #if abortflag |
|
16 | 16 | $ cat >> $HGRCPATH <<EOF |
|
17 | 17 | > [alias] |
|
18 | 18 | > abort = rebase --abort |
|
19 | 19 | > EOF |
|
20 | 20 | #endif |
|
21 | 21 | |
|
22 | 22 | #if continueflag |
|
23 | 23 | $ cat >> $HGRCPATH <<EOF |
|
24 | 24 | > [alias] |
|
25 | 25 | > continue = rebase --continue |
|
26 | 26 | > EOF |
|
27 | 27 | #endif |
|
28 | 28 | |
|
29 | 29 | $ hg init a |
|
30 | 30 | $ cd a |
|
31 | 31 | |
|
32 | 32 | $ touch .hg/rebasestate |
|
33 | 33 | $ hg sum |
|
34 | 34 | parent: -1:000000000000 tip (empty repository) |
|
35 | 35 | branch: default |
|
36 | 36 | commit: (clean) |
|
37 | 37 | update: (current) |
|
38 | 38 | abort: .hg/rebasestate is incomplete |
|
39 | 39 | [255] |
|
40 | 40 | $ rm .hg/rebasestate |
|
41 | 41 | |
|
42 | 42 | $ echo c1 > common |
|
43 | 43 | $ hg add common |
|
44 | 44 | $ hg ci -m C1 |
|
45 | 45 | |
|
46 | 46 | $ echo c2 >> common |
|
47 | 47 | $ hg ci -m C2 |
|
48 | 48 | |
|
49 | 49 | $ echo c3 >> common |
|
50 | 50 | $ hg ci -m C3 |
|
51 | 51 | |
|
52 | 52 | $ hg up -q -C 1 |
|
53 | 53 | |
|
54 | 54 | $ echo l1 >> extra |
|
55 | 55 | $ hg add extra |
|
56 | 56 | $ hg ci -m L1 |
|
57 | 57 | created new head |
|
58 | 58 | |
|
59 | 59 | $ sed -e 's/c2/l2/' common > common.new |
|
60 | 60 | $ mv common.new common |
|
61 | 61 | $ hg ci -m L2 |
|
62 | 62 | |
|
63 | 63 | $ hg phase --force --secret 2 |
|
64 | 64 | |
|
65 | 65 | $ hg tglog |
|
66 | 66 | @ 4:draft 'L2' |
|
67 | 67 | | |
|
68 | 68 | o 3:draft 'L1' |
|
69 | 69 | | |
|
70 | 70 | | o 2:secret 'C3' |
|
71 | 71 | |/ |
|
72 | 72 | o 1:draft 'C2' |
|
73 | 73 | | |
|
74 | 74 | o 0:draft 'C1' |
|
75 | 75 | |
|
76 | 76 | |
|
77 | 77 | Conflicting rebase: |
|
78 | 78 | |
|
79 | 79 | $ hg rebase -s 3 -d 2 |
|
80 | 80 | rebasing 3:3163e20567cc "L1" |
|
81 | 81 | rebasing 4:46f0b057b5c0 tip "L2" |
|
82 | 82 | merging common |
|
83 | 83 | warning: conflicts while merging common! (edit, then use 'hg resolve --mark') |
|
84 | 84 | unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') |
|
85 | 85 | [240] |
|
86 | 86 | |
|
87 | 87 | Insert unsupported advisory merge record: |
|
88 | 88 | |
|
89 | 89 | $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py fakemergerecord -x |
|
90 | 90 | $ hg debugmergestate |
|
91 | 91 | local (dest): 3e046f2ecedb793b97ed32108086edd1a162f8bc |
|
92 | 92 | other (source): 46f0b057b5c061d276b91491c22151f78698abd2 |
|
93 | 93 | file: common (state "u") |
|
94 | 94 | local path: common (hash 94c8c21d08740f5da9eaa38d1f175c592692f0d1, flags "") |
|
95 | 95 | ancestor path: common (node de0a666fdd9c1a0b0698b90d85064d8bd34f74b6) |
|
96 | 96 | other path: common (node 2f6411de53677f6f1048fef5bf888d67a342e0a5) |
|
97 | 97 | extra: ancestorlinknode = 3163e20567cc93074fbb7a53c8b93312e59dbf2c |
|
98 | 98 | extra: merged = yes |
|
99 | 99 | $ hg resolve -l |
|
100 | 100 | U common |
|
101 | 101 | |
|
102 | 102 | Insert unsupported mandatory merge record: |
|
103 | 103 | |
|
104 | 104 | $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py fakemergerecord -X |
|
105 | 105 | $ hg debugmergestate |
|
106 | 106 | abort: unsupported merge state records: X |
|
107 | 107 | (see https://mercurial-scm.org/wiki/MergeStateRecords for more information) |
|
108 | 108 | [255] |
|
109 | 109 | $ hg resolve -l |
|
110 | 110 | abort: unsupported merge state records: X |
|
111 | 111 | (see https://mercurial-scm.org/wiki/MergeStateRecords for more information) |
|
112 | 112 | [255] |
|
113 | 113 | $ hg resolve -ma |
|
114 | 114 | abort: unsupported merge state records: X |
|
115 | 115 | (see https://mercurial-scm.org/wiki/MergeStateRecords for more information) |
|
116 | 116 | [255] |
|
117 | 117 | |
|
118 | 118 | Abort (should clear out unsupported merge state): |
|
119 | 119 | |
|
120 | 120 | #if abortcommand |
|
121 | 121 | when in dry-run mode |
|
122 | 122 | $ hg abort --dry-run |
|
123 | 123 | rebase in progress, will be aborted |
|
124 | 124 | #endif |
|
125 | 125 | |
|
126 | 126 | $ hg abort |
|
127 | 127 | saved backup bundle to $TESTTMP/a/.hg/strip-backup/3e046f2ecedb-6beef7d5-backup.hg |
|
128 | 128 | rebase aborted |
|
129 | 129 | $ hg debugmergestate |
|
130 | 130 | no merge state found |
|
131 | 131 | |
|
132 | 132 | $ hg tglog |
|
133 | 133 | @ 4:draft 'L2' |
|
134 | 134 | | |
|
135 | 135 | o 3:draft 'L1' |
|
136 | 136 | | |
|
137 | 137 | | o 2:secret 'C3' |
|
138 | 138 | |/ |
|
139 | 139 | o 1:draft 'C2' |
|
140 | 140 | | |
|
141 | 141 | o 0:draft 'C1' |
|
142 | 142 | |
|
143 | 143 | Test safety for inconsistent rebase state, which may be created (and |
|
144 | 144 | forgotten) by Mercurial earlier than 2.7. This emulates Mercurial |
|
145 | 145 | earlier than 2.7 by renaming ".hg/rebasestate" temporarily. |
|
146 | 146 | |
|
147 | 147 | $ hg rebase -s 3 -d 2 |
|
148 | 148 | rebasing 3:3163e20567cc "L1" |
|
149 | 149 | rebasing 4:46f0b057b5c0 tip "L2" |
|
150 | 150 | merging common |
|
151 | 151 | warning: conflicts while merging common! (edit, then use 'hg resolve --mark') |
|
152 | 152 | unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') |
|
153 | 153 | [240] |
|
154 | 154 | |
|
155 | 155 | $ mv .hg/rebasestate .hg/rebasestate.back |
|
156 | 156 | $ hg update --quiet --clean 2 |
|
157 | 157 | $ hg --config extensions.mq= strip --quiet "destination()" |
|
158 | 158 | $ mv .hg/rebasestate.back .hg/rebasestate |
|
159 | 159 | |
|
160 | 160 | $ hg continue |
|
161 | 161 | abort: cannot continue inconsistent rebase |
|
162 | 162 | (use "hg rebase --abort" to clear broken state) |
|
163 | 163 | [255] |
|
164 | 164 | $ hg summary | grep '^rebase: ' |
|
165 | 165 | rebase: (use "hg rebase --abort" to clear broken state) |
|
166 | 166 | $ hg abort |
|
167 | 167 | rebase aborted (no revision is removed, only broken state is cleared) |
|
168 | 168 | |
|
169 | 169 | $ cd .. |
|
170 | 170 | |
|
171 | 171 | |
|
172 | 172 | Construct new repo: |
|
173 | 173 | |
|
174 | 174 | $ hg init b |
|
175 | 175 | $ cd b |
|
176 | 176 | |
|
177 | 177 | $ echo a > a |
|
178 | 178 | $ hg ci -Am A |
|
179 | 179 | adding a |
|
180 | 180 | |
|
181 | 181 | $ echo b > b |
|
182 | 182 | $ hg ci -Am B |
|
183 | 183 | adding b |
|
184 | 184 | |
|
185 | 185 | $ echo c > c |
|
186 | 186 | $ hg ci -Am C |
|
187 | 187 | adding c |
|
188 | 188 | |
|
189 | 189 | $ hg up -q 0 |
|
190 | 190 | |
|
191 | 191 | $ echo b > b |
|
192 | 192 | $ hg ci -Am 'B bis' |
|
193 | 193 | adding b |
|
194 | 194 | created new head |
|
195 | 195 | |
|
196 | 196 | $ echo c1 > c |
|
197 | 197 | $ hg ci -Am C1 |
|
198 | 198 | adding c |
|
199 | 199 | |
|
200 | 200 | $ hg phase --force --secret 1 |
|
201 | 201 | $ hg phase --public 1 |
|
202 | 202 | |
|
203 | 203 | Rebase and abort without generating new changesets: |
|
204 | 204 | |
|
205 | 205 | $ hg tglog |
|
206 | 206 | @ 4:draft 'C1' |
|
207 | 207 | | |
|
208 | 208 | o 3:draft 'B bis' |
|
209 | 209 | | |
|
210 | 210 | | o 2:secret 'C' |
|
211 | 211 | | | |
|
212 | 212 | | o 1:public 'B' |
|
213 | 213 | |/ |
|
214 | 214 | o 0:public 'A' |
|
215 | 215 | |
|
216 | 216 | $ hg rebase -b 4 -d 2 |
|
217 | 217 | rebasing 3:a6484957d6b9 "B bis" |
|
218 | 218 | note: not rebasing 3:a6484957d6b9 "B bis", its destination already has all its changes |
|
219 | 219 | rebasing 4:145842775fec tip "C1" |
|
220 | 220 | merging c |
|
221 | 221 | warning: conflicts while merging c! (edit, then use 'hg resolve --mark') |
|
222 | 222 | unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') |
|
223 | 223 | [240] |
|
224 | 224 | |
|
225 | 225 | $ hg tglog |
|
226 | 226 | % 4:draft 'C1' |
|
227 | 227 | | |
|
228 | 228 | o 3:draft 'B bis' |
|
229 | 229 | | |
|
230 | 230 | | @ 2:secret 'C' |
|
231 | 231 | | | |
|
232 | 232 | | o 1:public 'B' |
|
233 | 233 | |/ |
|
234 | 234 | o 0:public 'A' |
|
235 | 235 | |
|
236 | 236 | $ hg rebase -a |
|
237 | 237 | rebase aborted |
|
238 | 238 | |
|
239 | 239 | $ hg tglog |
|
240 | 240 | @ 4:draft 'C1' |
|
241 | 241 | | |
|
242 | 242 | o 3:draft 'B bis' |
|
243 | 243 | | |
|
244 | 244 | | o 2:secret 'C' |
|
245 | 245 | | | |
|
246 | 246 | | o 1:public 'B' |
|
247 | 247 | |/ |
|
248 | 248 | o 0:public 'A' |
|
249 | 249 | |
|
250 | 250 | |
|
251 | 251 | $ cd .. |
|
252 | 252 | |
|
253 | 253 | rebase abort should not leave working copy in a merge state if tip-1 is public |
|
254 | 254 | (issue4082) |
|
255 | 255 | |
|
256 | 256 | $ hg init abortpublic |
|
257 | 257 | $ cd abortpublic |
|
258 | 258 | $ echo a > a && hg ci -Aqm a |
|
259 | 259 | $ hg book master |
|
260 | 260 | $ hg book foo |
|
261 | 261 | $ echo b > b && hg ci -Aqm b |
|
262 | 262 | $ hg up -q master |
|
263 | 263 | $ echo c > c && hg ci -Aqm c |
|
264 | 264 | $ hg phase -p -r . |
|
265 | 265 | $ hg up -q foo |
|
266 | 266 | $ echo C > c && hg ci -Aqm C |
|
267 | 267 | $ hg log -G --template "{rev} {desc} {bookmarks}" |
|
268 | 268 | @ 3 C foo |
|
269 | 269 | | |
|
270 | 270 | | o 2 c master |
|
271 | 271 | | | |
|
272 | 272 | o | 1 b |
|
273 | 273 | |/ |
|
274 | 274 | o 0 a |
|
275 | 275 | |
|
276 | 276 | |
|
277 | 277 | $ hg rebase -d master -r foo |
|
278 | 278 | rebasing 3:6c0f977a22d8 foo tip "C" |
|
279 | 279 | merging c |
|
280 | 280 | warning: conflicts while merging c! (edit, then use 'hg resolve --mark') |
|
281 | 281 | unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') |
|
282 | 282 | [240] |
|
283 | 283 | $ hg abort |
|
284 | 284 | rebase aborted |
|
285 | 285 | $ hg log -G --template "{rev} {desc} {bookmarks}" |
|
286 | 286 | @ 3 C foo |
|
287 | 287 | | |
|
288 | 288 | | o 2 c master |
|
289 | 289 | | | |
|
290 | 290 | o | 1 b |
|
291 | 291 | |/ |
|
292 | 292 | o 0 a |
|
293 | 293 | |
|
294 | 294 | $ cd .. |
|
295 | 295 | |
|
296 | 296 | Make sure we don't clobber changes in the working directory when the |
|
297 | 297 | user has somehow managed to update to a different revision (issue4009) |
|
298 | 298 | |
|
299 | 299 | $ hg init noupdate |
|
300 | 300 | $ cd noupdate |
|
301 | 301 | $ hg book @ |
|
302 | 302 | $ echo original > a |
|
303 | 303 | $ hg add a |
|
304 | 304 | $ hg commit -m a |
|
305 | 305 | $ echo x > b |
|
306 | 306 | $ hg add b |
|
307 | 307 | $ hg commit -m b1 |
|
308 | 308 | $ hg up 0 |
|
309 | 309 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
310 | 310 | (leaving bookmark @) |
|
311 | 311 | $ hg book foo |
|
312 | 312 | $ echo y > b |
|
313 | 313 | $ hg add b |
|
314 | 314 | $ hg commit -m b2 |
|
315 | 315 | created new head |
|
316 | 316 | |
|
317 | 317 | $ hg rebase -d @ -b foo --tool=internal:fail |
|
318 | 318 | rebasing 2:070cf4580bb5 foo tip "b2" |
|
319 | 319 | unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') |
|
320 | 320 | [240] |
|
321 | 321 | |
|
322 | 322 | $ mv .hg/rebasestate ./ # so we're allowed to hg up like in mercurial <2.6.3 |
|
323 | 323 | $ hg up -C 0 # user does other stuff in the repo |
|
324 | 324 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
325 | 325 | |
|
326 | 326 | $ mv rebasestate .hg/ # user upgrades to 2.7 |
|
327 | 327 | |
|
328 | 328 | $ echo new > a |
|
329 | 329 | $ hg up 1 # user gets an error saying to run hg rebase --abort |
|
330 | 330 | abort: rebase in progress |
|
331 | 331 | (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop') |
|
332 | 332 | [20] |
|
333 | 333 | |
|
334 | 334 | $ cat a |
|
335 | 335 | new |
|
336 | 336 | $ hg abort |
|
337 | 337 | rebase aborted |
|
338 | 338 | $ cat a |
|
339 | 339 | new |
|
340 | 340 | |
|
341 | 341 | $ cd .. |
|
342 | 342 | |
|
343 | 343 | test aborting an interrupted series (issue5084) |
|
344 | 344 | $ hg init interrupted |
|
345 | 345 | $ cd interrupted |
|
346 | 346 | $ touch base |
|
347 | 347 | $ hg add base |
|
348 | 348 | $ hg commit -m base |
|
349 | 349 | $ touch a |
|
350 | 350 | $ hg add a |
|
351 | 351 | $ hg commit -m a |
|
352 | 352 | $ echo 1 > a |
|
353 | 353 | $ hg commit -m 1 |
|
354 | 354 | $ touch b |
|
355 | 355 | $ hg add b |
|
356 | 356 | $ hg commit -m b |
|
357 | 357 | $ echo 2 >> a |
|
358 | 358 | $ hg commit -m c |
|
359 | 359 | $ touch d |
|
360 | 360 | $ hg add d |
|
361 | 361 | $ hg commit -m d |
|
362 | 362 | $ hg co -q 1 |
|
363 | 363 | $ hg rm a |
|
364 | 364 | $ hg commit -m no-a |
|
365 | 365 | created new head |
|
366 | 366 | $ hg co 0 |
|
367 | 367 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
368 | 368 | $ hg log -G --template "{rev} {desc} {bookmarks}" |
|
369 | 369 | o 6 no-a |
|
370 | 370 | | |
|
371 | 371 | | o 5 d |
|
372 | 372 | | | |
|
373 | 373 | | o 4 c |
|
374 | 374 | | | |
|
375 | 375 | | o 3 b |
|
376 | 376 | | | |
|
377 | 377 | | o 2 1 |
|
378 | 378 | |/ |
|
379 | 379 | o 1 a |
|
380 | 380 | | |
|
381 | 381 | @ 0 base |
|
382 | 382 | |
|
383 | 383 | $ hg --config extensions.n=$TESTDIR/failfilemerge.py rebase -s 3 -d tip |
|
384 | 384 | rebasing 3:3a71550954f1 "b" |
|
385 | 385 | rebasing 4:e80b69427d80 "c" |
|
386 | 386 | abort: ^C |
|
387 | 387 | [255] |
|
388 | 388 | |
|
389 | 389 | New operations are blocked with the correct state message |
|
390 | 390 | |
|
391 | 391 | $ find .hg -name '*state' -prune | sort |
|
392 | 392 | .hg/dirstate |
|
393 | 393 | .hg/merge/state |
|
394 | 394 | .hg/rebasestate |
|
395 | .hg/undo.backup.dirstate | |
|
396 | 395 | .hg/updatestate |
|
397 | 396 | |
|
398 | 397 | $ hg rebase -s 3 -d tip |
|
399 | 398 | abort: rebase in progress |
|
400 | 399 | (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop') |
|
401 | 400 | [20] |
|
402 | 401 | $ hg up . |
|
403 | 402 | abort: rebase in progress |
|
404 | 403 | (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop') |
|
405 | 404 | [20] |
|
406 | 405 | $ hg up -C . |
|
407 | 406 | abort: rebase in progress |
|
408 | 407 | (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop') |
|
409 | 408 | [20] |
|
410 | 409 | |
|
411 | 410 | $ hg graft 3 |
|
412 | 411 | abort: rebase in progress |
|
413 | 412 | (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop') |
|
414 | 413 | [20] |
|
415 | 414 | |
|
416 | 415 | $ hg abort |
|
417 | 416 | saved backup bundle to $TESTTMP/interrupted/.hg/strip-backup/3d8812cf300d-93041a90-backup.hg |
|
418 | 417 | rebase aborted |
|
419 | 418 | $ hg log -G --template "{rev} {desc} {bookmarks}" |
|
420 | 419 | o 6 no-a |
|
421 | 420 | | |
|
422 | 421 | | o 5 d |
|
423 | 422 | | | |
|
424 | 423 | | o 4 c |
|
425 | 424 | | | |
|
426 | 425 | | o 3 b |
|
427 | 426 | | | |
|
428 | 427 | | o 2 1 |
|
429 | 428 | |/ |
|
430 | 429 | o 1 a |
|
431 | 430 | | |
|
432 | 431 | @ 0 base |
|
433 | 432 | |
|
434 | 433 | $ hg summary |
|
435 | 434 | parent: 0:df4f53cec30a |
|
436 | 435 | base |
|
437 | 436 | branch: default |
|
438 | 437 | commit: (clean) |
|
439 | 438 | update: 6 new changesets (update) |
|
440 | 439 | phases: 7 draft |
|
441 | 440 | |
|
442 | 441 | $ cd .. |
|
443 | 442 | On the other hand, make sure we *do* clobber changes whenever we |
|
444 | 443 | haven't somehow managed to update the repo to a different revision |
|
445 | 444 | during a rebase (issue4661) |
|
446 | 445 | |
|
447 | 446 | $ hg ini yesupdate |
|
448 | 447 | $ cd yesupdate |
|
449 | 448 | $ echo "initial data" > foo.txt |
|
450 | 449 | $ hg add |
|
451 | 450 | adding foo.txt |
|
452 | 451 | $ hg ci -m "initial checkin" |
|
453 | 452 | $ echo "change 1" > foo.txt |
|
454 | 453 | $ hg ci -m "change 1" |
|
455 | 454 | $ hg up 0 |
|
456 | 455 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
457 | 456 | $ echo "conflicting change 1" > foo.txt |
|
458 | 457 | $ hg ci -m "conflicting 1" |
|
459 | 458 | created new head |
|
460 | 459 | $ echo "conflicting change 2" > foo.txt |
|
461 | 460 | $ hg ci -m "conflicting 2" |
|
462 | 461 | |
|
463 | 462 | $ hg rebase -d 1 --tool 'internal:fail' |
|
464 | 463 | rebasing 2:e4ea5cdc9789 "conflicting 1" |
|
465 | 464 | unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') |
|
466 | 465 | [240] |
|
467 | 466 | $ hg abort |
|
468 | 467 | rebase aborted |
|
469 | 468 | $ hg summary |
|
470 | 469 | parent: 3:b16646383533 tip |
|
471 | 470 | conflicting 2 |
|
472 | 471 | branch: default |
|
473 | 472 | commit: (clean) |
|
474 | 473 | update: 1 new changesets, 2 branch heads (merge) |
|
475 | 474 | phases: 4 draft |
|
476 | 475 | $ cd .. |
|
477 | 476 | |
|
478 | 477 | test aborting a rebase succeeds after rebasing with skipped commits onto a |
|
479 | 478 | public changeset (issue4896) |
|
480 | 479 | |
|
481 | 480 | $ hg init succeedonpublic |
|
482 | 481 | $ cd succeedonpublic |
|
483 | 482 | $ echo 'content' > root |
|
484 | 483 | $ hg commit -A -m 'root' -q |
|
485 | 484 | |
|
486 | 485 | set up public branch |
|
487 | 486 | $ echo 'content' > disappear |
|
488 | 487 | $ hg commit -A -m 'disappear public' -q |
|
489 | 488 | commit will cause merge conflict on rebase |
|
490 | 489 | $ echo '' > root |
|
491 | 490 | $ hg commit -m 'remove content public' -q |
|
492 | 491 | $ hg phase --public |
|
493 | 492 | |
|
494 | 493 | setup the draft branch that will be rebased onto public commit |
|
495 | 494 | $ hg up -r 0 -q |
|
496 | 495 | $ echo 'content' > disappear |
|
497 | 496 | commit will disappear |
|
498 | 497 | $ hg commit -A -m 'disappear draft' -q |
|
499 | 498 | $ echo 'addedcontADDEDentadded' > root |
|
500 | 499 | commit will cause merge conflict on rebase |
|
501 | 500 | $ hg commit -m 'add content draft' -q |
|
502 | 501 | |
|
503 | 502 | $ hg rebase -d 'public()' --tool :merge -q |
|
504 | 503 | note: not rebasing 3:0682fd3dabf5 "disappear draft", its destination already has all its changes |
|
505 | 504 | warning: conflicts while merging root! (edit, then use 'hg resolve --mark') |
|
506 | 505 | unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') |
|
507 | 506 | [240] |
|
508 | 507 | $ hg abort |
|
509 | 508 | rebase aborted |
|
510 | 509 | $ cd .. |
|
511 | 510 |
@@ -1,457 +1,457 b'' | |||
|
1 | 1 | setup repo |
|
2 | 2 | $ hg init t |
|
3 | 3 | $ cd t |
|
4 | 4 | $ echo a > a |
|
5 | 5 | $ hg add a |
|
6 | 6 | $ hg commit -m 'add a' |
|
7 | 7 | $ hg verify -q |
|
8 | 8 | $ hg parents |
|
9 | 9 | changeset: 0:1f0dee641bb7 |
|
10 | 10 | tag: tip |
|
11 | 11 | user: test |
|
12 | 12 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
13 | 13 | summary: add a |
|
14 | 14 | |
|
15 | 15 | |
|
16 | 16 | rollback to null revision |
|
17 | 17 | $ hg status |
|
18 | 18 | $ hg rollback |
|
19 | 19 | repository tip rolled back to revision -1 (undo commit) |
|
20 | 20 | working directory now based on revision -1 |
|
21 | 21 | $ hg verify -q |
|
22 | 22 | $ hg parents |
|
23 | 23 | $ hg status |
|
24 | 24 | A a |
|
25 | 25 | |
|
26 | 26 | Two changesets this time so we rollback to a real changeset |
|
27 | 27 | $ hg commit -m'add a again' |
|
28 | 28 | $ echo a >> a |
|
29 | 29 | $ hg commit -m'modify a' |
|
30 | 30 | |
|
31 | 31 | Test issue 902 (current branch is preserved) |
|
32 | 32 | $ hg branch test |
|
33 | 33 | marked working directory as branch test |
|
34 | 34 | (branches are permanent and global, did you want a bookmark?) |
|
35 | 35 | $ hg rollback |
|
36 | 36 | repository tip rolled back to revision 0 (undo commit) |
|
37 | 37 | working directory now based on revision 0 |
|
38 | 38 | $ hg branch |
|
39 | 39 | default |
|
40 | 40 | |
|
41 | 41 | Test issue 1635 (commit message saved) |
|
42 | 42 | $ cat .hg/last-message.txt ; echo |
|
43 | 43 | modify a |
|
44 | 44 | |
|
45 | 45 | |
|
46 | 46 | working dir unaffected by rollback: do not restore dirstate et. al. |
|
47 | 47 | $ hg branch test --quiet |
|
48 | 48 | $ hg branch |
|
49 | 49 | test |
|
50 | 50 | $ hg log --template '{rev} {branch} {desc|firstline}\n' |
|
51 | 51 | 0 default add a again |
|
52 | 52 | $ hg status |
|
53 | 53 | M a |
|
54 | 54 | $ hg bookmark foo |
|
55 | 55 | $ hg commit -m'modify a again' |
|
56 | 56 | $ echo b > b |
|
57 | 57 | $ hg bookmark bar -r default #making bar active, before the transaction |
|
58 | 58 | $ hg log -G --template '{rev} [{branch}] ({bookmarks}) {desc|firstline}\n' |
|
59 | 59 | @ 1 [test] (foo) modify a again |
|
60 | 60 | | |
|
61 | 61 | o 0 [default] (bar) add a again |
|
62 | 62 | |
|
63 | 63 | $ hg add b |
|
64 | 64 | $ hg commit -m'add b' |
|
65 | 65 | $ hg log -G --template '{rev} [{branch}] ({bookmarks}) {desc|firstline}\n' |
|
66 | 66 | @ 2 [test] (foo) add b |
|
67 | 67 | | |
|
68 | 68 | o 1 [test] () modify a again |
|
69 | 69 | | |
|
70 | 70 | o 0 [default] (bar) add a again |
|
71 | 71 | |
|
72 | 72 | $ hg update bar |
|
73 | 73 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
74 | 74 | (activating bookmark bar) |
|
75 | $ cat .hg/undo.backup.branch | |
|
75 | $ cat .hg/undo.backup.branch.bck | |
|
76 | 76 | test |
|
77 | 77 | $ hg log -G --template '{rev} [{branch}] ({bookmarks}) {desc|firstline}\n' |
|
78 | 78 | o 2 [test] (foo) add b |
|
79 | 79 | | |
|
80 | 80 | o 1 [test] () modify a again |
|
81 | 81 | | |
|
82 | 82 | @ 0 [default] (bar) add a again |
|
83 | 83 | |
|
84 | 84 | $ hg rollback |
|
85 | 85 | abort: rollback of last commit while not checked out may lose data |
|
86 | 86 | (use -f to force) |
|
87 | 87 | [255] |
|
88 | 88 | $ hg rollback -f |
|
89 | 89 | repository tip rolled back to revision 1 (undo commit) |
|
90 | 90 | $ hg id -n |
|
91 | 91 | 0 |
|
92 | 92 | $ hg log -G --template '{rev} [{branch}] ({bookmarks}) {desc|firstline}\n' |
|
93 | 93 | o 1 [test] (foo) modify a again |
|
94 | 94 | | |
|
95 | 95 | @ 0 [default] (bar) add a again |
|
96 | 96 | |
|
97 | 97 | $ hg branch |
|
98 | 98 | default |
|
99 | 99 | $ cat .hg/bookmarks.current ; echo |
|
100 | 100 | bar |
|
101 | 101 | $ hg bookmark --delete foo bar |
|
102 | 102 | |
|
103 | 103 | rollback by pretxncommit saves commit message (issue1635) |
|
104 | 104 | |
|
105 | 105 | $ echo a >> a |
|
106 | 106 | $ hg --config hooks.pretxncommit=false commit -m"precious commit message" |
|
107 | 107 | transaction abort! |
|
108 | 108 | rollback completed |
|
109 | 109 | abort: pretxncommit hook exited with status * (glob) |
|
110 | 110 | [40] |
|
111 | 111 | $ cat .hg/last-message.txt ; echo |
|
112 | 112 | precious commit message |
|
113 | 113 | |
|
114 | 114 | same thing, but run $EDITOR |
|
115 | 115 | |
|
116 | 116 | $ cat > editor.sh << '__EOF__' |
|
117 | 117 | > echo "another precious commit message" > "$1" |
|
118 | 118 | > __EOF__ |
|
119 | 119 | $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg --config hooks.pretxncommit=false commit 2>&1 |
|
120 | 120 | transaction abort! |
|
121 | 121 | rollback completed |
|
122 | 122 | note: commit message saved in .hg/last-message.txt |
|
123 | 123 | note: use 'hg commit --logfile .hg/last-message.txt --edit' to reuse it |
|
124 | 124 | abort: pretxncommit hook exited with status * (glob) |
|
125 | 125 | [40] |
|
126 | 126 | $ cat .hg/last-message.txt |
|
127 | 127 | another precious commit message |
|
128 | 128 | |
|
129 | 129 | test rollback on served repository |
|
130 | 130 | |
|
131 | 131 | #if serve |
|
132 | 132 | $ hg commit -m "precious commit message" |
|
133 | 133 | $ hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log |
|
134 | 134 | $ cat hg.pid >> $DAEMON_PIDS |
|
135 | 135 | $ cd .. |
|
136 | 136 | $ hg clone http://localhost:$HGPORT u |
|
137 | 137 | requesting all changes |
|
138 | 138 | adding changesets |
|
139 | 139 | adding manifests |
|
140 | 140 | adding file changes |
|
141 | 141 | added 3 changesets with 2 changes to 1 files (+1 heads) |
|
142 | 142 | new changesets 23b0221f3370:068774709090 |
|
143 | 143 | updating to branch default |
|
144 | 144 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
145 | 145 | $ cd u |
|
146 | 146 | $ hg id default |
|
147 | 147 | 068774709090 |
|
148 | 148 | |
|
149 | 149 | now rollback and observe that 'hg serve' reloads the repository and |
|
150 | 150 | presents the correct tip changeset: |
|
151 | 151 | |
|
152 | 152 | $ hg -R ../t rollback |
|
153 | 153 | repository tip rolled back to revision 1 (undo commit) |
|
154 | 154 | working directory now based on revision 0 |
|
155 | 155 | $ hg id default |
|
156 | 156 | 791dd2169706 |
|
157 | 157 | |
|
158 | 158 | $ killdaemons.py |
|
159 | 159 | #endif |
|
160 | 160 | |
|
161 | 161 | update to older changeset and then refuse rollback, because |
|
162 | 162 | that would lose data (issue2998) |
|
163 | 163 | $ cd ../t |
|
164 | 164 | $ hg -q update |
|
165 | 165 | $ rm `hg status -un` |
|
166 | 166 | $ template='{rev}:{node|short} [{branch}] {desc|firstline}\n' |
|
167 | 167 | $ echo 'valuable new file' > b |
|
168 | 168 | $ echo 'valuable modification' >> a |
|
169 | 169 | $ hg commit -A -m'a valuable change' |
|
170 | 170 | adding b |
|
171 | 171 | $ hg update 0 |
|
172 | 172 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
173 | 173 | $ hg rollback |
|
174 | 174 | abort: rollback of last commit while not checked out may lose data |
|
175 | 175 | (use -f to force) |
|
176 | 176 | [255] |
|
177 | 177 | $ hg tip -q |
|
178 | 178 | 2:4d9cd3795eea |
|
179 | 179 | $ hg rollback -f |
|
180 | 180 | repository tip rolled back to revision 1 (undo commit) |
|
181 | 181 | $ hg status |
|
182 | 182 | $ hg log --removed b # yep, it's gone |
|
183 | 183 | |
|
184 | 184 | same again, but emulate an old client that doesn't write undo.desc |
|
185 | 185 | $ hg -q update |
|
186 | 186 | $ echo 'valuable modification redux' >> a |
|
187 | 187 | $ hg commit -m'a valuable change redux' |
|
188 | 188 | $ rm .hg/undo.desc |
|
189 | 189 | $ hg update 0 |
|
190 | 190 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
191 | 191 | $ hg rollback |
|
192 | 192 | rolling back unknown transaction |
|
193 | 193 | working directory now based on revision 0 |
|
194 | 194 | $ cat a |
|
195 | 195 | a |
|
196 | 196 | |
|
197 | 197 | corrupt journal test |
|
198 | 198 | $ echo "foo" > .hg/store/journal |
|
199 | 199 | $ hg recover --verify -q |
|
200 | 200 | couldn't read journal entry 'foo\n'! |
|
201 | 201 | |
|
202 | 202 | rollback disabled by config |
|
203 | 203 | $ cat >> $HGRCPATH <<EOF |
|
204 | 204 | > [ui] |
|
205 | 205 | > rollback = false |
|
206 | 206 | > EOF |
|
207 | 207 | $ echo narf >> pinky-sayings.txt |
|
208 | 208 | $ hg add pinky-sayings.txt |
|
209 | 209 | $ hg ci -m 'First one.' |
|
210 | 210 | $ hg rollback |
|
211 | 211 | abort: rollback is disabled because it is unsafe |
|
212 | 212 | (see `hg help -v rollback` for information) |
|
213 | 213 | [255] |
|
214 | 214 | |
|
215 | 215 | $ cd .. |
|
216 | 216 | |
|
217 | 217 | I/O errors on stdio are handled properly (issue5658) |
|
218 | 218 | |
|
219 | 219 | $ cat > badui.py << EOF |
|
220 | 220 | > import errno |
|
221 | 221 | > from mercurial.i18n import _ |
|
222 | 222 | > from mercurial import ( |
|
223 | 223 | > error, |
|
224 | 224 | > registrar, |
|
225 | 225 | > ui as uimod, |
|
226 | 226 | > ) |
|
227 | 227 | > |
|
228 | 228 | > configtable = {} |
|
229 | 229 | > configitem = registrar.configitem(configtable) |
|
230 | 230 | > |
|
231 | 231 | > configitem(b'ui', b'ioerrors', |
|
232 | 232 | > default=list, |
|
233 | 233 | > ) |
|
234 | 234 | > |
|
235 | 235 | > def pretxncommit(ui, repo, **kwargs): |
|
236 | 236 | > ui.warn(b'warn during pretxncommit\n') |
|
237 | 237 | > |
|
238 | 238 | > def pretxnclose(ui, repo, **kwargs): |
|
239 | 239 | > ui.warn(b'warn during pretxnclose\n') |
|
240 | 240 | > |
|
241 | 241 | > def txnclose(ui, repo, **kwargs): |
|
242 | 242 | > ui.warn(b'warn during txnclose\n') |
|
243 | 243 | > |
|
244 | 244 | > def txnabort(ui, repo, **kwargs): |
|
245 | 245 | > ui.warn(b'warn during abort\n') |
|
246 | 246 | > |
|
247 | 247 | > class fdproxy(object): |
|
248 | 248 | > def __init__(self, ui, o): |
|
249 | 249 | > self._ui = ui |
|
250 | 250 | > self._o = o |
|
251 | 251 | > |
|
252 | 252 | > def __getattr__(self, attr): |
|
253 | 253 | > return getattr(self._o, attr) |
|
254 | 254 | > |
|
255 | 255 | > def write(self, msg): |
|
256 | 256 | > errors = set(self._ui.configlist(b'ui', b'ioerrors')) |
|
257 | 257 | > pretxncommit = msg == b'warn during pretxncommit\n' |
|
258 | 258 | > pretxnclose = msg == b'warn during pretxnclose\n' |
|
259 | 259 | > txnclose = msg == b'warn during txnclose\n' |
|
260 | 260 | > txnabort = msg == b'warn during abort\n' |
|
261 | 261 | > msgabort = msg == _(b'transaction abort!\n') |
|
262 | 262 | > msgrollback = msg == _(b'rollback completed\n') |
|
263 | 263 | > |
|
264 | 264 | > if pretxncommit and b'pretxncommit' in errors: |
|
265 | 265 | > raise IOError(errno.EPIPE, 'simulated epipe') |
|
266 | 266 | > if pretxnclose and b'pretxnclose' in errors: |
|
267 | 267 | > raise IOError(errno.EIO, 'simulated eio') |
|
268 | 268 | > if txnclose and b'txnclose' in errors: |
|
269 | 269 | > raise IOError(errno.EBADF, 'simulated badf') |
|
270 | 270 | > if txnabort and b'txnabort' in errors: |
|
271 | 271 | > raise IOError(errno.EPIPE, 'simulated epipe') |
|
272 | 272 | > if msgabort and b'msgabort' in errors: |
|
273 | 273 | > raise IOError(errno.EBADF, 'simulated ebadf') |
|
274 | 274 | > if msgrollback and b'msgrollback' in errors: |
|
275 | 275 | > raise IOError(errno.EIO, 'simulated eio') |
|
276 | 276 | > |
|
277 | 277 | > return self._o.write(msg) |
|
278 | 278 | > |
|
279 | 279 | > def uisetup(ui): |
|
280 | 280 | > class badui(ui.__class__): |
|
281 | 281 | > def _write(self, dest, *args, **kwargs): |
|
282 | 282 | > olderr = self.ferr |
|
283 | 283 | > try: |
|
284 | 284 | > if dest is self.ferr: |
|
285 | 285 | > self.ferr = dest = fdproxy(self, olderr) |
|
286 | 286 | > return super(badui, self)._write(dest, *args, **kwargs) |
|
287 | 287 | > finally: |
|
288 | 288 | > self.ferr = olderr |
|
289 | 289 | > |
|
290 | 290 | > ui.__class__ = badui |
|
291 | 291 | > |
|
292 | 292 | > def reposetup(ui, repo): |
|
293 | 293 | > ui.setconfig(b'hooks', b'pretxnclose.badui', pretxnclose, b'badui') |
|
294 | 294 | > ui.setconfig(b'hooks', b'txnclose.badui', txnclose, b'badui') |
|
295 | 295 | > ui.setconfig(b'hooks', b'pretxncommit.badui', pretxncommit, b'badui') |
|
296 | 296 | > ui.setconfig(b'hooks', b'txnabort.badui', txnabort, b'badui') |
|
297 | 297 | > EOF |
|
298 | 298 | |
|
299 | 299 | $ cat >> $HGRCPATH << EOF |
|
300 | 300 | > [extensions] |
|
301 | 301 | > badui = $TESTTMP/badui.py |
|
302 | 302 | > EOF |
|
303 | 303 | |
|
304 | 304 | An I/O error during pretxncommit is handled |
|
305 | 305 | |
|
306 | 306 | $ hg init ioerror-pretxncommit |
|
307 | 307 | $ cd ioerror-pretxncommit |
|
308 | 308 | $ echo 0 > foo |
|
309 | 309 | $ hg -q commit -A -m initial |
|
310 | 310 | warn during pretxncommit |
|
311 | 311 | warn during pretxnclose |
|
312 | 312 | warn during txnclose |
|
313 | 313 | $ echo 1 > foo |
|
314 | 314 | $ hg --config ui.ioerrors=pretxncommit commit -m 'error during pretxncommit' |
|
315 | 315 | warn during pretxnclose |
|
316 | 316 | warn during txnclose |
|
317 | 317 | |
|
318 | 318 | $ hg commit -m 'commit 1' |
|
319 | 319 | nothing changed |
|
320 | 320 | [1] |
|
321 | 321 | |
|
322 | 322 | $ cd .. |
|
323 | 323 | |
|
324 | 324 | An I/O error during pretxnclose is handled |
|
325 | 325 | |
|
326 | 326 | $ hg init ioerror-pretxnclose |
|
327 | 327 | $ cd ioerror-pretxnclose |
|
328 | 328 | $ echo 0 > foo |
|
329 | 329 | $ hg -q commit -A -m initial |
|
330 | 330 | warn during pretxncommit |
|
331 | 331 | warn during pretxnclose |
|
332 | 332 | warn during txnclose |
|
333 | 333 | |
|
334 | 334 | $ echo 1 > foo |
|
335 | 335 | $ hg --config ui.ioerrors=pretxnclose commit -m 'error during pretxnclose' |
|
336 | 336 | warn during pretxncommit |
|
337 | 337 | warn during txnclose |
|
338 | 338 | |
|
339 | 339 | $ hg commit -m 'commit 1' |
|
340 | 340 | nothing changed |
|
341 | 341 | [1] |
|
342 | 342 | |
|
343 | 343 | $ cd .. |
|
344 | 344 | |
|
345 | 345 | An I/O error during txnclose is handled |
|
346 | 346 | |
|
347 | 347 | $ hg init ioerror-txnclose |
|
348 | 348 | $ cd ioerror-txnclose |
|
349 | 349 | $ echo 0 > foo |
|
350 | 350 | $ hg -q commit -A -m initial |
|
351 | 351 | warn during pretxncommit |
|
352 | 352 | warn during pretxnclose |
|
353 | 353 | warn during txnclose |
|
354 | 354 | |
|
355 | 355 | $ echo 1 > foo |
|
356 | 356 | $ hg --config ui.ioerrors=txnclose commit -m 'error during txnclose' |
|
357 | 357 | warn during pretxncommit |
|
358 | 358 | warn during pretxnclose |
|
359 | 359 | |
|
360 | 360 | $ hg commit -m 'commit 1' |
|
361 | 361 | nothing changed |
|
362 | 362 | [1] |
|
363 | 363 | |
|
364 | 364 | $ cd .. |
|
365 | 365 | |
|
366 | 366 | An I/O error writing "transaction abort" is handled |
|
367 | 367 | |
|
368 | 368 | $ hg init ioerror-msgabort |
|
369 | 369 | $ cd ioerror-msgabort |
|
370 | 370 | |
|
371 | 371 | $ echo 0 > foo |
|
372 | 372 | $ hg -q commit -A -m initial |
|
373 | 373 | warn during pretxncommit |
|
374 | 374 | warn during pretxnclose |
|
375 | 375 | warn during txnclose |
|
376 | 376 | |
|
377 | 377 | $ echo 1 > foo |
|
378 | 378 | $ hg --config ui.ioerrors=msgabort --config hooks.pretxncommit=false commit -m 'error during abort message' |
|
379 | 379 | warn during abort |
|
380 | 380 | rollback completed |
|
381 | 381 | abort: pretxncommit hook exited with status 1 |
|
382 | 382 | [40] |
|
383 | 383 | |
|
384 | 384 | $ hg commit -m 'commit 1' |
|
385 | 385 | warn during pretxncommit |
|
386 | 386 | warn during pretxnclose |
|
387 | 387 | warn during txnclose |
|
388 | 388 | |
|
389 | 389 | $ cd .. |
|
390 | 390 | |
|
391 | 391 | An I/O error during txnabort should still result in rollback |
|
392 | 392 | |
|
393 | 393 | $ hg init ioerror-txnabort |
|
394 | 394 | $ cd ioerror-txnabort |
|
395 | 395 | |
|
396 | 396 | $ echo 0 > foo |
|
397 | 397 | $ hg -q commit -A -m initial |
|
398 | 398 | warn during pretxncommit |
|
399 | 399 | warn during pretxnclose |
|
400 | 400 | warn during txnclose |
|
401 | 401 | |
|
402 | 402 | $ echo 1 > foo |
|
403 | 403 | $ hg --config ui.ioerrors=txnabort --config hooks.pretxncommit=false commit -m 'error during abort' |
|
404 | 404 | transaction abort! |
|
405 | 405 | rollback completed |
|
406 | 406 | abort: pretxncommit hook exited with status 1 |
|
407 | 407 | [40] |
|
408 | 408 | |
|
409 | 409 | $ hg commit -m 'commit 1' |
|
410 | 410 | warn during pretxncommit |
|
411 | 411 | warn during pretxnclose |
|
412 | 412 | warn during txnclose |
|
413 | 413 | |
|
414 | 414 | $ cd .. |
|
415 | 415 | |
|
416 | 416 | An I/O error writing "rollback completed" is handled |
|
417 | 417 | |
|
418 | 418 | $ hg init ioerror-msgrollback |
|
419 | 419 | $ cd ioerror-msgrollback |
|
420 | 420 | |
|
421 | 421 | $ echo 0 > foo |
|
422 | 422 | $ hg -q commit -A -m initial |
|
423 | 423 | warn during pretxncommit |
|
424 | 424 | warn during pretxnclose |
|
425 | 425 | warn during txnclose |
|
426 | 426 | |
|
427 | 427 | $ echo 1 > foo |
|
428 | 428 | |
|
429 | 429 | $ hg --config ui.ioerrors=msgrollback --config hooks.pretxncommit=false commit -m 'error during rollback message' |
|
430 | 430 | transaction abort! |
|
431 | 431 | warn during abort |
|
432 | 432 | abort: pretxncommit hook exited with status 1 |
|
433 | 433 | [40] |
|
434 | 434 | |
|
435 | 435 | $ hg verify -q |
|
436 | 436 | |
|
437 | 437 | $ cd .. |
|
438 | 438 | |
|
439 | 439 | Multiple I/O errors after transaction open are handled. |
|
440 | 440 | This is effectively what happens if a peer disconnects in the middle |
|
441 | 441 | of a transaction. |
|
442 | 442 | |
|
443 | 443 | $ hg init ioerror-multiple |
|
444 | 444 | $ cd ioerror-multiple |
|
445 | 445 | $ echo 0 > foo |
|
446 | 446 | $ hg -q commit -A -m initial |
|
447 | 447 | warn during pretxncommit |
|
448 | 448 | warn during pretxnclose |
|
449 | 449 | warn during txnclose |
|
450 | 450 | |
|
451 | 451 | $ echo 1 > foo |
|
452 | 452 | |
|
453 | 453 | $ hg --config ui.ioerrors=pretxncommit,pretxnclose,txnclose,txnabort,msgabort,msgrollback commit -m 'multiple errors' |
|
454 | 454 | |
|
455 | 455 | $ hg verify -q |
|
456 | 456 | |
|
457 | 457 | $ cd .. |
@@ -1,448 +1,448 b'' | |||
|
1 | 1 | Test correctness of revlog inline -> non-inline transition |
|
2 | 2 | ---------------------------------------------------------- |
|
3 | 3 | |
|
4 | 4 | We test various file length and naming pattern as this created issue in the |
|
5 | 5 | past. |
|
6 | 6 | |
|
7 | 7 | Helper extension to intercept renames and kill process |
|
8 | 8 | |
|
9 | 9 | $ cat > $TESTTMP/intercept_before_rename.py << EOF |
|
10 | 10 | > import os |
|
11 | 11 | > import signal |
|
12 | 12 | > from mercurial import extensions, util |
|
13 | 13 | > |
|
14 | 14 | > def extsetup(ui): |
|
15 | 15 | > def rename(orig, src, dest, *args, **kwargs): |
|
16 | 16 | > path = util.normpath(dest) |
|
17 | 17 | > if path.endswith(b'data/file.i'): |
|
18 | 18 | > os.kill(os.getpid(), signal.SIGKILL) |
|
19 | 19 | > return orig(src, dest, *args, **kwargs) |
|
20 | 20 | > extensions.wrapfunction(util, 'rename', rename) |
|
21 | 21 | > EOF |
|
22 | 22 | |
|
23 | 23 | $ cat > $TESTTMP/intercept_after_rename.py << EOF |
|
24 | 24 | > import os |
|
25 | 25 | > import signal |
|
26 | 26 | > from mercurial import extensions, util |
|
27 | 27 | > |
|
28 | 28 | > def extsetup(ui): |
|
29 | 29 | > def close(orig, *args, **kwargs): |
|
30 | 30 | > path = util.normpath(args[0]._atomictempfile__name) |
|
31 | 31 | > r = orig(*args, **kwargs) |
|
32 | 32 | > if path.endswith(b'/.hg/store/data/file.i'): |
|
33 | 33 | > os.kill(os.getpid(), signal.SIGKILL) |
|
34 | 34 | > return r |
|
35 | 35 | > extensions.wrapfunction(util.atomictempfile, 'close', close) |
|
36 | 36 | > def extsetup(ui): |
|
37 | 37 | > def rename(orig, src, dest, *args, **kwargs): |
|
38 | 38 | > path = util.normpath(dest) |
|
39 | 39 | > r = orig(src, dest, *args, **kwargs) |
|
40 | 40 | > if path.endswith(b'data/file.i'): |
|
41 | 41 | > os.kill(os.getpid(), signal.SIGKILL) |
|
42 | 42 | > return r |
|
43 | 43 | > extensions.wrapfunction(util, 'rename', rename) |
|
44 | 44 | > EOF |
|
45 | 45 | |
|
46 | 46 | $ cat > $TESTTMP/killme.py << EOF |
|
47 | 47 | > import os |
|
48 | 48 | > import signal |
|
49 | 49 | > |
|
50 | 50 | > def killme(ui, repo, hooktype, **kwargs): |
|
51 | 51 | > os.kill(os.getpid(), signal.SIGKILL) |
|
52 | 52 | > EOF |
|
53 | 53 | |
|
54 | 54 | $ cat > $TESTTMP/reader_wait_split.py << EOF |
|
55 | 55 | > import os |
|
56 | 56 | > import signal |
|
57 | 57 | > from mercurial import extensions, revlog, testing |
|
58 | 58 | > def _wait_post_load(orig, self, *args, **kwargs): |
|
59 | 59 | > wait = b'data/file' in self.radix |
|
60 | 60 | > if wait: |
|
61 | 61 | > testing.wait_file(b"$TESTTMP/writer-revlog-split") |
|
62 | 62 | > r = orig(self, *args, **kwargs) |
|
63 | 63 | > if wait: |
|
64 | 64 | > testing.write_file(b"$TESTTMP/reader-index-read") |
|
65 | 65 | > testing.wait_file(b"$TESTTMP/writer-revlog-unsplit") |
|
66 | 66 | > return r |
|
67 | 67 | > |
|
68 | 68 | > def extsetup(ui): |
|
69 | 69 | > extensions.wrapfunction(revlog.revlog, '_loadindex', _wait_post_load) |
|
70 | 70 | > EOF |
|
71 | 71 | |
|
72 | 72 | setup a repository for tests |
|
73 | 73 | ---------------------------- |
|
74 | 74 | |
|
75 | 75 | $ cat >> $HGRCPATH << EOF |
|
76 | 76 | > [format] |
|
77 | 77 | > revlog-compression=none |
|
78 | 78 | > EOF |
|
79 | 79 | |
|
80 | 80 | $ hg init troffset-computation |
|
81 | 81 | $ cd troffset-computation |
|
82 | 82 | $ files=" |
|
83 | 83 | > file |
|
84 | 84 | > Directory_With,Special%Char/Complex_File.babar |
|
85 | 85 | > foo/bar/babar_celeste/foo |
|
86 | 86 | > 1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/f |
|
87 | 87 | > " |
|
88 | 88 | $ for f in $files; do |
|
89 | 89 | > mkdir -p `dirname $f` |
|
90 | 90 | > done |
|
91 | 91 | $ for f in $files; do |
|
92 | 92 | > printf '%20d' '1' > $f |
|
93 | 93 | > done |
|
94 | 94 | $ hg commit -Aqma |
|
95 | 95 | $ for f in $files; do |
|
96 | 96 | > printf '%1024d' '1' > $f |
|
97 | 97 | > done |
|
98 | 98 | $ hg commit -Aqmb |
|
99 | 99 | $ for f in $files; do |
|
100 | 100 | > printf '%20d' '1' > $f |
|
101 | 101 | > done |
|
102 | 102 | $ hg commit -Aqmc |
|
103 | 103 | $ for f in $files; do |
|
104 | 104 | > dd if=/dev/zero of=$f bs=1k count=128 > /dev/null 2>&1 |
|
105 | 105 | > done |
|
106 | 106 | $ hg commit -AqmD --traceback |
|
107 | 107 | |
|
108 | 108 | Reference size: |
|
109 | 109 | $ f -s file |
|
110 | 110 | file: size=131072 |
|
111 | 111 | $ f -s .hg/store/data/file* |
|
112 | 112 | .hg/store/data/file.d: size=132139 |
|
113 | 113 | .hg/store/data/file.i: size=256 |
|
114 | 114 | |
|
115 | 115 | $ cd .. |
|
116 | 116 | |
|
117 | 117 | |
|
118 | 118 | Test a hard crash after the file was split but before the transaction was committed |
|
119 | 119 | =================================================================================== |
|
120 | 120 | |
|
121 | 121 | Test offset computation to correctly factor in the index entries themselves. |
|
122 | 122 | Also test that the new data size has the correct size if the transaction is aborted |
|
123 | 123 | after the index has been replaced. |
|
124 | 124 | |
|
125 | 125 | Test repo has commits a, b, c, D, where D is large (grows the revlog enough that it |
|
126 | 126 | transitions to non-inline storage). The clone initially has changes a, b |
|
127 | 127 | and will transition to non-inline storage when adding c, D. |
|
128 | 128 | |
|
129 | 129 | If the transaction adding c, D is rolled back, then we don't undo the revlog split, |
|
130 | 130 | but truncate the index and the data to remove both c and D. |
|
131 | 131 | |
|
132 | 132 | |
|
133 | 133 | $ hg clone --quiet --rev 1 troffset-computation troffset-computation-copy |
|
134 | 134 | $ cd troffset-computation-copy |
|
135 | 135 | |
|
136 | 136 | Reference size: |
|
137 | 137 | $ f -s file |
|
138 | 138 | file: size=1024 |
|
139 | 139 | $ f -s .hg/store/data/file* |
|
140 | 140 | .hg/store/data/file.i: size=1174 |
|
141 | 141 | |
|
142 | 142 | $ cat > .hg/hgrc <<EOF |
|
143 | 143 | > [hooks] |
|
144 | 144 | > pretxnchangegroup = python:$TESTTMP/killme.py:killme |
|
145 | 145 | > EOF |
|
146 | 146 | #if chg |
|
147 | 147 | $ hg pull ../troffset-computation |
|
148 | 148 | pulling from ../troffset-computation |
|
149 | 149 | [255] |
|
150 | 150 | #else |
|
151 | 151 | $ hg pull ../troffset-computation |
|
152 | 152 | pulling from ../troffset-computation |
|
153 | 153 | *Killed* (glob) |
|
154 | 154 | [137] |
|
155 | 155 | #endif |
|
156 | 156 | |
|
157 | 157 | |
|
158 | 158 | The inline revlog still exist, but a split version exist next to it |
|
159 | 159 | |
|
160 | 160 | $ f -s .hg/store/data/file* |
|
161 | 161 | .hg/store/data/file.d: size=132139 |
|
162 | 162 | .hg/store/data/file.i: size=132395 |
|
163 | 163 | .hg/store/data/file.i.s: size=256 |
|
164 | 164 | |
|
165 | 165 | |
|
166 | 166 | The first file.i entry should match the "Reference size" above. |
|
167 | 167 | The first file.d entry is the temporary record during the split, |
|
168 | 168 | |
|
169 | 169 | A "temporary file" entry exist for the split index. |
|
170 | 170 | |
|
171 | 171 | $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file |
|
172 | 172 | data/file.i 1174 |
|
173 | 173 | data/file.d 0 |
|
174 | 174 | $ cat .hg/store/journal.backupfiles | tr -s '\000' ' ' | tr -s '\00' ' '| grep data/file |
|
175 | data/file.i data/journal.backup.file.i 0 | |
|
175 | data/file.i data/journal.backup.file.i.bck 0 | |
|
176 | 176 | data/file.i.s 0 |
|
177 | 177 | |
|
178 | 178 | recover is rolling the split back, the fncache is still valid |
|
179 | 179 | |
|
180 | 180 | $ hg recover |
|
181 | 181 | rolling back interrupted transaction |
|
182 | 182 | (verify step skipped, run `hg verify` to check your repository content) |
|
183 | 183 | $ f -s .hg/store/data/file* |
|
184 | 184 | .hg/store/data/file.i: size=1174 |
|
185 | 185 | $ hg tip |
|
186 | 186 | changeset: 1:cc8dfb126534 |
|
187 | 187 | tag: tip |
|
188 | 188 | user: test |
|
189 | 189 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
190 | 190 | summary: b |
|
191 | 191 | |
|
192 | 192 | $ hg verify -q |
|
193 | 193 | $ hg debugrebuildfncache --only-data |
|
194 | 194 | fncache already up to date |
|
195 | 195 | $ hg verify -q |
|
196 | 196 | $ cd .. |
|
197 | 197 | |
|
198 | 198 | Test a hard crash right before the index is move into place |
|
199 | 199 | =========================================================== |
|
200 | 200 | |
|
201 | 201 | Now retry the procedure but intercept the rename of the index and check that |
|
202 | 202 | the journal does not contain the new index size. This demonstrates the edge case |
|
203 | 203 | where the data file is left as garbage. |
|
204 | 204 | |
|
205 | 205 | $ hg clone --quiet --rev 1 troffset-computation troffset-computation-copy2 |
|
206 | 206 | $ cd troffset-computation-copy2 |
|
207 | 207 | |
|
208 | 208 | Reference size: |
|
209 | 209 | $ f -s file |
|
210 | 210 | file: size=1024 |
|
211 | 211 | $ f -s .hg/store/data/file* |
|
212 | 212 | .hg/store/data/file.i: size=1174 |
|
213 | 213 | |
|
214 | 214 | $ cat > .hg/hgrc <<EOF |
|
215 | 215 | > [extensions] |
|
216 | 216 | > intercept_rename = $TESTTMP/intercept_before_rename.py |
|
217 | 217 | > EOF |
|
218 | 218 | #if chg |
|
219 | 219 | $ hg pull ../troffset-computation |
|
220 | 220 | pulling from ../troffset-computation |
|
221 | 221 | searching for changes |
|
222 | 222 | adding changesets |
|
223 | 223 | adding manifests |
|
224 | 224 | adding file changes |
|
225 | 225 | [255] |
|
226 | 226 | #else |
|
227 | 227 | $ hg pull ../troffset-computation |
|
228 | 228 | pulling from ../troffset-computation |
|
229 | 229 | searching for changes |
|
230 | 230 | adding changesets |
|
231 | 231 | adding manifests |
|
232 | 232 | adding file changes |
|
233 | 233 | *Killed* (glob) |
|
234 | 234 | [137] |
|
235 | 235 | #endif |
|
236 | 236 | |
|
237 | 237 | The inline revlog still exist, but a split version exist next to it |
|
238 | 238 | |
|
239 | 239 | $ f -s .hg/store/data/file* |
|
240 | 240 | .hg/store/data/file.d: size=132139 |
|
241 | 241 | .hg/store/data/file.i: size=132395 |
|
242 | 242 | .hg/store/data/file.i.s: size=256 |
|
243 | 243 | |
|
244 | 244 | $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file |
|
245 | 245 | data/file.i 1174 |
|
246 | 246 | data/file.d 0 |
|
247 | 247 | |
|
248 | 248 | recover is rolling the split back, the fncache is still valid |
|
249 | 249 | |
|
250 | 250 | $ hg recover |
|
251 | 251 | rolling back interrupted transaction |
|
252 | 252 | (verify step skipped, run `hg verify` to check your repository content) |
|
253 | 253 | $ f -s .hg/store/data/file* |
|
254 | 254 | .hg/store/data/file.i: size=1174 |
|
255 | 255 | $ hg tip |
|
256 | 256 | changeset: 1:cc8dfb126534 |
|
257 | 257 | tag: tip |
|
258 | 258 | user: test |
|
259 | 259 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
260 | 260 | summary: b |
|
261 | 261 | |
|
262 | 262 | $ hg verify -q |
|
263 | 263 | $ cd .. |
|
264 | 264 | |
|
265 | 265 | Test a hard crash right after the index is move into place |
|
266 | 266 | =========================================================== |
|
267 | 267 | |
|
268 | 268 | Now retry the procedure but intercept the rename of the index. |
|
269 | 269 | |
|
270 | 270 | $ hg clone --quiet --rev 1 troffset-computation troffset-computation-crash-after-rename |
|
271 | 271 | $ cd troffset-computation-crash-after-rename |
|
272 | 272 | |
|
273 | 273 | Reference size: |
|
274 | 274 | $ f -s file |
|
275 | 275 | file: size=1024 |
|
276 | 276 | $ f -s .hg/store/data/file* |
|
277 | 277 | .hg/store/data/file.i: size=1174 |
|
278 | 278 | |
|
279 | 279 | $ cat > .hg/hgrc <<EOF |
|
280 | 280 | > [extensions] |
|
281 | 281 | > intercept_rename = $TESTTMP/intercept_after_rename.py |
|
282 | 282 | > EOF |
|
283 | 283 | #if chg |
|
284 | 284 | $ hg pull ../troffset-computation |
|
285 | 285 | pulling from ../troffset-computation |
|
286 | 286 | searching for changes |
|
287 | 287 | adding changesets |
|
288 | 288 | adding manifests |
|
289 | 289 | adding file changes |
|
290 | 290 | [255] |
|
291 | 291 | #else |
|
292 | 292 | $ hg pull ../troffset-computation |
|
293 | 293 | pulling from ../troffset-computation |
|
294 | 294 | searching for changes |
|
295 | 295 | adding changesets |
|
296 | 296 | adding manifests |
|
297 | 297 | adding file changes |
|
298 | 298 | *Killed* (glob) |
|
299 | 299 | [137] |
|
300 | 300 | #endif |
|
301 | 301 | |
|
302 | 302 | The inline revlog was over written on disk |
|
303 | 303 | |
|
304 | 304 | $ f -s .hg/store/data/file* |
|
305 | 305 | .hg/store/data/file.d: size=132139 |
|
306 | 306 | .hg/store/data/file.i: size=256 |
|
307 | 307 | |
|
308 | 308 | $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file |
|
309 | 309 | data/file.i 1174 |
|
310 | 310 | data/file.d 0 |
|
311 | 311 | |
|
312 | 312 | recover is rolling the split back, the fncache is still valid |
|
313 | 313 | |
|
314 | 314 | $ hg recover |
|
315 | 315 | rolling back interrupted transaction |
|
316 | 316 | (verify step skipped, run `hg verify` to check your repository content) |
|
317 | 317 | $ f -s .hg/store/data/file* |
|
318 | 318 | .hg/store/data/file.i: size=1174 |
|
319 | 319 | $ hg tip |
|
320 | 320 | changeset: 1:cc8dfb126534 |
|
321 | 321 | tag: tip |
|
322 | 322 | user: test |
|
323 | 323 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
324 | 324 | summary: b |
|
325 | 325 | |
|
326 | 326 | $ hg verify -q |
|
327 | 327 | $ cd .. |
|
328 | 328 | |
|
329 | 329 | Have the transaction rollback itself without any hard crash |
|
330 | 330 | =========================================================== |
|
331 | 331 | |
|
332 | 332 | |
|
333 | 333 | Repeat the original test but let hg rollback the transaction. |
|
334 | 334 | |
|
335 | 335 | $ hg clone --quiet --rev 1 troffset-computation troffset-computation-copy-rb |
|
336 | 336 | $ cd troffset-computation-copy-rb |
|
337 | 337 | $ cat > .hg/hgrc <<EOF |
|
338 | 338 | > [hooks] |
|
339 | 339 | > pretxnchangegroup = false |
|
340 | 340 | > EOF |
|
341 | 341 | $ hg pull ../troffset-computation |
|
342 | 342 | pulling from ../troffset-computation |
|
343 | 343 | searching for changes |
|
344 | 344 | adding changesets |
|
345 | 345 | adding manifests |
|
346 | 346 | adding file changes |
|
347 | 347 | transaction abort! |
|
348 | 348 | rollback completed |
|
349 | 349 | abort: pretxnchangegroup hook exited with status 1 |
|
350 | 350 | [40] |
|
351 | 351 | |
|
352 | 352 | The split was rollback |
|
353 | 353 | |
|
354 | 354 | $ f -s .hg/store/data/file* |
|
355 | 355 | .hg/store/data/file.d: size=0 |
|
356 | 356 | .hg/store/data/file.i: size=1174 |
|
357 | 357 | |
|
358 | 358 | |
|
359 | 359 | $ hg tip |
|
360 | 360 | changeset: 1:cc8dfb126534 |
|
361 | 361 | tag: tip |
|
362 | 362 | user: test |
|
363 | 363 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
364 | 364 | summary: b |
|
365 | 365 | |
|
366 | 366 | $ hg verify -q |
|
367 | 367 | $ cd .. |
|
368 | 368 | |
|
369 | 369 | Read race |
|
370 | 370 | ========= |
|
371 | 371 | |
|
372 | 372 | We check that a client that started reading a revlog (its index) after the |
|
373 | 373 | split and end reading (the data) after the rollback should be fine |
|
374 | 374 | |
|
375 | 375 | $ hg clone --quiet --rev 1 troffset-computation troffset-computation-race |
|
376 | 376 | $ cd troffset-computation-race |
|
377 | 377 | $ cat > .hg/hgrc <<EOF |
|
378 | 378 | > [hooks] |
|
379 | 379 | > pretxnchangegroup=$RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/reader-index-read $TESTTMP/writer-revlog-split |
|
380 | 380 | > pretxnclose = false |
|
381 | 381 | > EOF |
|
382 | 382 | |
|
383 | 383 | start a reader |
|
384 | 384 | |
|
385 | 385 | $ hg cat --rev 0 file \ |
|
386 | 386 | > --config "extensions.wait_read=$TESTTMP/reader_wait_split.py" \ |
|
387 | 387 | > 2> $TESTTMP/reader.stderr \ |
|
388 | 388 | > > $TESTTMP/reader.stdout & |
|
389 | 389 | |
|
390 | 390 | Do a failed pull in // |
|
391 | 391 | |
|
392 | 392 | $ hg pull ../troffset-computation |
|
393 | 393 | pulling from ../troffset-computation |
|
394 | 394 | searching for changes |
|
395 | 395 | adding changesets |
|
396 | 396 | adding manifests |
|
397 | 397 | adding file changes |
|
398 | 398 | transaction abort! |
|
399 | 399 | rollback completed |
|
400 | 400 | abort: pretxnclose hook exited with status 1 |
|
401 | 401 | [40] |
|
402 | 402 | $ touch $TESTTMP/writer-revlog-unsplit |
|
403 | 403 | $ wait |
|
404 | 404 | |
|
405 | 405 | The reader should be fine |
|
406 | 406 | $ cat $TESTTMP/reader.stderr |
|
407 | 407 | $ cat $TESTTMP/reader.stdout |
|
408 | 408 | 1 (no-eol) |
|
409 | 409 | $ cd .. |
|
410 | 410 | |
|
411 | 411 | pending hooks |
|
412 | 412 | ============= |
|
413 | 413 | |
|
414 | 414 | We checks that hooks properly see the inside of the transaction, while other process don't. |
|
415 | 415 | |
|
416 | 416 | $ hg clone --quiet --rev 1 troffset-computation troffset-computation-hooks |
|
417 | 417 | $ cd troffset-computation-hooks |
|
418 | 418 | $ cat > .hg/hgrc <<EOF |
|
419 | 419 | > [hooks] |
|
420 | 420 | > pretxnclose.01-echo = hg cat -r 'max(all())' file | f --size |
|
421 | 421 | > pretxnclose.02-echo = $RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/hook-done $TESTTMP/hook-tr-ready |
|
422 | 422 | > pretxnclose.03-abort = false |
|
423 | 423 | > EOF |
|
424 | 424 | |
|
425 | 425 | $ ( |
|
426 | 426 | > $RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/hook-tr-ready;\ |
|
427 | 427 | > hg cat -r 'max(all())' file | f --size;\ |
|
428 | 428 | > touch $TESTTMP/hook-done |
|
429 | 429 | > ) >stdout 2>stderr & |
|
430 | 430 | |
|
431 | 431 | $ hg pull ../troffset-computation |
|
432 | 432 | pulling from ../troffset-computation |
|
433 | 433 | searching for changes |
|
434 | 434 | adding changesets |
|
435 | 435 | adding manifests |
|
436 | 436 | adding file changes |
|
437 | 437 | size=131072 |
|
438 | 438 | transaction abort! |
|
439 | 439 | rollback completed |
|
440 | 440 | abort: pretxnclose.03-abort hook exited with status 1 |
|
441 | 441 | [40] |
|
442 | 442 | |
|
443 | 443 | $ cat stdout |
|
444 | 444 | size=1024 |
|
445 | 445 | $ cat stderr |
|
446 | 446 | |
|
447 | 447 | |
|
448 | 448 | $ cd .. |
@@ -1,2101 +1,2101 b'' | |||
|
1 | 1 | #require no-reposimplestore |
|
2 | 2 | |
|
3 | 3 | $ cat >> $HGRCPATH << EOF |
|
4 | 4 | > [extensions] |
|
5 | 5 | > share = |
|
6 | 6 | > [format] |
|
7 | 7 | > # stabilize test accross variant |
|
8 | 8 | > revlog-compression=zlib |
|
9 | 9 | > [storage] |
|
10 | 10 | > dirstate-v2.slow-path=allow |
|
11 | 11 | > EOF |
|
12 | 12 | |
|
13 | 13 | store and revlogv1 are required in source |
|
14 | 14 | |
|
15 | 15 | $ hg --config format.usestore=false init no-store |
|
16 | 16 | $ hg -R no-store debugupgraderepo |
|
17 | 17 | abort: cannot upgrade repository; requirement missing: store |
|
18 | 18 | [255] |
|
19 | 19 | |
|
20 | 20 | $ hg init no-revlogv1 |
|
21 | 21 | $ cat > no-revlogv1/.hg/requires << EOF |
|
22 | 22 | > dotencode |
|
23 | 23 | > fncache |
|
24 | 24 | > generaldelta |
|
25 | 25 | > store |
|
26 | 26 | > EOF |
|
27 | 27 | |
|
28 | 28 | $ hg -R no-revlogv1 debugupgraderepo |
|
29 | 29 | abort: cannot upgrade repository; missing a revlog version |
|
30 | 30 | [255] |
|
31 | 31 | |
|
32 | 32 | Cannot upgrade shared repositories |
|
33 | 33 | |
|
34 | 34 | $ hg init share-parent |
|
35 | 35 | $ hg -R share-parent debugbuilddag -n .+9 |
|
36 | 36 | $ hg -R share-parent up tip |
|
37 | 37 | 10 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
38 | 38 | $ hg -q share share-parent share-child |
|
39 | 39 | |
|
40 | 40 | $ hg -R share-child debugupgraderepo --config format.sparse-revlog=no |
|
41 | 41 | abort: cannot use these actions on a share repository: sparserevlog |
|
42 | 42 | (upgrade the main repository directly) |
|
43 | 43 | [255] |
|
44 | 44 | |
|
45 | 45 | Unless the action is compatible with share |
|
46 | 46 | |
|
47 | 47 | $ hg -R share-child debugupgraderepo --config format.use-dirstate-v2=yes --quiet |
|
48 | 48 | requirements |
|
49 | 49 | preserved: * (glob) |
|
50 | 50 | added: dirstate-v2 |
|
51 | 51 | |
|
52 | 52 | no revlogs to process |
|
53 | 53 | |
|
54 | 54 | |
|
55 | 55 | $ hg -R share-child debugupgraderepo --config format.use-dirstate-v2=yes --quiet --run |
|
56 | 56 | upgrade will perform the following actions: |
|
57 | 57 | |
|
58 | 58 | requirements |
|
59 | 59 | preserved: * (glob) |
|
60 | 60 | added: dirstate-v2 |
|
61 | 61 | |
|
62 | 62 | no revlogs to process |
|
63 | 63 | |
|
64 | 64 | $ hg debugformat -R share-child | grep dirstate-v2 |
|
65 | 65 | dirstate-v2: yes |
|
66 | 66 | $ hg debugformat -R share-parent | grep dirstate-v2 |
|
67 | 67 | dirstate-v2: no |
|
68 | 68 | $ hg status --all -R share-child |
|
69 | 69 | C nf0 |
|
70 | 70 | C nf1 |
|
71 | 71 | C nf2 |
|
72 | 72 | C nf3 |
|
73 | 73 | C nf4 |
|
74 | 74 | C nf5 |
|
75 | 75 | C nf6 |
|
76 | 76 | C nf7 |
|
77 | 77 | C nf8 |
|
78 | 78 | C nf9 |
|
79 | 79 | $ hg log -l 3 -R share-child |
|
80 | 80 | changeset: 9:0059eb38e4a4 |
|
81 | 81 | tag: tip |
|
82 | 82 | user: debugbuilddag |
|
83 | 83 | date: Thu Jan 01 00:00:09 1970 +0000 |
|
84 | 84 | summary: r9 |
|
85 | 85 | |
|
86 | 86 | changeset: 8:4d5be70c8130 |
|
87 | 87 | user: debugbuilddag |
|
88 | 88 | date: Thu Jan 01 00:00:08 1970 +0000 |
|
89 | 89 | summary: r8 |
|
90 | 90 | |
|
91 | 91 | changeset: 7:e60bfe72517e |
|
92 | 92 | user: debugbuilddag |
|
93 | 93 | date: Thu Jan 01 00:00:07 1970 +0000 |
|
94 | 94 | summary: r7 |
|
95 | 95 | |
|
96 | 96 | $ hg status --all -R share-parent |
|
97 | 97 | C nf0 |
|
98 | 98 | C nf1 |
|
99 | 99 | C nf2 |
|
100 | 100 | C nf3 |
|
101 | 101 | C nf4 |
|
102 | 102 | C nf5 |
|
103 | 103 | C nf6 |
|
104 | 104 | C nf7 |
|
105 | 105 | C nf8 |
|
106 | 106 | C nf9 |
|
107 | 107 | $ hg log -l 3 -R share-parent |
|
108 | 108 | changeset: 9:0059eb38e4a4 |
|
109 | 109 | tag: tip |
|
110 | 110 | user: debugbuilddag |
|
111 | 111 | date: Thu Jan 01 00:00:09 1970 +0000 |
|
112 | 112 | summary: r9 |
|
113 | 113 | |
|
114 | 114 | changeset: 8:4d5be70c8130 |
|
115 | 115 | user: debugbuilddag |
|
116 | 116 | date: Thu Jan 01 00:00:08 1970 +0000 |
|
117 | 117 | summary: r8 |
|
118 | 118 | |
|
119 | 119 | changeset: 7:e60bfe72517e |
|
120 | 120 | user: debugbuilddag |
|
121 | 121 | date: Thu Jan 01 00:00:07 1970 +0000 |
|
122 | 122 | summary: r7 |
|
123 | 123 | |
|
124 | 124 | |
|
125 | 125 | $ hg -R share-child debugupgraderepo --config format.use-dirstate-v2=no --quiet --run |
|
126 | 126 | upgrade will perform the following actions: |
|
127 | 127 | |
|
128 | 128 | requirements |
|
129 | 129 | preserved: * (glob) |
|
130 | 130 | removed: dirstate-v2 |
|
131 | 131 | |
|
132 | 132 | no revlogs to process |
|
133 | 133 | |
|
134 | 134 | $ hg debugformat -R share-child | grep dirstate-v2 |
|
135 | 135 | dirstate-v2: no |
|
136 | 136 | $ hg debugformat -R share-parent | grep dirstate-v2 |
|
137 | 137 | dirstate-v2: no |
|
138 | 138 | $ hg status --all -R share-child |
|
139 | 139 | C nf0 |
|
140 | 140 | C nf1 |
|
141 | 141 | C nf2 |
|
142 | 142 | C nf3 |
|
143 | 143 | C nf4 |
|
144 | 144 | C nf5 |
|
145 | 145 | C nf6 |
|
146 | 146 | C nf7 |
|
147 | 147 | C nf8 |
|
148 | 148 | C nf9 |
|
149 | 149 | $ hg log -l 3 -R share-child |
|
150 | 150 | changeset: 9:0059eb38e4a4 |
|
151 | 151 | tag: tip |
|
152 | 152 | user: debugbuilddag |
|
153 | 153 | date: Thu Jan 01 00:00:09 1970 +0000 |
|
154 | 154 | summary: r9 |
|
155 | 155 | |
|
156 | 156 | changeset: 8:4d5be70c8130 |
|
157 | 157 | user: debugbuilddag |
|
158 | 158 | date: Thu Jan 01 00:00:08 1970 +0000 |
|
159 | 159 | summary: r8 |
|
160 | 160 | |
|
161 | 161 | changeset: 7:e60bfe72517e |
|
162 | 162 | user: debugbuilddag |
|
163 | 163 | date: Thu Jan 01 00:00:07 1970 +0000 |
|
164 | 164 | summary: r7 |
|
165 | 165 | |
|
166 | 166 | $ hg status --all -R share-parent |
|
167 | 167 | C nf0 |
|
168 | 168 | C nf1 |
|
169 | 169 | C nf2 |
|
170 | 170 | C nf3 |
|
171 | 171 | C nf4 |
|
172 | 172 | C nf5 |
|
173 | 173 | C nf6 |
|
174 | 174 | C nf7 |
|
175 | 175 | C nf8 |
|
176 | 176 | C nf9 |
|
177 | 177 | $ hg log -l 3 -R share-parent |
|
178 | 178 | changeset: 9:0059eb38e4a4 |
|
179 | 179 | tag: tip |
|
180 | 180 | user: debugbuilddag |
|
181 | 181 | date: Thu Jan 01 00:00:09 1970 +0000 |
|
182 | 182 | summary: r9 |
|
183 | 183 | |
|
184 | 184 | changeset: 8:4d5be70c8130 |
|
185 | 185 | user: debugbuilddag |
|
186 | 186 | date: Thu Jan 01 00:00:08 1970 +0000 |
|
187 | 187 | summary: r8 |
|
188 | 188 | |
|
189 | 189 | changeset: 7:e60bfe72517e |
|
190 | 190 | user: debugbuilddag |
|
191 | 191 | date: Thu Jan 01 00:00:07 1970 +0000 |
|
192 | 192 | summary: r7 |
|
193 | 193 | |
|
194 | 194 | |
|
195 | 195 | Do not yet support upgrading treemanifest repos |
|
196 | 196 | |
|
197 | 197 | $ hg --config experimental.treemanifest=true init treemanifest |
|
198 | 198 | $ hg -R treemanifest debugupgraderepo |
|
199 | 199 | abort: cannot upgrade repository; unsupported source requirement: treemanifest |
|
200 | 200 | [255] |
|
201 | 201 | |
|
202 | 202 | Cannot add treemanifest requirement during upgrade |
|
203 | 203 | |
|
204 | 204 | $ hg init disallowaddedreq |
|
205 | 205 | $ hg -R disallowaddedreq --config experimental.treemanifest=true debugupgraderepo |
|
206 | 206 | abort: cannot upgrade repository; do not support adding requirement: treemanifest |
|
207 | 207 | [255] |
|
208 | 208 | |
|
209 | 209 | An upgrade of a repository created with recommended settings only suggests optimizations |
|
210 | 210 | |
|
211 | 211 | $ hg init empty |
|
212 | 212 | $ cd empty |
|
213 | 213 | $ hg debugformat |
|
214 | 214 | format-variant repo |
|
215 | 215 | fncache: yes |
|
216 | 216 | dirstate-v2: no |
|
217 | 217 | tracked-hint: no |
|
218 | 218 | dotencode: yes |
|
219 | 219 | generaldelta: yes |
|
220 | 220 | share-safe: yes |
|
221 | 221 | sparserevlog: yes |
|
222 | 222 | persistent-nodemap: no (no-rust !) |
|
223 | 223 | persistent-nodemap: yes (rust !) |
|
224 | 224 | copies-sdc: no |
|
225 | 225 | revlog-v2: no |
|
226 | 226 | changelog-v2: no |
|
227 | 227 | plain-cl-delta: yes |
|
228 | 228 | compression: zlib |
|
229 | 229 | compression-level: default |
|
230 | 230 | $ hg debugformat --verbose |
|
231 | 231 | format-variant repo config default |
|
232 | 232 | fncache: yes yes yes |
|
233 | 233 | dirstate-v2: no no no |
|
234 | 234 | tracked-hint: no no no |
|
235 | 235 | dotencode: yes yes yes |
|
236 | 236 | generaldelta: yes yes yes |
|
237 | 237 | share-safe: yes yes yes |
|
238 | 238 | sparserevlog: yes yes yes |
|
239 | 239 | persistent-nodemap: no no no (no-rust !) |
|
240 | 240 | persistent-nodemap: yes yes no (rust !) |
|
241 | 241 | copies-sdc: no no no |
|
242 | 242 | revlog-v2: no no no |
|
243 | 243 | changelog-v2: no no no |
|
244 | 244 | plain-cl-delta: yes yes yes |
|
245 | 245 | compression: zlib zlib zlib (no-zstd !) |
|
246 | 246 | compression: zlib zlib zstd (zstd !) |
|
247 | 247 | compression-level: default default default |
|
248 | 248 | $ hg debugformat --verbose --config format.usefncache=no |
|
249 | 249 | format-variant repo config default |
|
250 | 250 | fncache: yes no yes |
|
251 | 251 | dirstate-v2: no no no |
|
252 | 252 | tracked-hint: no no no |
|
253 | 253 | dotencode: yes no yes |
|
254 | 254 | generaldelta: yes yes yes |
|
255 | 255 | share-safe: yes yes yes |
|
256 | 256 | sparserevlog: yes yes yes |
|
257 | 257 | persistent-nodemap: no no no (no-rust !) |
|
258 | 258 | persistent-nodemap: yes yes no (rust !) |
|
259 | 259 | copies-sdc: no no no |
|
260 | 260 | revlog-v2: no no no |
|
261 | 261 | changelog-v2: no no no |
|
262 | 262 | plain-cl-delta: yes yes yes |
|
263 | 263 | compression: zlib zlib zlib (no-zstd !) |
|
264 | 264 | compression: zlib zlib zstd (zstd !) |
|
265 | 265 | compression-level: default default default |
|
266 | 266 | $ hg debugformat --verbose --config format.usefncache=no --color=debug |
|
267 | 267 | format-variant repo config default |
|
268 | 268 | [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes] |
|
269 | 269 | [formatvariant.name.uptodate|dirstate-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] |
|
270 | 270 | [formatvariant.name.uptodate|tracked-hint: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] |
|
271 | 271 | [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes] |
|
272 | 272 | [formatvariant.name.uptodate|generaldelta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes] |
|
273 | 273 | [formatvariant.name.uptodate|share-safe: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes] |
|
274 | 274 | [formatvariant.name.uptodate|sparserevlog: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes] |
|
275 | 275 | [formatvariant.name.uptodate|persistent-nodemap:][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] (no-rust !) |
|
276 | 276 | [formatvariant.name.mismatchdefault|persistent-nodemap:][formatvariant.repo.mismatchdefault| yes][formatvariant.config.special| yes][formatvariant.default| no] (rust !) |
|
277 | 277 | [formatvariant.name.uptodate|copies-sdc: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] |
|
278 | 278 | [formatvariant.name.uptodate|revlog-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] |
|
279 | 279 | [formatvariant.name.uptodate|changelog-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] |
|
280 | 280 | [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes] |
|
281 | 281 | [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib] (no-zstd !) |
|
282 | 282 | [formatvariant.name.mismatchdefault|compression: ][formatvariant.repo.mismatchdefault| zlib][formatvariant.config.special| zlib][formatvariant.default| zstd] (zstd !) |
|
283 | 283 | [formatvariant.name.uptodate|compression-level: ][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default] |
|
284 | 284 | $ hg debugformat -Tjson |
|
285 | 285 | [ |
|
286 | 286 | { |
|
287 | 287 | "config": true, |
|
288 | 288 | "default": true, |
|
289 | 289 | "name": "fncache", |
|
290 | 290 | "repo": true |
|
291 | 291 | }, |
|
292 | 292 | { |
|
293 | 293 | "config": false, |
|
294 | 294 | "default": false, |
|
295 | 295 | "name": "dirstate-v2", |
|
296 | 296 | "repo": false |
|
297 | 297 | }, |
|
298 | 298 | { |
|
299 | 299 | "config": false, |
|
300 | 300 | "default": false, |
|
301 | 301 | "name": "tracked-hint", |
|
302 | 302 | "repo": false |
|
303 | 303 | }, |
|
304 | 304 | { |
|
305 | 305 | "config": true, |
|
306 | 306 | "default": true, |
|
307 | 307 | "name": "dotencode", |
|
308 | 308 | "repo": true |
|
309 | 309 | }, |
|
310 | 310 | { |
|
311 | 311 | "config": true, |
|
312 | 312 | "default": true, |
|
313 | 313 | "name": "generaldelta", |
|
314 | 314 | "repo": true |
|
315 | 315 | }, |
|
316 | 316 | { |
|
317 | 317 | "config": true, |
|
318 | 318 | "default": true, |
|
319 | 319 | "name": "share-safe", |
|
320 | 320 | "repo": true |
|
321 | 321 | }, |
|
322 | 322 | { |
|
323 | 323 | "config": true, |
|
324 | 324 | "default": true, |
|
325 | 325 | "name": "sparserevlog", |
|
326 | 326 | "repo": true |
|
327 | 327 | }, |
|
328 | 328 | { |
|
329 | 329 | "config": false, (no-rust !) |
|
330 | 330 | "config": true, (rust !) |
|
331 | 331 | "default": false, |
|
332 | 332 | "name": "persistent-nodemap", |
|
333 | 333 | "repo": false (no-rust !) |
|
334 | 334 | "repo": true (rust !) |
|
335 | 335 | }, |
|
336 | 336 | { |
|
337 | 337 | "config": false, |
|
338 | 338 | "default": false, |
|
339 | 339 | "name": "copies-sdc", |
|
340 | 340 | "repo": false |
|
341 | 341 | }, |
|
342 | 342 | { |
|
343 | 343 | "config": false, |
|
344 | 344 | "default": false, |
|
345 | 345 | "name": "revlog-v2", |
|
346 | 346 | "repo": false |
|
347 | 347 | }, |
|
348 | 348 | { |
|
349 | 349 | "config": false, |
|
350 | 350 | "default": false, |
|
351 | 351 | "name": "changelog-v2", |
|
352 | 352 | "repo": false |
|
353 | 353 | }, |
|
354 | 354 | { |
|
355 | 355 | "config": true, |
|
356 | 356 | "default": true, |
|
357 | 357 | "name": "plain-cl-delta", |
|
358 | 358 | "repo": true |
|
359 | 359 | }, |
|
360 | 360 | { |
|
361 | 361 | "config": "zlib", |
|
362 | 362 | "default": "zlib", (no-zstd !) |
|
363 | 363 | "default": "zstd", (zstd !) |
|
364 | 364 | "name": "compression", |
|
365 | 365 | "repo": "zlib" |
|
366 | 366 | }, |
|
367 | 367 | { |
|
368 | 368 | "config": "default", |
|
369 | 369 | "default": "default", |
|
370 | 370 | "name": "compression-level", |
|
371 | 371 | "repo": "default" |
|
372 | 372 | } |
|
373 | 373 | ] |
|
374 | 374 | $ hg debugupgraderepo |
|
375 | 375 | (no format upgrades found in existing repository) |
|
376 | 376 | performing an upgrade with "--run" will make the following changes: |
|
377 | 377 | |
|
378 | 378 | requirements |
|
379 | 379 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !) |
|
380 | 380 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !) |
|
381 | 381 | |
|
382 | 382 | no revlogs to process |
|
383 | 383 | |
|
384 | 384 | additional optimizations are available by specifying "--optimize <name>": |
|
385 | 385 | |
|
386 | 386 | re-delta-parent |
|
387 | 387 | deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower |
|
388 | 388 | |
|
389 | 389 | re-delta-multibase |
|
390 | 390 | deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges |
|
391 | 391 | |
|
392 | 392 | re-delta-all |
|
393 | 393 | deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed |
|
394 | 394 | |
|
395 | 395 | re-delta-fulladd |
|
396 | 396 | every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved. |
|
397 | 397 | |
|
398 | 398 | |
|
399 | 399 | $ hg debugupgraderepo --quiet |
|
400 | 400 | requirements |
|
401 | 401 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !) |
|
402 | 402 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !) |
|
403 | 403 | |
|
404 | 404 | no revlogs to process |
|
405 | 405 | |
|
406 | 406 | |
|
407 | 407 | --optimize can be used to add optimizations |
|
408 | 408 | |
|
409 | 409 | $ hg debugupgrade --optimize 're-delta-parent' |
|
410 | 410 | (no format upgrades found in existing repository) |
|
411 | 411 | performing an upgrade with "--run" will make the following changes: |
|
412 | 412 | |
|
413 | 413 | requirements |
|
414 | 414 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !) |
|
415 | 415 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !) |
|
416 | 416 | |
|
417 | 417 | optimisations: re-delta-parent |
|
418 | 418 | |
|
419 | 419 | re-delta-parent |
|
420 | 420 | deltas within internal storage will choose a new base revision if needed |
|
421 | 421 | |
|
422 | 422 | processed revlogs: |
|
423 | 423 | - all-filelogs |
|
424 | 424 | - changelog |
|
425 | 425 | - manifest |
|
426 | 426 | |
|
427 | 427 | additional optimizations are available by specifying "--optimize <name>": |
|
428 | 428 | |
|
429 | 429 | re-delta-multibase |
|
430 | 430 | deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges |
|
431 | 431 | |
|
432 | 432 | re-delta-all |
|
433 | 433 | deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed |
|
434 | 434 | |
|
435 | 435 | re-delta-fulladd |
|
436 | 436 | every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved. |
|
437 | 437 | |
|
438 | 438 | |
|
439 | 439 | modern form of the option |
|
440 | 440 | |
|
441 | 441 | $ hg debugupgrade --optimize re-delta-parent |
|
442 | 442 | (no format upgrades found in existing repository) |
|
443 | 443 | performing an upgrade with "--run" will make the following changes: |
|
444 | 444 | |
|
445 | 445 | requirements |
|
446 | 446 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !) |
|
447 | 447 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !) |
|
448 | 448 | |
|
449 | 449 | optimisations: re-delta-parent |
|
450 | 450 | |
|
451 | 451 | re-delta-parent |
|
452 | 452 | deltas within internal storage will choose a new base revision if needed |
|
453 | 453 | |
|
454 | 454 | processed revlogs: |
|
455 | 455 | - all-filelogs |
|
456 | 456 | - changelog |
|
457 | 457 | - manifest |
|
458 | 458 | |
|
459 | 459 | additional optimizations are available by specifying "--optimize <name>": |
|
460 | 460 | |
|
461 | 461 | re-delta-multibase |
|
462 | 462 | deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges |
|
463 | 463 | |
|
464 | 464 | re-delta-all |
|
465 | 465 | deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed |
|
466 | 466 | |
|
467 | 467 | re-delta-fulladd |
|
468 | 468 | every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved. |
|
469 | 469 | |
|
470 | 470 | |
|
471 | 471 | $ hg debugupgrade --optimize re-delta-parent --quiet |
|
472 | 472 | requirements |
|
473 | 473 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !) |
|
474 | 474 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !) |
|
475 | 475 | |
|
476 | 476 | optimisations: re-delta-parent |
|
477 | 477 | |
|
478 | 478 | processed revlogs: |
|
479 | 479 | - all-filelogs |
|
480 | 480 | - changelog |
|
481 | 481 | - manifest |
|
482 | 482 | |
|
483 | 483 | |
|
484 | 484 | passing multiple optimization: |
|
485 | 485 | |
|
486 | 486 | $ hg debugupgrade --optimize re-delta-parent --optimize re-delta-multibase --quiet |
|
487 | 487 | requirements |
|
488 | 488 | preserved: * (glob) |
|
489 | 489 | |
|
490 | 490 | optimisations: re-delta-multibase, re-delta-parent |
|
491 | 491 | |
|
492 | 492 | processed revlogs: |
|
493 | 493 | - all-filelogs |
|
494 | 494 | - changelog |
|
495 | 495 | - manifest |
|
496 | 496 | |
|
497 | 497 | |
|
498 | 498 | unknown optimization: |
|
499 | 499 | |
|
500 | 500 | $ hg debugupgrade --optimize foobar |
|
501 | 501 | abort: unknown optimization action requested: foobar |
|
502 | 502 | (run without arguments to see valid optimizations) |
|
503 | 503 | [255] |
|
504 | 504 | |
|
505 | 505 | Various sub-optimal detections work |
|
506 | 506 | |
|
507 | 507 | $ cat > .hg/requires << EOF |
|
508 | 508 | > revlogv1 |
|
509 | 509 | > store |
|
510 | 510 | > EOF |
|
511 | 511 | |
|
512 | 512 | $ hg debugformat |
|
513 | 513 | format-variant repo |
|
514 | 514 | fncache: no |
|
515 | 515 | dirstate-v2: no |
|
516 | 516 | tracked-hint: no |
|
517 | 517 | dotencode: no |
|
518 | 518 | generaldelta: no |
|
519 | 519 | share-safe: no |
|
520 | 520 | sparserevlog: no |
|
521 | 521 | persistent-nodemap: no |
|
522 | 522 | copies-sdc: no |
|
523 | 523 | revlog-v2: no |
|
524 | 524 | changelog-v2: no |
|
525 | 525 | plain-cl-delta: yes |
|
526 | 526 | compression: zlib |
|
527 | 527 | compression-level: default |
|
528 | 528 | $ hg debugformat --verbose |
|
529 | 529 | format-variant repo config default |
|
530 | 530 | fncache: no yes yes |
|
531 | 531 | dirstate-v2: no no no |
|
532 | 532 | tracked-hint: no no no |
|
533 | 533 | dotencode: no yes yes |
|
534 | 534 | generaldelta: no yes yes |
|
535 | 535 | share-safe: no yes yes |
|
536 | 536 | sparserevlog: no yes yes |
|
537 | 537 | persistent-nodemap: no no no (no-rust !) |
|
538 | 538 | persistent-nodemap: no yes no (rust !) |
|
539 | 539 | copies-sdc: no no no |
|
540 | 540 | revlog-v2: no no no |
|
541 | 541 | changelog-v2: no no no |
|
542 | 542 | plain-cl-delta: yes yes yes |
|
543 | 543 | compression: zlib zlib zlib (no-zstd !) |
|
544 | 544 | compression: zlib zlib zstd (zstd !) |
|
545 | 545 | compression-level: default default default |
|
546 | 546 | $ hg debugformat --verbose --config format.usegeneraldelta=no |
|
547 | 547 | format-variant repo config default |
|
548 | 548 | fncache: no yes yes |
|
549 | 549 | dirstate-v2: no no no |
|
550 | 550 | tracked-hint: no no no |
|
551 | 551 | dotencode: no yes yes |
|
552 | 552 | generaldelta: no no yes |
|
553 | 553 | share-safe: no yes yes |
|
554 | 554 | sparserevlog: no no yes |
|
555 | 555 | persistent-nodemap: no no no (no-rust !) |
|
556 | 556 | persistent-nodemap: no yes no (rust !) |
|
557 | 557 | copies-sdc: no no no |
|
558 | 558 | revlog-v2: no no no |
|
559 | 559 | changelog-v2: no no no |
|
560 | 560 | plain-cl-delta: yes yes yes |
|
561 | 561 | compression: zlib zlib zlib (no-zstd !) |
|
562 | 562 | compression: zlib zlib zstd (zstd !) |
|
563 | 563 | compression-level: default default default |
|
564 | 564 | $ hg debugformat --verbose --config format.usegeneraldelta=no --color=debug |
|
565 | 565 | format-variant repo config default |
|
566 | 566 | [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes] |
|
567 | 567 | [formatvariant.name.uptodate|dirstate-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] |
|
568 | 568 | [formatvariant.name.uptodate|tracked-hint: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] |
|
569 | 569 | [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes] |
|
570 | 570 | [formatvariant.name.mismatchdefault|generaldelta: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes] |
|
571 | 571 | [formatvariant.name.mismatchconfig|share-safe: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes] |
|
572 | 572 | [formatvariant.name.mismatchdefault|sparserevlog: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes] |
|
573 | 573 | [formatvariant.name.uptodate|persistent-nodemap:][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] (no-rust !) |
|
574 | 574 | [formatvariant.name.mismatchconfig|persistent-nodemap:][formatvariant.repo.mismatchconfig| no][formatvariant.config.special| yes][formatvariant.default| no] (rust !) |
|
575 | 575 | [formatvariant.name.uptodate|copies-sdc: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] |
|
576 | 576 | [formatvariant.name.uptodate|revlog-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] |
|
577 | 577 | [formatvariant.name.uptodate|changelog-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] |
|
578 | 578 | [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes] |
|
579 | 579 | [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib] (no-zstd !) |
|
580 | 580 | [formatvariant.name.mismatchdefault|compression: ][formatvariant.repo.mismatchdefault| zlib][formatvariant.config.special| zlib][formatvariant.default| zstd] (zstd !) |
|
581 | 581 | [formatvariant.name.uptodate|compression-level: ][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default] |
|
582 | 582 | $ hg debugupgraderepo |
|
583 | 583 | note: selecting all-filelogs for processing to change: dotencode |
|
584 | 584 | note: selecting all-manifestlogs for processing to change: dotencode |
|
585 | 585 | note: selecting changelog for processing to change: dotencode |
|
586 | 586 | |
|
587 | 587 | repository lacks features recommended by current config options: |
|
588 | 588 | |
|
589 | 589 | fncache |
|
590 | 590 | long and reserved filenames may not work correctly; repository performance is sub-optimal |
|
591 | 591 | |
|
592 | 592 | dotencode |
|
593 | 593 | storage of filenames beginning with a period or space may not work correctly |
|
594 | 594 | |
|
595 | 595 | generaldelta |
|
596 | 596 | deltas within internal storage are unable to choose optimal revisions; repository is larger and slower than it could be; interaction with other repositories may require extra network and CPU resources, making "hg push" and "hg pull" slower |
|
597 | 597 | |
|
598 | 598 | share-safe |
|
599 | 599 | old shared repositories do not share source repository requirements and config. This leads to various problems when the source repository format is upgraded or some new extensions are enabled. |
|
600 | 600 | |
|
601 | 601 | sparserevlog |
|
602 | 602 | in order to limit disk reading and memory usage on older version, the span of a delta chain from its root to its end is limited, whatever the relevant data in this span. This can severly limit Mercurial ability to build good chain of delta resulting is much more storage space being taken and limit reusability of on disk delta during exchange. |
|
603 | 603 | |
|
604 | 604 | persistent-nodemap (rust !) |
|
605 | 605 | persist the node -> rev mapping on disk to speedup lookup (rust !) |
|
606 | 606 | (rust !) |
|
607 | 607 | |
|
608 | 608 | performing an upgrade with "--run" will make the following changes: |
|
609 | 609 | |
|
610 | 610 | requirements |
|
611 | 611 | preserved: revlogv1, store |
|
612 | 612 | added: dotencode, fncache, generaldelta, share-safe, sparserevlog (no-rust !) |
|
613 | 613 | added: dotencode, fncache, generaldelta, persistent-nodemap, share-safe, sparserevlog (rust !) |
|
614 | 614 | |
|
615 | 615 | fncache |
|
616 | 616 | repository will be more resilient to storing certain paths and performance of certain operations should be improved |
|
617 | 617 | |
|
618 | 618 | dotencode |
|
619 | 619 | repository will be better able to store files beginning with a space or period |
|
620 | 620 | |
|
621 | 621 | generaldelta |
|
622 | 622 | repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster |
|
623 | 623 | |
|
624 | 624 | share-safe |
|
625 | 625 | Upgrades a repository to share-safe format so that future shares of this repository share its requirements and configs. |
|
626 | 626 | |
|
627 | 627 | sparserevlog |
|
628 | 628 | Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server. |
|
629 | 629 | |
|
630 | 630 | persistent-nodemap (rust !) |
|
631 | 631 | Speedup revision lookup by node id. (rust !) |
|
632 | 632 | (rust !) |
|
633 | 633 | processed revlogs: |
|
634 | 634 | - all-filelogs |
|
635 | 635 | - changelog |
|
636 | 636 | - manifest |
|
637 | 637 | |
|
638 | 638 | additional optimizations are available by specifying "--optimize <name>": |
|
639 | 639 | |
|
640 | 640 | re-delta-parent |
|
641 | 641 | deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower |
|
642 | 642 | |
|
643 | 643 | re-delta-multibase |
|
644 | 644 | deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges |
|
645 | 645 | |
|
646 | 646 | re-delta-all |
|
647 | 647 | deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed |
|
648 | 648 | |
|
649 | 649 | re-delta-fulladd |
|
650 | 650 | every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved. |
|
651 | 651 | |
|
652 | 652 | $ hg debugupgraderepo --quiet |
|
653 | 653 | requirements |
|
654 | 654 | preserved: revlogv1, store |
|
655 | 655 | added: dotencode, fncache, generaldelta, share-safe, sparserevlog (no-rust !) |
|
656 | 656 | added: dotencode, fncache, generaldelta, persistent-nodemap, share-safe, sparserevlog (rust !) |
|
657 | 657 | |
|
658 | 658 | processed revlogs: |
|
659 | 659 | - all-filelogs |
|
660 | 660 | - changelog |
|
661 | 661 | - manifest |
|
662 | 662 | |
|
663 | 663 | |
|
664 | 664 | $ hg --config format.dotencode=false debugupgraderepo |
|
665 | 665 | note: selecting all-filelogs for processing to change: fncache |
|
666 | 666 | note: selecting all-manifestlogs for processing to change: fncache |
|
667 | 667 | note: selecting changelog for processing to change: fncache |
|
668 | 668 | |
|
669 | 669 | repository lacks features recommended by current config options: |
|
670 | 670 | |
|
671 | 671 | fncache |
|
672 | 672 | long and reserved filenames may not work correctly; repository performance is sub-optimal |
|
673 | 673 | |
|
674 | 674 | generaldelta |
|
675 | 675 | deltas within internal storage are unable to choose optimal revisions; repository is larger and slower than it could be; interaction with other repositories may require extra network and CPU resources, making "hg push" and "hg pull" slower |
|
676 | 676 | |
|
677 | 677 | share-safe |
|
678 | 678 | old shared repositories do not share source repository requirements and config. This leads to various problems when the source repository format is upgraded or some new extensions are enabled. |
|
679 | 679 | |
|
680 | 680 | sparserevlog |
|
681 | 681 | in order to limit disk reading and memory usage on older version, the span of a delta chain from its root to its end is limited, whatever the relevant data in this span. This can severly limit Mercurial ability to build good chain of delta resulting is much more storage space being taken and limit reusability of on disk delta during exchange. |
|
682 | 682 | |
|
683 | 683 | persistent-nodemap (rust !) |
|
684 | 684 | persist the node -> rev mapping on disk to speedup lookup (rust !) |
|
685 | 685 | (rust !) |
|
686 | 686 | repository lacks features used by the default config options: |
|
687 | 687 | |
|
688 | 688 | dotencode |
|
689 | 689 | storage of filenames beginning with a period or space may not work correctly |
|
690 | 690 | |
|
691 | 691 | |
|
692 | 692 | performing an upgrade with "--run" will make the following changes: |
|
693 | 693 | |
|
694 | 694 | requirements |
|
695 | 695 | preserved: revlogv1, store |
|
696 | 696 | added: fncache, generaldelta, share-safe, sparserevlog (no-rust !) |
|
697 | 697 | added: fncache, generaldelta, persistent-nodemap, share-safe, sparserevlog (rust !) |
|
698 | 698 | |
|
699 | 699 | fncache |
|
700 | 700 | repository will be more resilient to storing certain paths and performance of certain operations should be improved |
|
701 | 701 | |
|
702 | 702 | generaldelta |
|
703 | 703 | repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster |
|
704 | 704 | |
|
705 | 705 | share-safe |
|
706 | 706 | Upgrades a repository to share-safe format so that future shares of this repository share its requirements and configs. |
|
707 | 707 | |
|
708 | 708 | sparserevlog |
|
709 | 709 | Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server. |
|
710 | 710 | |
|
711 | 711 | persistent-nodemap (rust !) |
|
712 | 712 | Speedup revision lookup by node id. (rust !) |
|
713 | 713 | (rust !) |
|
714 | 714 | processed revlogs: |
|
715 | 715 | - all-filelogs |
|
716 | 716 | - changelog |
|
717 | 717 | - manifest |
|
718 | 718 | |
|
719 | 719 | additional optimizations are available by specifying "--optimize <name>": |
|
720 | 720 | |
|
721 | 721 | re-delta-parent |
|
722 | 722 | deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower |
|
723 | 723 | |
|
724 | 724 | re-delta-multibase |
|
725 | 725 | deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges |
|
726 | 726 | |
|
727 | 727 | re-delta-all |
|
728 | 728 | deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed |
|
729 | 729 | |
|
730 | 730 | re-delta-fulladd |
|
731 | 731 | every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved. |
|
732 | 732 | |
|
733 | 733 | |
|
734 | 734 | $ cd .. |
|
735 | 735 | |
|
736 | 736 | Upgrading a repository that is already modern essentially no-ops |
|
737 | 737 | |
|
738 | 738 | $ hg init modern |
|
739 | 739 | $ hg -R modern debugupgraderepo --run |
|
740 | 740 | nothing to do |
|
741 | 741 | |
|
742 | 742 | Upgrading a repository to generaldelta works |
|
743 | 743 | |
|
744 | 744 | $ hg --config format.usegeneraldelta=false init upgradegd |
|
745 | 745 | $ cd upgradegd |
|
746 | 746 | $ touch f0 |
|
747 | 747 | $ hg -q commit -A -m initial |
|
748 | 748 | $ mkdir FooBarDirectory.d |
|
749 | 749 | $ touch FooBarDirectory.d/f1 |
|
750 | 750 | $ hg -q commit -A -m 'add f1' |
|
751 | 751 | $ hg -q up -r 0 |
|
752 | 752 | >>> import random |
|
753 | 753 | >>> random.seed(0) # have a reproducible content |
|
754 | 754 | >>> with open("f2", "wb") as f: |
|
755 | 755 | ... for i in range(100000): |
|
756 | 756 | ... f.write(b"%d\n" % random.randint(1000000000, 9999999999)) and None |
|
757 | 757 | $ hg -q commit -A -m 'add f2' |
|
758 | 758 | |
|
759 | 759 | make sure we have a .d file |
|
760 | 760 | |
|
761 | 761 | $ ls -d .hg/store/data/* |
|
762 | 762 | .hg/store/data/_foo_bar_directory.d.hg |
|
763 | 763 | .hg/store/data/f0.i |
|
764 | 764 | .hg/store/data/f2.d |
|
765 | 765 | .hg/store/data/f2.i |
|
766 | 766 | |
|
767 | 767 | $ hg debugupgraderepo --run --config format.sparse-revlog=false |
|
768 | 768 | note: selecting all-filelogs for processing to change: generaldelta |
|
769 | 769 | note: selecting all-manifestlogs for processing to change: generaldelta |
|
770 | 770 | note: selecting changelog for processing to change: generaldelta |
|
771 | 771 | |
|
772 | 772 | upgrade will perform the following actions: |
|
773 | 773 | |
|
774 | 774 | requirements |
|
775 | 775 | preserved: dotencode, fncache, revlogv1, share-safe, store (no-rust !) |
|
776 | 776 | preserved: dotencode, fncache, persistent-nodemap, revlogv1, share-safe, store (rust !) |
|
777 | 777 | added: generaldelta |
|
778 | 778 | |
|
779 | 779 | generaldelta |
|
780 | 780 | repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster |
|
781 | 781 | |
|
782 | 782 | processed revlogs: |
|
783 | 783 | - all-filelogs |
|
784 | 784 | - changelog |
|
785 | 785 | - manifest |
|
786 | 786 | |
|
787 | 787 | beginning upgrade... |
|
788 | 788 | repository locked and read-only |
|
789 | 789 | creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
790 | 790 | (it is safe to interrupt this process any time before data migration completes) |
|
791 | 791 | migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog) |
|
792 | 792 | migrating 519 KB in store; 1.05 MB tracked data |
|
793 | 793 | migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data) |
|
794 | 794 | finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes |
|
795 | 795 | migrating 1 manifests containing 3 revisions (384 bytes in store; 238 bytes tracked data) |
|
796 | 796 | finished migrating 3 manifest revisions across 1 manifests; change in size: -17 bytes |
|
797 | 797 | migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data) |
|
798 | 798 | finished migrating 3 changelog revisions; change in size: 0 bytes |
|
799 | 799 | finished migrating 9 total revisions; total change in store size: -17 bytes |
|
800 | 800 | copying phaseroots |
|
801 | 801 | copying requires |
|
802 | 802 | data fully upgraded in a temporary repository |
|
803 | 803 | marking source repository as being upgraded; clients will be unable to read from repository |
|
804 | 804 | starting in-place swap of repository data |
|
805 | 805 | replaced files will be backed up at $TESTTMP/upgradegd/.hg/upgradebackup.* (glob) |
|
806 | 806 | replacing store... |
|
807 | 807 | store replacement complete; repository was inconsistent for *s (glob) |
|
808 | 808 | finalizing requirements file and making repository readable again |
|
809 | 809 | removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
810 | 810 | copy of old repository backed up at $TESTTMP/upgradegd/.hg/upgradebackup.* (glob) |
|
811 | 811 | the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified |
|
812 | 812 | |
|
813 | 813 | Original requirements backed up |
|
814 | 814 | |
|
815 | 815 | $ cat .hg/upgradebackup.*/requires |
|
816 | 816 | share-safe |
|
817 | 817 | $ cat .hg/upgradebackup.*/store/requires |
|
818 | 818 | dotencode |
|
819 | 819 | fncache |
|
820 | 820 | persistent-nodemap (rust !) |
|
821 | 821 | revlogv1 |
|
822 | 822 | store |
|
823 | 823 | upgradeinprogress |
|
824 | 824 | |
|
825 | 825 | generaldelta added to original requirements files |
|
826 | 826 | |
|
827 | 827 | $ hg debugrequires |
|
828 | 828 | dotencode |
|
829 | 829 | fncache |
|
830 | 830 | generaldelta |
|
831 | 831 | persistent-nodemap (rust !) |
|
832 | 832 | revlogv1 |
|
833 | 833 | share-safe |
|
834 | 834 | store |
|
835 | 835 | |
|
836 | 836 | store directory has files we expect |
|
837 | 837 | |
|
838 | 838 | $ ls .hg/store |
|
839 | 839 | 00changelog.i |
|
840 | 840 | 00manifest.i |
|
841 | 841 | data |
|
842 | 842 | fncache |
|
843 | 843 | phaseroots |
|
844 | 844 | requires |
|
845 | 845 | undo |
|
846 | 846 | undo.backupfiles |
|
847 | 847 | |
|
848 | 848 | manifest should be generaldelta |
|
849 | 849 | |
|
850 | 850 | $ hg debugrevlog -m | grep flags |
|
851 | 851 | flags : inline, generaldelta |
|
852 | 852 | |
|
853 | 853 | verify should be happy |
|
854 | 854 | |
|
855 | 855 | $ hg verify -q |
|
856 | 856 | |
|
857 | 857 | old store should be backed up |
|
858 | 858 | |
|
859 | 859 | $ ls -d .hg/upgradebackup.*/ |
|
860 | 860 | .hg/upgradebackup.*/ (glob) |
|
861 | 861 | $ ls .hg/upgradebackup.*/store |
|
862 | 862 | 00changelog.i |
|
863 | 863 | 00manifest.i |
|
864 | 864 | data |
|
865 | 865 | fncache |
|
866 | 866 | phaseroots |
|
867 | 867 | requires |
|
868 | 868 | undo |
|
869 | undo.backup.fncache | |
|
869 | undo.backup.fncache.bck | |
|
870 | 870 | undo.backupfiles |
|
871 | 871 | |
|
872 | 872 | unless --no-backup is passed |
|
873 | 873 | |
|
874 | 874 | $ rm -rf .hg/upgradebackup.*/ |
|
875 | 875 | $ hg debugupgraderepo --run --no-backup |
|
876 | 876 | note: selecting all-filelogs for processing to change: sparserevlog |
|
877 | 877 | note: selecting all-manifestlogs for processing to change: sparserevlog |
|
878 | 878 | note: selecting changelog for processing to change: sparserevlog |
|
879 | 879 | |
|
880 | 880 | upgrade will perform the following actions: |
|
881 | 881 | |
|
882 | 882 | requirements |
|
883 | 883 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, store (no-rust !) |
|
884 | 884 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, store (rust !) |
|
885 | 885 | added: sparserevlog |
|
886 | 886 | |
|
887 | 887 | sparserevlog |
|
888 | 888 | Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server. |
|
889 | 889 | |
|
890 | 890 | processed revlogs: |
|
891 | 891 | - all-filelogs |
|
892 | 892 | - changelog |
|
893 | 893 | - manifest |
|
894 | 894 | |
|
895 | 895 | beginning upgrade... |
|
896 | 896 | repository locked and read-only |
|
897 | 897 | creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
898 | 898 | (it is safe to interrupt this process any time before data migration completes) |
|
899 | 899 | migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog) |
|
900 | 900 | migrating 519 KB in store; 1.05 MB tracked data |
|
901 | 901 | migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data) |
|
902 | 902 | finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes |
|
903 | 903 | migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data) |
|
904 | 904 | finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes |
|
905 | 905 | migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data) |
|
906 | 906 | finished migrating 3 changelog revisions; change in size: 0 bytes |
|
907 | 907 | finished migrating 9 total revisions; total change in store size: 0 bytes |
|
908 | 908 | copying phaseroots |
|
909 | 909 | copying requires |
|
910 | 910 | data fully upgraded in a temporary repository |
|
911 | 911 | marking source repository as being upgraded; clients will be unable to read from repository |
|
912 | 912 | starting in-place swap of repository data |
|
913 | 913 | replacing store... |
|
914 | 914 | store replacement complete; repository was inconsistent for * (glob) |
|
915 | 915 | finalizing requirements file and making repository readable again |
|
916 | 916 | removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
917 | 917 | $ ls -1 .hg/ | grep upgradebackup |
|
918 | 918 | [1] |
|
919 | 919 | |
|
920 | 920 | We can restrict optimization to some revlog: |
|
921 | 921 | |
|
922 | 922 | $ hg debugupgrade --optimize re-delta-parent --run --manifest --no-backup --debug --traceback |
|
923 | 923 | upgrade will perform the following actions: |
|
924 | 924 | |
|
925 | 925 | requirements |
|
926 | 926 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !) |
|
927 | 927 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !) |
|
928 | 928 | |
|
929 | 929 | optimisations: re-delta-parent |
|
930 | 930 | |
|
931 | 931 | re-delta-parent |
|
932 | 932 | deltas within internal storage will choose a new base revision if needed |
|
933 | 933 | |
|
934 | 934 | processed revlogs: |
|
935 | 935 | - manifest |
|
936 | 936 | |
|
937 | 937 | beginning upgrade... |
|
938 | 938 | repository locked and read-only |
|
939 | 939 | creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
940 | 940 | (it is safe to interrupt this process any time before data migration completes) |
|
941 | 941 | migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog) |
|
942 | 942 | migrating 519 KB in store; 1.05 MB tracked data |
|
943 | 943 | migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data) |
|
944 | 944 | blindly copying data/FooBarDirectory.d/f1.i containing 1 revisions |
|
945 | 945 | blindly copying data/f0.i containing 1 revisions |
|
946 | 946 | blindly copying data/f2.i containing 1 revisions |
|
947 | 947 | finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes |
|
948 | 948 | migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data) |
|
949 | 949 | cloning 3 revisions from 00manifest.i |
|
950 | 950 | finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes |
|
951 | 951 | migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data) |
|
952 | 952 | blindly copying 00changelog.i containing 3 revisions |
|
953 | 953 | finished migrating 3 changelog revisions; change in size: 0 bytes |
|
954 | 954 | finished migrating 9 total revisions; total change in store size: 0 bytes |
|
955 | 955 | copying phaseroots |
|
956 | 956 | copying requires |
|
957 | 957 | data fully upgraded in a temporary repository |
|
958 | 958 | marking source repository as being upgraded; clients will be unable to read from repository |
|
959 | 959 | starting in-place swap of repository data |
|
960 | 960 | replacing store... |
|
961 | 961 | store replacement complete; repository was inconsistent for *s (glob) |
|
962 | 962 | finalizing requirements file and making repository readable again |
|
963 | 963 | removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
964 | 964 | |
|
965 | 965 | Check that the repo still works fine |
|
966 | 966 | |
|
967 | 967 | $ hg log -G --stat |
|
968 | 968 | @ changeset: 2:fca376863211 |
|
969 | 969 | | tag: tip |
|
970 | 970 | | parent: 0:ba592bf28da2 |
|
971 | 971 | | user: test |
|
972 | 972 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
973 | 973 | | summary: add f2 |
|
974 | 974 | | |
|
975 | 975 | | f2 | 100000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
976 | 976 | | 1 files changed, 100000 insertions(+), 0 deletions(-) |
|
977 | 977 | | |
|
978 | 978 | | o changeset: 1:2029ce2354e2 |
|
979 | 979 | |/ user: test |
|
980 | 980 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
981 | 981 | | summary: add f1 |
|
982 | 982 | | |
|
983 | 983 | | |
|
984 | 984 | o changeset: 0:ba592bf28da2 |
|
985 | 985 | user: test |
|
986 | 986 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
987 | 987 | summary: initial |
|
988 | 988 | |
|
989 | 989 | |
|
990 | 990 | |
|
991 | 991 | $ hg verify -q |
|
992 | 992 | |
|
993 | 993 | Check we can select negatively |
|
994 | 994 | |
|
995 | 995 | $ hg debugupgrade --optimize re-delta-parent --run --no-manifest --no-backup --debug --traceback |
|
996 | 996 | upgrade will perform the following actions: |
|
997 | 997 | |
|
998 | 998 | requirements |
|
999 | 999 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !) |
|
1000 | 1000 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !) |
|
1001 | 1001 | |
|
1002 | 1002 | optimisations: re-delta-parent |
|
1003 | 1003 | |
|
1004 | 1004 | re-delta-parent |
|
1005 | 1005 | deltas within internal storage will choose a new base revision if needed |
|
1006 | 1006 | |
|
1007 | 1007 | processed revlogs: |
|
1008 | 1008 | - all-filelogs |
|
1009 | 1009 | - changelog |
|
1010 | 1010 | |
|
1011 | 1011 | beginning upgrade... |
|
1012 | 1012 | repository locked and read-only |
|
1013 | 1013 | creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
1014 | 1014 | (it is safe to interrupt this process any time before data migration completes) |
|
1015 | 1015 | migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog) |
|
1016 | 1016 | migrating 519 KB in store; 1.05 MB tracked data |
|
1017 | 1017 | migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data) |
|
1018 | 1018 | cloning 1 revisions from data/FooBarDirectory.d/f1.i |
|
1019 | 1019 | cloning 1 revisions from data/f0.i |
|
1020 | 1020 | cloning 1 revisions from data/f2.i |
|
1021 | 1021 | finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes |
|
1022 | 1022 | migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data) |
|
1023 | 1023 | blindly copying 00manifest.i containing 3 revisions |
|
1024 | 1024 | finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes |
|
1025 | 1025 | migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data) |
|
1026 | 1026 | cloning 3 revisions from 00changelog.i |
|
1027 | 1027 | finished migrating 3 changelog revisions; change in size: 0 bytes |
|
1028 | 1028 | finished migrating 9 total revisions; total change in store size: 0 bytes |
|
1029 | 1029 | copying phaseroots |
|
1030 | 1030 | copying requires |
|
1031 | 1031 | data fully upgraded in a temporary repository |
|
1032 | 1032 | marking source repository as being upgraded; clients will be unable to read from repository |
|
1033 | 1033 | starting in-place swap of repository data |
|
1034 | 1034 | replacing store... |
|
1035 | 1035 | store replacement complete; repository was inconsistent for *s (glob) |
|
1036 | 1036 | finalizing requirements file and making repository readable again |
|
1037 | 1037 | removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
1038 | 1038 | $ hg verify -q |
|
1039 | 1039 | |
|
1040 | 1040 | Check that we can select changelog only |
|
1041 | 1041 | |
|
1042 | 1042 | $ hg debugupgrade --optimize re-delta-parent --run --changelog --no-backup --debug --traceback |
|
1043 | 1043 | upgrade will perform the following actions: |
|
1044 | 1044 | |
|
1045 | 1045 | requirements |
|
1046 | 1046 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !) |
|
1047 | 1047 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !) |
|
1048 | 1048 | |
|
1049 | 1049 | optimisations: re-delta-parent |
|
1050 | 1050 | |
|
1051 | 1051 | re-delta-parent |
|
1052 | 1052 | deltas within internal storage will choose a new base revision if needed |
|
1053 | 1053 | |
|
1054 | 1054 | processed revlogs: |
|
1055 | 1055 | - changelog |
|
1056 | 1056 | |
|
1057 | 1057 | beginning upgrade... |
|
1058 | 1058 | repository locked and read-only |
|
1059 | 1059 | creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
1060 | 1060 | (it is safe to interrupt this process any time before data migration completes) |
|
1061 | 1061 | migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog) |
|
1062 | 1062 | migrating 519 KB in store; 1.05 MB tracked data |
|
1063 | 1063 | migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data) |
|
1064 | 1064 | blindly copying data/FooBarDirectory.d/f1.i containing 1 revisions |
|
1065 | 1065 | blindly copying data/f0.i containing 1 revisions |
|
1066 | 1066 | blindly copying data/f2.i containing 1 revisions |
|
1067 | 1067 | finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes |
|
1068 | 1068 | migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data) |
|
1069 | 1069 | blindly copying 00manifest.i containing 3 revisions |
|
1070 | 1070 | finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes |
|
1071 | 1071 | migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data) |
|
1072 | 1072 | cloning 3 revisions from 00changelog.i |
|
1073 | 1073 | finished migrating 3 changelog revisions; change in size: 0 bytes |
|
1074 | 1074 | finished migrating 9 total revisions; total change in store size: 0 bytes |
|
1075 | 1075 | copying phaseroots |
|
1076 | 1076 | copying requires |
|
1077 | 1077 | data fully upgraded in a temporary repository |
|
1078 | 1078 | marking source repository as being upgraded; clients will be unable to read from repository |
|
1079 | 1079 | starting in-place swap of repository data |
|
1080 | 1080 | replacing store... |
|
1081 | 1081 | store replacement complete; repository was inconsistent for *s (glob) |
|
1082 | 1082 | finalizing requirements file and making repository readable again |
|
1083 | 1083 | removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
1084 | 1084 | $ hg verify -q |
|
1085 | 1085 | |
|
1086 | 1086 | Check that we can select filelog only |
|
1087 | 1087 | |
|
1088 | 1088 | $ hg debugupgrade --optimize re-delta-parent --run --no-changelog --no-manifest --no-backup --debug --traceback |
|
1089 | 1089 | upgrade will perform the following actions: |
|
1090 | 1090 | |
|
1091 | 1091 | requirements |
|
1092 | 1092 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !) |
|
1093 | 1093 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !) |
|
1094 | 1094 | |
|
1095 | 1095 | optimisations: re-delta-parent |
|
1096 | 1096 | |
|
1097 | 1097 | re-delta-parent |
|
1098 | 1098 | deltas within internal storage will choose a new base revision if needed |
|
1099 | 1099 | |
|
1100 | 1100 | processed revlogs: |
|
1101 | 1101 | - all-filelogs |
|
1102 | 1102 | |
|
1103 | 1103 | beginning upgrade... |
|
1104 | 1104 | repository locked and read-only |
|
1105 | 1105 | creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
1106 | 1106 | (it is safe to interrupt this process any time before data migration completes) |
|
1107 | 1107 | migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog) |
|
1108 | 1108 | migrating 519 KB in store; 1.05 MB tracked data |
|
1109 | 1109 | migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data) |
|
1110 | 1110 | cloning 1 revisions from data/FooBarDirectory.d/f1.i |
|
1111 | 1111 | cloning 1 revisions from data/f0.i |
|
1112 | 1112 | cloning 1 revisions from data/f2.i |
|
1113 | 1113 | finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes |
|
1114 | 1114 | migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data) |
|
1115 | 1115 | blindly copying 00manifest.i containing 3 revisions |
|
1116 | 1116 | finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes |
|
1117 | 1117 | migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data) |
|
1118 | 1118 | blindly copying 00changelog.i containing 3 revisions |
|
1119 | 1119 | finished migrating 3 changelog revisions; change in size: 0 bytes |
|
1120 | 1120 | finished migrating 9 total revisions; total change in store size: 0 bytes |
|
1121 | 1121 | copying phaseroots |
|
1122 | 1122 | copying requires |
|
1123 | 1123 | data fully upgraded in a temporary repository |
|
1124 | 1124 | marking source repository as being upgraded; clients will be unable to read from repository |
|
1125 | 1125 | starting in-place swap of repository data |
|
1126 | 1126 | replacing store... |
|
1127 | 1127 | store replacement complete; repository was inconsistent for *s (glob) |
|
1128 | 1128 | finalizing requirements file and making repository readable again |
|
1129 | 1129 | removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
1130 | 1130 | $ hg verify -q |
|
1131 | 1131 | |
|
1132 | 1132 | |
|
1133 | 1133 | Check you can't skip revlog clone during important format downgrade |
|
1134 | 1134 | |
|
1135 | 1135 | $ echo "[format]" > .hg/hgrc |
|
1136 | 1136 | $ echo "sparse-revlog=no" >> .hg/hgrc |
|
1137 | 1137 | $ hg debugupgrade --optimize re-delta-parent --no-manifest --no-backup --quiet |
|
1138 | 1138 | warning: ignoring --no-manifest, as upgrade is changing: sparserevlog |
|
1139 | 1139 | |
|
1140 | 1140 | requirements |
|
1141 | 1141 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, store (no-rust !) |
|
1142 | 1142 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, store (rust !) |
|
1143 | 1143 | removed: sparserevlog |
|
1144 | 1144 | |
|
1145 | 1145 | optimisations: re-delta-parent |
|
1146 | 1146 | |
|
1147 | 1147 | processed revlogs: |
|
1148 | 1148 | - all-filelogs |
|
1149 | 1149 | - changelog |
|
1150 | 1150 | - manifest |
|
1151 | 1151 | |
|
1152 | 1152 | $ hg debugupgrade --optimize re-delta-parent --run --manifest --no-backup --debug --traceback |
|
1153 | 1153 | note: selecting all-filelogs for processing to change: sparserevlog |
|
1154 | 1154 | note: selecting changelog for processing to change: sparserevlog |
|
1155 | 1155 | |
|
1156 | 1156 | upgrade will perform the following actions: |
|
1157 | 1157 | |
|
1158 | 1158 | requirements |
|
1159 | 1159 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, store (no-rust !) |
|
1160 | 1160 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, store (rust !) |
|
1161 | 1161 | removed: sparserevlog |
|
1162 | 1162 | |
|
1163 | 1163 | optimisations: re-delta-parent |
|
1164 | 1164 | |
|
1165 | 1165 | re-delta-parent |
|
1166 | 1166 | deltas within internal storage will choose a new base revision if needed |
|
1167 | 1167 | |
|
1168 | 1168 | processed revlogs: |
|
1169 | 1169 | - all-filelogs |
|
1170 | 1170 | - changelog |
|
1171 | 1171 | - manifest |
|
1172 | 1172 | |
|
1173 | 1173 | beginning upgrade... |
|
1174 | 1174 | repository locked and read-only |
|
1175 | 1175 | creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
1176 | 1176 | (it is safe to interrupt this process any time before data migration completes) |
|
1177 | 1177 | migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog) |
|
1178 | 1178 | migrating 519 KB in store; 1.05 MB tracked data |
|
1179 | 1179 | migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data) |
|
1180 | 1180 | cloning 1 revisions from data/FooBarDirectory.d/f1.i |
|
1181 | 1181 | cloning 1 revisions from data/f0.i |
|
1182 | 1182 | cloning 1 revisions from data/f2.i |
|
1183 | 1183 | finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes |
|
1184 | 1184 | migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data) |
|
1185 | 1185 | cloning 3 revisions from 00manifest.i |
|
1186 | 1186 | finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes |
|
1187 | 1187 | migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data) |
|
1188 | 1188 | cloning 3 revisions from 00changelog.i |
|
1189 | 1189 | finished migrating 3 changelog revisions; change in size: 0 bytes |
|
1190 | 1190 | finished migrating 9 total revisions; total change in store size: 0 bytes |
|
1191 | 1191 | copying phaseroots |
|
1192 | 1192 | copying requires |
|
1193 | 1193 | data fully upgraded in a temporary repository |
|
1194 | 1194 | marking source repository as being upgraded; clients will be unable to read from repository |
|
1195 | 1195 | starting in-place swap of repository data |
|
1196 | 1196 | replacing store... |
|
1197 | 1197 | store replacement complete; repository was inconsistent for *s (glob) |
|
1198 | 1198 | finalizing requirements file and making repository readable again |
|
1199 | 1199 | removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
1200 | 1200 | $ hg verify -q |
|
1201 | 1201 | |
|
1202 | 1202 | Check you can't skip revlog clone during important format upgrade |
|
1203 | 1203 | |
|
1204 | 1204 | $ echo "sparse-revlog=yes" >> .hg/hgrc |
|
1205 | 1205 | $ hg debugupgrade --optimize re-delta-parent --run --manifest --no-backup --debug --traceback |
|
1206 | 1206 | note: selecting all-filelogs for processing to change: sparserevlog |
|
1207 | 1207 | note: selecting changelog for processing to change: sparserevlog |
|
1208 | 1208 | |
|
1209 | 1209 | upgrade will perform the following actions: |
|
1210 | 1210 | |
|
1211 | 1211 | requirements |
|
1212 | 1212 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, store (no-rust !) |
|
1213 | 1213 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, store (rust !) |
|
1214 | 1214 | added: sparserevlog |
|
1215 | 1215 | |
|
1216 | 1216 | optimisations: re-delta-parent |
|
1217 | 1217 | |
|
1218 | 1218 | sparserevlog |
|
1219 | 1219 | Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server. |
|
1220 | 1220 | |
|
1221 | 1221 | re-delta-parent |
|
1222 | 1222 | deltas within internal storage will choose a new base revision if needed |
|
1223 | 1223 | |
|
1224 | 1224 | processed revlogs: |
|
1225 | 1225 | - all-filelogs |
|
1226 | 1226 | - changelog |
|
1227 | 1227 | - manifest |
|
1228 | 1228 | |
|
1229 | 1229 | beginning upgrade... |
|
1230 | 1230 | repository locked and read-only |
|
1231 | 1231 | creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
1232 | 1232 | (it is safe to interrupt this process any time before data migration completes) |
|
1233 | 1233 | migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog) |
|
1234 | 1234 | migrating 519 KB in store; 1.05 MB tracked data |
|
1235 | 1235 | migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data) |
|
1236 | 1236 | cloning 1 revisions from data/FooBarDirectory.d/f1.i |
|
1237 | 1237 | cloning 1 revisions from data/f0.i |
|
1238 | 1238 | cloning 1 revisions from data/f2.i |
|
1239 | 1239 | finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes |
|
1240 | 1240 | migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data) |
|
1241 | 1241 | cloning 3 revisions from 00manifest.i |
|
1242 | 1242 | finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes |
|
1243 | 1243 | migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data) |
|
1244 | 1244 | cloning 3 revisions from 00changelog.i |
|
1245 | 1245 | finished migrating 3 changelog revisions; change in size: 0 bytes |
|
1246 | 1246 | finished migrating 9 total revisions; total change in store size: 0 bytes |
|
1247 | 1247 | copying phaseroots |
|
1248 | 1248 | copying requires |
|
1249 | 1249 | data fully upgraded in a temporary repository |
|
1250 | 1250 | marking source repository as being upgraded; clients will be unable to read from repository |
|
1251 | 1251 | starting in-place swap of repository data |
|
1252 | 1252 | replacing store... |
|
1253 | 1253 | store replacement complete; repository was inconsistent for *s (glob) |
|
1254 | 1254 | finalizing requirements file and making repository readable again |
|
1255 | 1255 | removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob) |
|
1256 | 1256 | $ hg verify -q |
|
1257 | 1257 | |
|
1258 | 1258 | $ cd .. |
|
1259 | 1259 | |
|
1260 | 1260 | store files with special filenames aren't encoded during copy |
|
1261 | 1261 | |
|
1262 | 1262 | $ hg init store-filenames |
|
1263 | 1263 | $ cd store-filenames |
|
1264 | 1264 | $ touch foo |
|
1265 | 1265 | $ hg -q commit -A -m initial |
|
1266 | 1266 | $ touch .hg/store/.XX_special_filename |
|
1267 | 1267 | |
|
1268 | 1268 | $ hg debugupgraderepo --run |
|
1269 | 1269 | nothing to do |
|
1270 | 1270 | $ hg debugupgraderepo --run --optimize 're-delta-fulladd' |
|
1271 | 1271 | upgrade will perform the following actions: |
|
1272 | 1272 | |
|
1273 | 1273 | requirements |
|
1274 | 1274 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !) |
|
1275 | 1275 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !) |
|
1276 | 1276 | |
|
1277 | 1277 | optimisations: re-delta-fulladd |
|
1278 | 1278 | |
|
1279 | 1279 | re-delta-fulladd |
|
1280 | 1280 | each revision will be added as new content to the internal storage; this will likely drastically slow down execution time, but some extensions might need it |
|
1281 | 1281 | |
|
1282 | 1282 | processed revlogs: |
|
1283 | 1283 | - all-filelogs |
|
1284 | 1284 | - changelog |
|
1285 | 1285 | - manifest |
|
1286 | 1286 | |
|
1287 | 1287 | beginning upgrade... |
|
1288 | 1288 | repository locked and read-only |
|
1289 | 1289 | creating temporary repository to stage upgraded data: $TESTTMP/store-filenames/.hg/upgrade.* (glob) |
|
1290 | 1290 | (it is safe to interrupt this process any time before data migration completes) |
|
1291 | 1291 | migrating 3 total revisions (1 in filelogs, 1 in manifests, 1 in changelog) |
|
1292 | 1292 | migrating 301 bytes in store; 107 bytes tracked data |
|
1293 | 1293 | migrating 1 filelogs containing 1 revisions (64 bytes in store; 0 bytes tracked data) |
|
1294 | 1294 | finished migrating 1 filelog revisions across 1 filelogs; change in size: 0 bytes |
|
1295 | 1295 | migrating 1 manifests containing 1 revisions (110 bytes in store; 45 bytes tracked data) |
|
1296 | 1296 | finished migrating 1 manifest revisions across 1 manifests; change in size: 0 bytes |
|
1297 | 1297 | migrating changelog containing 1 revisions (127 bytes in store; 62 bytes tracked data) |
|
1298 | 1298 | finished migrating 1 changelog revisions; change in size: 0 bytes |
|
1299 | 1299 | finished migrating 3 total revisions; total change in store size: 0 bytes |
|
1300 | 1300 | copying .XX_special_filename |
|
1301 | 1301 | copying phaseroots |
|
1302 | 1302 | copying requires |
|
1303 | 1303 | data fully upgraded in a temporary repository |
|
1304 | 1304 | marking source repository as being upgraded; clients will be unable to read from repository |
|
1305 | 1305 | starting in-place swap of repository data |
|
1306 | 1306 | replaced files will be backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob) |
|
1307 | 1307 | replacing store... |
|
1308 | 1308 | store replacement complete; repository was inconsistent for *s (glob) |
|
1309 | 1309 | finalizing requirements file and making repository readable again |
|
1310 | 1310 | removing temporary repository $TESTTMP/store-filenames/.hg/upgrade.* (glob) |
|
1311 | 1311 | copy of old repository backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob) |
|
1312 | 1312 | the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified |
|
1313 | 1313 | |
|
1314 | 1314 | fncache is valid after upgrade |
|
1315 | 1315 | |
|
1316 | 1316 | $ hg debugrebuildfncache |
|
1317 | 1317 | fncache already up to date |
|
1318 | 1318 | |
|
1319 | 1319 | $ cd .. |
|
1320 | 1320 | |
|
1321 | 1321 | Check upgrading a large file repository |
|
1322 | 1322 | --------------------------------------- |
|
1323 | 1323 | |
|
1324 | 1324 | $ hg init largefilesrepo |
|
1325 | 1325 | $ cat << EOF >> largefilesrepo/.hg/hgrc |
|
1326 | 1326 | > [extensions] |
|
1327 | 1327 | > largefiles = |
|
1328 | 1328 | > EOF |
|
1329 | 1329 | |
|
1330 | 1330 | $ cd largefilesrepo |
|
1331 | 1331 | $ touch foo |
|
1332 | 1332 | $ hg add --large foo |
|
1333 | 1333 | $ hg -q commit -m initial |
|
1334 | 1334 | $ hg debugrequires |
|
1335 | 1335 | dotencode |
|
1336 | 1336 | fncache |
|
1337 | 1337 | generaldelta |
|
1338 | 1338 | largefiles |
|
1339 | 1339 | persistent-nodemap (rust !) |
|
1340 | 1340 | revlogv1 |
|
1341 | 1341 | share-safe |
|
1342 | 1342 | sparserevlog |
|
1343 | 1343 | store |
|
1344 | 1344 | |
|
1345 | 1345 | $ hg debugupgraderepo --run |
|
1346 | 1346 | nothing to do |
|
1347 | 1347 | $ hg debugrequires |
|
1348 | 1348 | dotencode |
|
1349 | 1349 | fncache |
|
1350 | 1350 | generaldelta |
|
1351 | 1351 | largefiles |
|
1352 | 1352 | persistent-nodemap (rust !) |
|
1353 | 1353 | revlogv1 |
|
1354 | 1354 | share-safe |
|
1355 | 1355 | sparserevlog |
|
1356 | 1356 | store |
|
1357 | 1357 | |
|
1358 | 1358 | $ cat << EOF >> .hg/hgrc |
|
1359 | 1359 | > [extensions] |
|
1360 | 1360 | > lfs = |
|
1361 | 1361 | > [lfs] |
|
1362 | 1362 | > threshold = 10 |
|
1363 | 1363 | > EOF |
|
1364 | 1364 | $ echo '123456789012345' > lfs.bin |
|
1365 | 1365 | $ hg ci -Am 'lfs.bin' |
|
1366 | 1366 | adding lfs.bin |
|
1367 | 1367 | $ hg debugrequires | grep lfs |
|
1368 | 1368 | lfs |
|
1369 | 1369 | $ find .hg/store/lfs -type f |
|
1370 | 1370 | .hg/store/lfs/objects/d0/beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f |
|
1371 | 1371 | |
|
1372 | 1372 | $ hg debugupgraderepo --run |
|
1373 | 1373 | nothing to do |
|
1374 | 1374 | |
|
1375 | 1375 | $ hg debugrequires | grep lfs |
|
1376 | 1376 | lfs |
|
1377 | 1377 | $ find .hg/store/lfs -type f |
|
1378 | 1378 | .hg/store/lfs/objects/d0/beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f |
|
1379 | 1379 | $ hg verify -q |
|
1380 | 1380 | $ hg debugdata lfs.bin 0 |
|
1381 | 1381 | version https://git-lfs.github.com/spec/v1 |
|
1382 | 1382 | oid sha256:d0beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f |
|
1383 | 1383 | size 16 |
|
1384 | 1384 | x-is-binary 0 |
|
1385 | 1385 | |
|
1386 | 1386 | $ cd .. |
|
1387 | 1387 | |
|
1388 | 1388 | repository config is taken in account |
|
1389 | 1389 | ------------------------------------- |
|
1390 | 1390 | |
|
1391 | 1391 | $ cat << EOF >> $HGRCPATH |
|
1392 | 1392 | > [format] |
|
1393 | 1393 | > maxchainlen = 1 |
|
1394 | 1394 | > EOF |
|
1395 | 1395 | |
|
1396 | 1396 | $ hg init localconfig |
|
1397 | 1397 | $ cd localconfig |
|
1398 | 1398 | $ cat << EOF > file |
|
1399 | 1399 | > some content |
|
1400 | 1400 | > with some length |
|
1401 | 1401 | > to make sure we get a delta |
|
1402 | 1402 | > after changes |
|
1403 | 1403 | > very long |
|
1404 | 1404 | > very long |
|
1405 | 1405 | > very long |
|
1406 | 1406 | > very long |
|
1407 | 1407 | > very long |
|
1408 | 1408 | > very long |
|
1409 | 1409 | > very long |
|
1410 | 1410 | > very long |
|
1411 | 1411 | > very long |
|
1412 | 1412 | > very long |
|
1413 | 1413 | > very long |
|
1414 | 1414 | > EOF |
|
1415 | 1415 | $ hg -q commit -A -m A |
|
1416 | 1416 | $ echo "new line" >> file |
|
1417 | 1417 | $ hg -q commit -m B |
|
1418 | 1418 | $ echo "new line" >> file |
|
1419 | 1419 | $ hg -q commit -m C |
|
1420 | 1420 | |
|
1421 | 1421 | $ cat << EOF >> .hg/hgrc |
|
1422 | 1422 | > [format] |
|
1423 | 1423 | > maxchainlen = 9001 |
|
1424 | 1424 | > EOF |
|
1425 | 1425 | $ hg config format |
|
1426 | 1426 | format.revlog-compression=$BUNDLE2_COMPRESSIONS$ |
|
1427 | 1427 | format.maxchainlen=9001 |
|
1428 | 1428 | $ hg debugdeltachain file |
|
1429 | 1429 | rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks |
|
1430 | 1430 | 0 -1 -1 1 1 -1 base 77 182 77 0.42308 77 0 0.00000 77 77 1.00000 1 |
|
1431 | 1431 | 1 0 -1 1 2 0 p1 21 191 98 0.51309 98 0 0.00000 98 98 1.00000 1 |
|
1432 | 1432 | 2 1 -1 1 2 0 snap 30 200 107 0.53500 128 21 0.19626 128 128 0.83594 1 |
|
1433 | 1433 | |
|
1434 | 1434 | $ hg debugupgraderepo --run --optimize 're-delta-all' |
|
1435 | 1435 | upgrade will perform the following actions: |
|
1436 | 1436 | |
|
1437 | 1437 | requirements |
|
1438 | 1438 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !) |
|
1439 | 1439 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !) |
|
1440 | 1440 | |
|
1441 | 1441 | optimisations: re-delta-all |
|
1442 | 1442 | |
|
1443 | 1443 | re-delta-all |
|
1444 | 1444 | deltas within internal storage will be fully recomputed; this will likely drastically slow down execution time |
|
1445 | 1445 | |
|
1446 | 1446 | processed revlogs: |
|
1447 | 1447 | - all-filelogs |
|
1448 | 1448 | - changelog |
|
1449 | 1449 | - manifest |
|
1450 | 1450 | |
|
1451 | 1451 | beginning upgrade... |
|
1452 | 1452 | repository locked and read-only |
|
1453 | 1453 | creating temporary repository to stage upgraded data: $TESTTMP/localconfig/.hg/upgrade.* (glob) |
|
1454 | 1454 | (it is safe to interrupt this process any time before data migration completes) |
|
1455 | 1455 | migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog) |
|
1456 | 1456 | migrating 1019 bytes in store; 882 bytes tracked data |
|
1457 | 1457 | migrating 1 filelogs containing 3 revisions (320 bytes in store; 573 bytes tracked data) |
|
1458 | 1458 | finished migrating 3 filelog revisions across 1 filelogs; change in size: -9 bytes |
|
1459 | 1459 | migrating 1 manifests containing 3 revisions (333 bytes in store; 138 bytes tracked data) |
|
1460 | 1460 | finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes |
|
1461 | 1461 | migrating changelog containing 3 revisions (366 bytes in store; 171 bytes tracked data) |
|
1462 | 1462 | finished migrating 3 changelog revisions; change in size: 0 bytes |
|
1463 | 1463 | finished migrating 9 total revisions; total change in store size: -9 bytes |
|
1464 | 1464 | copying phaseroots |
|
1465 | 1465 | copying requires |
|
1466 | 1466 | data fully upgraded in a temporary repository |
|
1467 | 1467 | marking source repository as being upgraded; clients will be unable to read from repository |
|
1468 | 1468 | starting in-place swap of repository data |
|
1469 | 1469 | replaced files will be backed up at $TESTTMP/localconfig/.hg/upgradebackup.* (glob) |
|
1470 | 1470 | replacing store... |
|
1471 | 1471 | store replacement complete; repository was inconsistent for *s (glob) |
|
1472 | 1472 | finalizing requirements file and making repository readable again |
|
1473 | 1473 | removing temporary repository $TESTTMP/localconfig/.hg/upgrade.* (glob) |
|
1474 | 1474 | copy of old repository backed up at $TESTTMP/localconfig/.hg/upgradebackup.* (glob) |
|
1475 | 1475 | the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified |
|
1476 | 1476 | $ hg debugdeltachain file |
|
1477 | 1477 | rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks |
|
1478 | 1478 | 0 -1 -1 1 1 -1 base 77 182 77 0.42308 77 0 0.00000 77 77 1.00000 1 |
|
1479 | 1479 | 1 0 -1 1 2 0 p1 21 191 98 0.51309 98 0 0.00000 98 98 1.00000 1 |
|
1480 | 1480 | 2 1 -1 1 3 1 p1 21 200 119 0.59500 119 0 0.00000 119 119 1.00000 1 |
|
1481 | 1481 | $ cd .. |
|
1482 | 1482 | |
|
1483 | 1483 | $ cat << EOF >> $HGRCPATH |
|
1484 | 1484 | > [format] |
|
1485 | 1485 | > maxchainlen = 9001 |
|
1486 | 1486 | > EOF |
|
1487 | 1487 | |
|
1488 | 1488 | Check upgrading a sparse-revlog repository |
|
1489 | 1489 | --------------------------------------- |
|
1490 | 1490 | |
|
1491 | 1491 | $ hg init sparserevlogrepo --config format.sparse-revlog=no |
|
1492 | 1492 | $ cd sparserevlogrepo |
|
1493 | 1493 | $ touch foo |
|
1494 | 1494 | $ hg add foo |
|
1495 | 1495 | $ hg -q commit -m "foo" |
|
1496 | 1496 | $ hg debugrequires |
|
1497 | 1497 | dotencode |
|
1498 | 1498 | fncache |
|
1499 | 1499 | generaldelta |
|
1500 | 1500 | persistent-nodemap (rust !) |
|
1501 | 1501 | revlogv1 |
|
1502 | 1502 | share-safe |
|
1503 | 1503 | store |
|
1504 | 1504 | |
|
1505 | 1505 | Check that we can add the sparse-revlog format requirement |
|
1506 | 1506 | $ hg --config format.sparse-revlog=yes debugupgraderepo --run --quiet |
|
1507 | 1507 | upgrade will perform the following actions: |
|
1508 | 1508 | |
|
1509 | 1509 | requirements |
|
1510 | 1510 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, store (no-rust !) |
|
1511 | 1511 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, store (rust !) |
|
1512 | 1512 | added: sparserevlog |
|
1513 | 1513 | |
|
1514 | 1514 | processed revlogs: |
|
1515 | 1515 | - all-filelogs |
|
1516 | 1516 | - changelog |
|
1517 | 1517 | - manifest |
|
1518 | 1518 | |
|
1519 | 1519 | $ hg debugrequires |
|
1520 | 1520 | dotencode |
|
1521 | 1521 | fncache |
|
1522 | 1522 | generaldelta |
|
1523 | 1523 | persistent-nodemap (rust !) |
|
1524 | 1524 | revlogv1 |
|
1525 | 1525 | share-safe |
|
1526 | 1526 | sparserevlog |
|
1527 | 1527 | store |
|
1528 | 1528 | |
|
1529 | 1529 | Check that we can remove the sparse-revlog format requirement |
|
1530 | 1530 | $ hg --config format.sparse-revlog=no debugupgraderepo --run --quiet |
|
1531 | 1531 | upgrade will perform the following actions: |
|
1532 | 1532 | |
|
1533 | 1533 | requirements |
|
1534 | 1534 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, store (no-rust !) |
|
1535 | 1535 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, store (rust !) |
|
1536 | 1536 | removed: sparserevlog |
|
1537 | 1537 | |
|
1538 | 1538 | processed revlogs: |
|
1539 | 1539 | - all-filelogs |
|
1540 | 1540 | - changelog |
|
1541 | 1541 | - manifest |
|
1542 | 1542 | |
|
1543 | 1543 | $ hg debugrequires |
|
1544 | 1544 | dotencode |
|
1545 | 1545 | fncache |
|
1546 | 1546 | generaldelta |
|
1547 | 1547 | persistent-nodemap (rust !) |
|
1548 | 1548 | revlogv1 |
|
1549 | 1549 | share-safe |
|
1550 | 1550 | store |
|
1551 | 1551 | |
|
1552 | 1552 | #if zstd |
|
1553 | 1553 | |
|
1554 | 1554 | Check upgrading to a zstd revlog |
|
1555 | 1555 | -------------------------------- |
|
1556 | 1556 | |
|
1557 | 1557 | upgrade |
|
1558 | 1558 | |
|
1559 | 1559 | $ hg --config format.revlog-compression=zstd debugupgraderepo --run --no-backup --quiet |
|
1560 | 1560 | upgrade will perform the following actions: |
|
1561 | 1561 | |
|
1562 | 1562 | requirements |
|
1563 | 1563 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, store (no-rust !) |
|
1564 | 1564 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, store (rust !) |
|
1565 | 1565 | added: revlog-compression-zstd, sparserevlog |
|
1566 | 1566 | |
|
1567 | 1567 | processed revlogs: |
|
1568 | 1568 | - all-filelogs |
|
1569 | 1569 | - changelog |
|
1570 | 1570 | - manifest |
|
1571 | 1571 | |
|
1572 | 1572 | $ hg debugformat -v |
|
1573 | 1573 | format-variant repo config default |
|
1574 | 1574 | fncache: yes yes yes |
|
1575 | 1575 | dirstate-v2: no no no |
|
1576 | 1576 | tracked-hint: no no no |
|
1577 | 1577 | dotencode: yes yes yes |
|
1578 | 1578 | generaldelta: yes yes yes |
|
1579 | 1579 | share-safe: yes yes yes |
|
1580 | 1580 | sparserevlog: yes yes yes |
|
1581 | 1581 | persistent-nodemap: no no no (no-rust !) |
|
1582 | 1582 | persistent-nodemap: yes yes no (rust !) |
|
1583 | 1583 | copies-sdc: no no no |
|
1584 | 1584 | revlog-v2: no no no |
|
1585 | 1585 | changelog-v2: no no no |
|
1586 | 1586 | plain-cl-delta: yes yes yes |
|
1587 | 1587 | compression: zlib zlib zlib (no-zstd !) |
|
1588 | 1588 | compression: zstd zlib zstd (zstd !) |
|
1589 | 1589 | compression-level: default default default |
|
1590 | 1590 | $ hg debugrequires |
|
1591 | 1591 | dotencode |
|
1592 | 1592 | fncache |
|
1593 | 1593 | generaldelta |
|
1594 | 1594 | persistent-nodemap (rust !) |
|
1595 | 1595 | revlog-compression-zstd |
|
1596 | 1596 | revlogv1 |
|
1597 | 1597 | share-safe |
|
1598 | 1598 | sparserevlog |
|
1599 | 1599 | store |
|
1600 | 1600 | |
|
1601 | 1601 | downgrade |
|
1602 | 1602 | |
|
1603 | 1603 | $ hg debugupgraderepo --run --no-backup --quiet |
|
1604 | 1604 | upgrade will perform the following actions: |
|
1605 | 1605 | |
|
1606 | 1606 | requirements |
|
1607 | 1607 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !) |
|
1608 | 1608 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !) |
|
1609 | 1609 | removed: revlog-compression-zstd |
|
1610 | 1610 | |
|
1611 | 1611 | processed revlogs: |
|
1612 | 1612 | - all-filelogs |
|
1613 | 1613 | - changelog |
|
1614 | 1614 | - manifest |
|
1615 | 1615 | |
|
1616 | 1616 | $ hg debugformat -v |
|
1617 | 1617 | format-variant repo config default |
|
1618 | 1618 | fncache: yes yes yes |
|
1619 | 1619 | dirstate-v2: no no no |
|
1620 | 1620 | tracked-hint: no no no |
|
1621 | 1621 | dotencode: yes yes yes |
|
1622 | 1622 | generaldelta: yes yes yes |
|
1623 | 1623 | share-safe: yes yes yes |
|
1624 | 1624 | sparserevlog: yes yes yes |
|
1625 | 1625 | persistent-nodemap: no no no (no-rust !) |
|
1626 | 1626 | persistent-nodemap: yes yes no (rust !) |
|
1627 | 1627 | copies-sdc: no no no |
|
1628 | 1628 | revlog-v2: no no no |
|
1629 | 1629 | changelog-v2: no no no |
|
1630 | 1630 | plain-cl-delta: yes yes yes |
|
1631 | 1631 | compression: zlib zlib zlib (no-zstd !) |
|
1632 | 1632 | compression: zlib zlib zstd (zstd !) |
|
1633 | 1633 | compression-level: default default default |
|
1634 | 1634 | $ hg debugrequires |
|
1635 | 1635 | dotencode |
|
1636 | 1636 | fncache |
|
1637 | 1637 | generaldelta |
|
1638 | 1638 | persistent-nodemap (rust !) |
|
1639 | 1639 | revlogv1 |
|
1640 | 1640 | share-safe |
|
1641 | 1641 | sparserevlog |
|
1642 | 1642 | store |
|
1643 | 1643 | |
|
1644 | 1644 | upgrade from hgrc |
|
1645 | 1645 | |
|
1646 | 1646 | $ cat >> .hg/hgrc << EOF |
|
1647 | 1647 | > [format] |
|
1648 | 1648 | > revlog-compression=zstd |
|
1649 | 1649 | > EOF |
|
1650 | 1650 | $ hg debugupgraderepo --run --no-backup --quiet |
|
1651 | 1651 | upgrade will perform the following actions: |
|
1652 | 1652 | |
|
1653 | 1653 | requirements |
|
1654 | 1654 | preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !) |
|
1655 | 1655 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !) |
|
1656 | 1656 | added: revlog-compression-zstd |
|
1657 | 1657 | |
|
1658 | 1658 | processed revlogs: |
|
1659 | 1659 | - all-filelogs |
|
1660 | 1660 | - changelog |
|
1661 | 1661 | - manifest |
|
1662 | 1662 | |
|
1663 | 1663 | $ hg debugformat -v |
|
1664 | 1664 | format-variant repo config default |
|
1665 | 1665 | fncache: yes yes yes |
|
1666 | 1666 | dirstate-v2: no no no |
|
1667 | 1667 | tracked-hint: no no no |
|
1668 | 1668 | dotencode: yes yes yes |
|
1669 | 1669 | generaldelta: yes yes yes |
|
1670 | 1670 | share-safe: yes yes yes |
|
1671 | 1671 | sparserevlog: yes yes yes |
|
1672 | 1672 | persistent-nodemap: no no no (no-rust !) |
|
1673 | 1673 | persistent-nodemap: yes yes no (rust !) |
|
1674 | 1674 | copies-sdc: no no no |
|
1675 | 1675 | revlog-v2: no no no |
|
1676 | 1676 | changelog-v2: no no no |
|
1677 | 1677 | plain-cl-delta: yes yes yes |
|
1678 | 1678 | compression: zlib zlib zlib (no-zstd !) |
|
1679 | 1679 | compression: zstd zstd zstd (zstd !) |
|
1680 | 1680 | compression-level: default default default |
|
1681 | 1681 | $ hg debugrequires |
|
1682 | 1682 | dotencode |
|
1683 | 1683 | fncache |
|
1684 | 1684 | generaldelta |
|
1685 | 1685 | persistent-nodemap (rust !) |
|
1686 | 1686 | revlog-compression-zstd |
|
1687 | 1687 | revlogv1 |
|
1688 | 1688 | share-safe |
|
1689 | 1689 | sparserevlog |
|
1690 | 1690 | store |
|
1691 | 1691 | |
|
1692 | 1692 | #endif |
|
1693 | 1693 | |
|
1694 | 1694 | Check upgrading to a revlog format supporting sidedata |
|
1695 | 1695 | ------------------------------------------------------ |
|
1696 | 1696 | |
|
1697 | 1697 | upgrade |
|
1698 | 1698 | |
|
1699 | 1699 | $ hg debugsidedata -c 0 |
|
1700 | 1700 | $ hg --config experimental.revlogv2=enable-unstable-format-and-corrupt-my-data debugupgraderepo --run --no-backup --config "extensions.sidedata=$TESTDIR/testlib/ext-sidedata.py" --quiet |
|
1701 | 1701 | upgrade will perform the following actions: |
|
1702 | 1702 | |
|
1703 | 1703 | requirements |
|
1704 | 1704 | preserved: dotencode, fncache, generaldelta, share-safe, store (no-zstd !) |
|
1705 | 1705 | preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, share-safe, sparserevlog, store (zstd no-rust !) |
|
1706 | 1706 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, share-safe, sparserevlog, store (rust !) |
|
1707 | 1707 | removed: revlogv1 |
|
1708 | 1708 | added: exp-revlogv2.2 (zstd !) |
|
1709 | 1709 | added: exp-revlogv2.2, sparserevlog (no-zstd !) |
|
1710 | 1710 | |
|
1711 | 1711 | processed revlogs: |
|
1712 | 1712 | - all-filelogs |
|
1713 | 1713 | - changelog |
|
1714 | 1714 | - manifest |
|
1715 | 1715 | |
|
1716 | 1716 | $ hg debugformat -v |
|
1717 | 1717 | format-variant repo config default |
|
1718 | 1718 | fncache: yes yes yes |
|
1719 | 1719 | dirstate-v2: no no no |
|
1720 | 1720 | tracked-hint: no no no |
|
1721 | 1721 | dotencode: yes yes yes |
|
1722 | 1722 | generaldelta: yes yes yes |
|
1723 | 1723 | share-safe: yes yes yes |
|
1724 | 1724 | sparserevlog: yes yes yes |
|
1725 | 1725 | persistent-nodemap: no no no (no-rust !) |
|
1726 | 1726 | persistent-nodemap: yes yes no (rust !) |
|
1727 | 1727 | copies-sdc: no no no |
|
1728 | 1728 | revlog-v2: yes no no |
|
1729 | 1729 | changelog-v2: no no no |
|
1730 | 1730 | plain-cl-delta: yes yes yes |
|
1731 | 1731 | compression: zlib zlib zlib (no-zstd !) |
|
1732 | 1732 | compression: zstd zstd zstd (zstd !) |
|
1733 | 1733 | compression-level: default default default |
|
1734 | 1734 | $ hg debugrequires |
|
1735 | 1735 | dotencode |
|
1736 | 1736 | exp-revlogv2.2 |
|
1737 | 1737 | fncache |
|
1738 | 1738 | generaldelta |
|
1739 | 1739 | persistent-nodemap (rust !) |
|
1740 | 1740 | revlog-compression-zstd (zstd !) |
|
1741 | 1741 | share-safe |
|
1742 | 1742 | sparserevlog |
|
1743 | 1743 | store |
|
1744 | 1744 | $ hg debugsidedata -c 0 |
|
1745 | 1745 | 2 sidedata entries |
|
1746 | 1746 | entry-0001 size 4 |
|
1747 | 1747 | entry-0002 size 32 |
|
1748 | 1748 | |
|
1749 | 1749 | downgrade |
|
1750 | 1750 | |
|
1751 | 1751 | $ hg debugupgraderepo --config experimental.revlogv2=no --run --no-backup --quiet |
|
1752 | 1752 | upgrade will perform the following actions: |
|
1753 | 1753 | |
|
1754 | 1754 | requirements |
|
1755 | 1755 | preserved: dotencode, fncache, generaldelta, share-safe, sparserevlog, store (no-zstd !) |
|
1756 | 1756 | preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, share-safe, sparserevlog, store (zstd no-rust !) |
|
1757 | 1757 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, share-safe, sparserevlog, store (rust !) |
|
1758 | 1758 | removed: exp-revlogv2.2 |
|
1759 | 1759 | added: revlogv1 |
|
1760 | 1760 | |
|
1761 | 1761 | processed revlogs: |
|
1762 | 1762 | - all-filelogs |
|
1763 | 1763 | - changelog |
|
1764 | 1764 | - manifest |
|
1765 | 1765 | |
|
1766 | 1766 | $ hg debugformat -v |
|
1767 | 1767 | format-variant repo config default |
|
1768 | 1768 | fncache: yes yes yes |
|
1769 | 1769 | dirstate-v2: no no no |
|
1770 | 1770 | tracked-hint: no no no |
|
1771 | 1771 | dotencode: yes yes yes |
|
1772 | 1772 | generaldelta: yes yes yes |
|
1773 | 1773 | share-safe: yes yes yes |
|
1774 | 1774 | sparserevlog: yes yes yes |
|
1775 | 1775 | persistent-nodemap: no no no (no-rust !) |
|
1776 | 1776 | persistent-nodemap: yes yes no (rust !) |
|
1777 | 1777 | copies-sdc: no no no |
|
1778 | 1778 | revlog-v2: no no no |
|
1779 | 1779 | changelog-v2: no no no |
|
1780 | 1780 | plain-cl-delta: yes yes yes |
|
1781 | 1781 | compression: zlib zlib zlib (no-zstd !) |
|
1782 | 1782 | compression: zstd zstd zstd (zstd !) |
|
1783 | 1783 | compression-level: default default default |
|
1784 | 1784 | $ hg debugrequires |
|
1785 | 1785 | dotencode |
|
1786 | 1786 | fncache |
|
1787 | 1787 | generaldelta |
|
1788 | 1788 | persistent-nodemap (rust !) |
|
1789 | 1789 | revlog-compression-zstd (zstd !) |
|
1790 | 1790 | revlogv1 |
|
1791 | 1791 | share-safe |
|
1792 | 1792 | sparserevlog |
|
1793 | 1793 | store |
|
1794 | 1794 | $ hg debugsidedata -c 0 |
|
1795 | 1795 | |
|
1796 | 1796 | upgrade from hgrc |
|
1797 | 1797 | |
|
1798 | 1798 | $ cat >> .hg/hgrc << EOF |
|
1799 | 1799 | > [experimental] |
|
1800 | 1800 | > revlogv2=enable-unstable-format-and-corrupt-my-data |
|
1801 | 1801 | > EOF |
|
1802 | 1802 | $ hg debugupgraderepo --run --no-backup --quiet |
|
1803 | 1803 | upgrade will perform the following actions: |
|
1804 | 1804 | |
|
1805 | 1805 | requirements |
|
1806 | 1806 | preserved: dotencode, fncache, generaldelta, share-safe, sparserevlog, store (no-zstd !) |
|
1807 | 1807 | preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, share-safe, sparserevlog, store (zstd no-rust !) |
|
1808 | 1808 | preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, share-safe, sparserevlog, store (rust !) |
|
1809 | 1809 | removed: revlogv1 |
|
1810 | 1810 | added: exp-revlogv2.2 |
|
1811 | 1811 | |
|
1812 | 1812 | processed revlogs: |
|
1813 | 1813 | - all-filelogs |
|
1814 | 1814 | - changelog |
|
1815 | 1815 | - manifest |
|
1816 | 1816 | |
|
1817 | 1817 | $ hg debugformat -v |
|
1818 | 1818 | format-variant repo config default |
|
1819 | 1819 | fncache: yes yes yes |
|
1820 | 1820 | dirstate-v2: no no no |
|
1821 | 1821 | tracked-hint: no no no |
|
1822 | 1822 | dotencode: yes yes yes |
|
1823 | 1823 | generaldelta: yes yes yes |
|
1824 | 1824 | share-safe: yes yes yes |
|
1825 | 1825 | sparserevlog: yes yes yes |
|
1826 | 1826 | persistent-nodemap: no no no (no-rust !) |
|
1827 | 1827 | persistent-nodemap: yes yes no (rust !) |
|
1828 | 1828 | copies-sdc: no no no |
|
1829 | 1829 | revlog-v2: yes yes no |
|
1830 | 1830 | changelog-v2: no no no |
|
1831 | 1831 | plain-cl-delta: yes yes yes |
|
1832 | 1832 | compression: zlib zlib zlib (no-zstd !) |
|
1833 | 1833 | compression: zstd zstd zstd (zstd !) |
|
1834 | 1834 | compression-level: default default default |
|
1835 | 1835 | $ hg debugrequires |
|
1836 | 1836 | dotencode |
|
1837 | 1837 | exp-revlogv2.2 |
|
1838 | 1838 | fncache |
|
1839 | 1839 | generaldelta |
|
1840 | 1840 | persistent-nodemap (rust !) |
|
1841 | 1841 | revlog-compression-zstd (zstd !) |
|
1842 | 1842 | share-safe |
|
1843 | 1843 | sparserevlog |
|
1844 | 1844 | store |
|
1845 | 1845 | $ hg debugsidedata -c 0 |
|
1846 | 1846 | |
|
1847 | 1847 | Demonstrate that nothing to perform upgrade will still run all the way through |
|
1848 | 1848 | |
|
1849 | 1849 | $ hg debugupgraderepo --run |
|
1850 | 1850 | nothing to do |
|
1851 | 1851 | |
|
1852 | 1852 | #if no-rust |
|
1853 | 1853 | |
|
1854 | 1854 | $ cat << EOF >> $HGRCPATH |
|
1855 | 1855 | > [storage] |
|
1856 | 1856 | > dirstate-v2.slow-path = allow |
|
1857 | 1857 | > EOF |
|
1858 | 1858 | |
|
1859 | 1859 | #endif |
|
1860 | 1860 | |
|
1861 | 1861 | Upgrade to dirstate-v2 |
|
1862 | 1862 | |
|
1863 | 1863 | $ hg debugformat -v --config format.use-dirstate-v2=1 | grep dirstate-v2 |
|
1864 | 1864 | dirstate-v2: no yes no |
|
1865 | 1865 | $ hg debugupgraderepo --config format.use-dirstate-v2=1 --run |
|
1866 | 1866 | upgrade will perform the following actions: |
|
1867 | 1867 | |
|
1868 | 1868 | requirements |
|
1869 | 1869 | preserved: * (glob) |
|
1870 | 1870 | added: dirstate-v2 |
|
1871 | 1871 | |
|
1872 | 1872 | dirstate-v2 |
|
1873 | 1873 | "hg status" will be faster |
|
1874 | 1874 | |
|
1875 | 1875 | no revlogs to process |
|
1876 | 1876 | |
|
1877 | 1877 | beginning upgrade... |
|
1878 | 1878 | repository locked and read-only |
|
1879 | 1879 | creating temporary repository to stage upgraded data: $TESTTMP/sparserevlogrepo/.hg/upgrade.* (glob) |
|
1880 | 1880 | (it is safe to interrupt this process any time before data migration completes) |
|
1881 | 1881 | upgrading to dirstate-v2 from v1 |
|
1882 | 1882 | replaced files will be backed up at $TESTTMP/sparserevlogrepo/.hg/upgradebackup.* (glob) |
|
1883 | 1883 | removing temporary repository $TESTTMP/sparserevlogrepo/.hg/upgrade.* (glob) |
|
1884 | 1884 | $ ls .hg/upgradebackup.*/dirstate |
|
1885 | 1885 | .hg/upgradebackup.*/dirstate (glob) |
|
1886 | 1886 | $ hg debugformat -v | grep dirstate-v2 |
|
1887 | 1887 | dirstate-v2: yes no no |
|
1888 | 1888 | $ hg status |
|
1889 | 1889 | $ dd bs=12 count=1 if=.hg/dirstate 2> /dev/null |
|
1890 | 1890 | dirstate-v2 |
|
1891 | 1891 | |
|
1892 | 1892 | Downgrade from dirstate-v2 |
|
1893 | 1893 | |
|
1894 | 1894 | $ hg debugupgraderepo --run |
|
1895 | 1895 | upgrade will perform the following actions: |
|
1896 | 1896 | |
|
1897 | 1897 | requirements |
|
1898 | 1898 | preserved: * (glob) |
|
1899 | 1899 | removed: dirstate-v2 |
|
1900 | 1900 | |
|
1901 | 1901 | no revlogs to process |
|
1902 | 1902 | |
|
1903 | 1903 | beginning upgrade... |
|
1904 | 1904 | repository locked and read-only |
|
1905 | 1905 | creating temporary repository to stage upgraded data: $TESTTMP/sparserevlogrepo/.hg/upgrade.* (glob) |
|
1906 | 1906 | (it is safe to interrupt this process any time before data migration completes) |
|
1907 | 1907 | downgrading from dirstate-v2 to v1 |
|
1908 | 1908 | replaced files will be backed up at $TESTTMP/sparserevlogrepo/.hg/upgradebackup.* (glob) |
|
1909 | 1909 | removing temporary repository $TESTTMP/sparserevlogrepo/.hg/upgrade.* (glob) |
|
1910 | 1910 | $ hg debugformat -v | grep dirstate-v2 |
|
1911 | 1911 | dirstate-v2: no no no |
|
1912 | 1912 | $ hg status |
|
1913 | 1913 | |
|
1914 | 1914 | $ cd .. |
|
1915 | 1915 | |
|
1916 | 1916 | dirstate-v2: upgrade and downgrade from and empty repository: |
|
1917 | 1917 | ------------------------------------------------------------- |
|
1918 | 1918 | |
|
1919 | 1919 | $ hg init --config format.use-dirstate-v2=no dirstate-v2-empty |
|
1920 | 1920 | $ cd dirstate-v2-empty |
|
1921 | 1921 | $ hg debugformat | grep dirstate-v2 |
|
1922 | 1922 | dirstate-v2: no |
|
1923 | 1923 | |
|
1924 | 1924 | upgrade |
|
1925 | 1925 | |
|
1926 | 1926 | $ hg debugupgraderepo --run --config format.use-dirstate-v2=yes |
|
1927 | 1927 | upgrade will perform the following actions: |
|
1928 | 1928 | |
|
1929 | 1929 | requirements |
|
1930 | 1930 | preserved: * (glob) |
|
1931 | 1931 | added: dirstate-v2 |
|
1932 | 1932 | |
|
1933 | 1933 | dirstate-v2 |
|
1934 | 1934 | "hg status" will be faster |
|
1935 | 1935 | |
|
1936 | 1936 | no revlogs to process |
|
1937 | 1937 | |
|
1938 | 1938 | beginning upgrade... |
|
1939 | 1939 | repository locked and read-only |
|
1940 | 1940 | creating temporary repository to stage upgraded data: $TESTTMP/dirstate-v2-empty/.hg/upgrade.* (glob) |
|
1941 | 1941 | (it is safe to interrupt this process any time before data migration completes) |
|
1942 | 1942 | upgrading to dirstate-v2 from v1 |
|
1943 | 1943 | replaced files will be backed up at $TESTTMP/dirstate-v2-empty/.hg/upgradebackup.* (glob) |
|
1944 | 1944 | removing temporary repository $TESTTMP/dirstate-v2-empty/.hg/upgrade.* (glob) |
|
1945 | 1945 | $ hg debugformat | grep dirstate-v2 |
|
1946 | 1946 | dirstate-v2: yes |
|
1947 | 1947 | |
|
1948 | 1948 | downgrade |
|
1949 | 1949 | |
|
1950 | 1950 | $ hg debugupgraderepo --run --config format.use-dirstate-v2=no |
|
1951 | 1951 | upgrade will perform the following actions: |
|
1952 | 1952 | |
|
1953 | 1953 | requirements |
|
1954 | 1954 | preserved: * (glob) |
|
1955 | 1955 | removed: dirstate-v2 |
|
1956 | 1956 | |
|
1957 | 1957 | no revlogs to process |
|
1958 | 1958 | |
|
1959 | 1959 | beginning upgrade... |
|
1960 | 1960 | repository locked and read-only |
|
1961 | 1961 | creating temporary repository to stage upgraded data: $TESTTMP/dirstate-v2-empty/.hg/upgrade.* (glob) |
|
1962 | 1962 | (it is safe to interrupt this process any time before data migration completes) |
|
1963 | 1963 | downgrading from dirstate-v2 to v1 |
|
1964 | 1964 | replaced files will be backed up at $TESTTMP/dirstate-v2-empty/.hg/upgradebackup.* (glob) |
|
1965 | 1965 | removing temporary repository $TESTTMP/dirstate-v2-empty/.hg/upgrade.* (glob) |
|
1966 | 1966 | $ hg debugformat | grep dirstate-v2 |
|
1967 | 1967 | dirstate-v2: no |
|
1968 | 1968 | |
|
1969 | 1969 | $ cd .. |
|
1970 | 1970 | |
|
1971 | 1971 | Test automatic upgrade/downgrade |
|
1972 | 1972 | ================================ |
|
1973 | 1973 | |
|
1974 | 1974 | |
|
1975 | 1975 | For dirstate v2 |
|
1976 | 1976 | --------------- |
|
1977 | 1977 | |
|
1978 | 1978 | create an initial repository |
|
1979 | 1979 | |
|
1980 | 1980 | $ hg init auto-upgrade \ |
|
1981 | 1981 | > --config format.use-dirstate-v2=no \ |
|
1982 | 1982 | > --config format.use-dirstate-tracked-hint=yes \ |
|
1983 | 1983 | > --config format.use-share-safe=no |
|
1984 | 1984 | $ hg debugbuilddag -R auto-upgrade --new-file .+5 |
|
1985 | 1985 | $ hg -R auto-upgrade update |
|
1986 | 1986 | 6 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
1987 | 1987 | $ hg debugformat -R auto-upgrade | grep dirstate-v2 |
|
1988 | 1988 | dirstate-v2: no |
|
1989 | 1989 | |
|
1990 | 1990 | upgrade it to dirstate-v2 automatically |
|
1991 | 1991 | |
|
1992 | 1992 | $ hg status -R auto-upgrade \ |
|
1993 | 1993 | > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories=yes \ |
|
1994 | 1994 | > --config format.use-dirstate-v2=yes |
|
1995 | 1995 | automatically upgrading repository to the `dirstate-v2` feature |
|
1996 | 1996 | (see `hg help config.format.use-dirstate-v2` for details) |
|
1997 | 1997 | $ hg debugformat -R auto-upgrade | grep dirstate-v2 |
|
1998 | 1998 | dirstate-v2: yes |
|
1999 | 1999 | |
|
2000 | 2000 | downgrade it from dirstate-v2 automatically |
|
2001 | 2001 | |
|
2002 | 2002 | $ hg status -R auto-upgrade \ |
|
2003 | 2003 | > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories=yes \ |
|
2004 | 2004 | > --config format.use-dirstate-v2=no |
|
2005 | 2005 | automatically downgrading repository from the `dirstate-v2` feature |
|
2006 | 2006 | (see `hg help config.format.use-dirstate-v2` for details) |
|
2007 | 2007 | $ hg debugformat -R auto-upgrade | grep dirstate-v2 |
|
2008 | 2008 | dirstate-v2: no |
|
2009 | 2009 | |
|
2010 | 2010 | |
|
2011 | 2011 | For multiple change at the same time |
|
2012 | 2012 | ------------------------------------ |
|
2013 | 2013 | |
|
2014 | 2014 | $ hg debugformat -R auto-upgrade | egrep '(dirstate-v2|tracked|share-safe)' |
|
2015 | 2015 | dirstate-v2: no |
|
2016 | 2016 | tracked-hint: yes |
|
2017 | 2017 | share-safe: no |
|
2018 | 2018 | |
|
2019 | 2019 | $ hg status -R auto-upgrade \ |
|
2020 | 2020 | > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories=yes \ |
|
2021 | 2021 | > --config format.use-dirstate-v2=yes \ |
|
2022 | 2022 | > --config format.use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories=yes \ |
|
2023 | 2023 | > --config format.use-dirstate-tracked-hint=no\ |
|
2024 | 2024 | > --config format.use-share-safe.automatic-upgrade-of-mismatching-repositories=yes \ |
|
2025 | 2025 | > --config format.use-share-safe=yes |
|
2026 | 2026 | automatically upgrading repository to the `dirstate-v2` feature |
|
2027 | 2027 | (see `hg help config.format.use-dirstate-v2` for details) |
|
2028 | 2028 | automatically upgrading repository to the `share-safe` feature |
|
2029 | 2029 | (see `hg help config.format.use-share-safe` for details) |
|
2030 | 2030 | automatically downgrading repository from the `tracked-hint` feature |
|
2031 | 2031 | (see `hg help config.format.use-dirstate-tracked-hint` for details) |
|
2032 | 2032 | $ hg debugformat -R auto-upgrade | egrep '(dirstate-v2|tracked|share-safe)' |
|
2033 | 2033 | dirstate-v2: yes |
|
2034 | 2034 | tracked-hint: no |
|
2035 | 2035 | share-safe: yes |
|
2036 | 2036 | |
|
2037 | 2037 | Quiet upgrade and downgrade |
|
2038 | 2038 | --------------------------- |
|
2039 | 2039 | |
|
2040 | 2040 | |
|
2041 | 2041 | $ hg debugformat -R auto-upgrade | egrep '(dirstate-v2|tracked|share-safe)' |
|
2042 | 2042 | dirstate-v2: yes |
|
2043 | 2043 | tracked-hint: no |
|
2044 | 2044 | share-safe: yes |
|
2045 | 2045 | $ hg status -R auto-upgrade \ |
|
2046 | 2046 | > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories=yes \ |
|
2047 | 2047 | > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet=yes \ |
|
2048 | 2048 | > --config format.use-dirstate-v2=no \ |
|
2049 | 2049 | > --config format.use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories=yes \ |
|
2050 | 2050 | > --config format.use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet=yes \ |
|
2051 | 2051 | > --config format.use-dirstate-tracked-hint=yes \ |
|
2052 | 2052 | > --config format.use-share-safe.automatic-upgrade-of-mismatching-repositories=yes \ |
|
2053 | 2053 | > --config format.use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet=yes \ |
|
2054 | 2054 | > --config format.use-share-safe=no |
|
2055 | 2055 | |
|
2056 | 2056 | $ hg debugformat -R auto-upgrade | egrep '(dirstate-v2|tracked|share-safe)' |
|
2057 | 2057 | dirstate-v2: no |
|
2058 | 2058 | tracked-hint: yes |
|
2059 | 2059 | share-safe: no |
|
2060 | 2060 | |
|
2061 | 2061 | $ hg status -R auto-upgrade \ |
|
2062 | 2062 | > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories=yes \ |
|
2063 | 2063 | > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet=yes \ |
|
2064 | 2064 | > --config format.use-dirstate-v2=yes \ |
|
2065 | 2065 | > --config format.use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories=yes \ |
|
2066 | 2066 | > --config format.use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet=yes \ |
|
2067 | 2067 | > --config format.use-dirstate-tracked-hint=no\ |
|
2068 | 2068 | > --config format.use-share-safe.automatic-upgrade-of-mismatching-repositories=yes \ |
|
2069 | 2069 | > --config format.use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet=yes \ |
|
2070 | 2070 | > --config format.use-share-safe=yes |
|
2071 | 2071 | $ hg debugformat -R auto-upgrade | egrep '(dirstate-v2|tracked|share-safe)' |
|
2072 | 2072 | dirstate-v2: yes |
|
2073 | 2073 | tracked-hint: no |
|
2074 | 2074 | share-safe: yes |
|
2075 | 2075 | |
|
2076 | 2076 | Attempting Auto-upgrade on a read-only repository |
|
2077 | 2077 | ------------------------------------------------- |
|
2078 | 2078 | |
|
2079 | 2079 | $ chmod -R a-w auto-upgrade |
|
2080 | 2080 | |
|
2081 | 2081 | $ hg status -R auto-upgrade \ |
|
2082 | 2082 | > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories=yes \ |
|
2083 | 2083 | > --config format.use-dirstate-v2=no |
|
2084 | 2084 | $ hg debugformat -R auto-upgrade | grep dirstate-v2 |
|
2085 | 2085 | dirstate-v2: yes |
|
2086 | 2086 | |
|
2087 | 2087 | $ chmod -R u+w auto-upgrade |
|
2088 | 2088 | |
|
2089 | 2089 | Attempting Auto-upgrade on a locked repository |
|
2090 | 2090 | ---------------------------------------------- |
|
2091 | 2091 | |
|
2092 | 2092 | $ hg -R auto-upgrade debuglock --set-lock --quiet & |
|
2093 | 2093 | $ echo $! >> $DAEMON_PIDS |
|
2094 | 2094 | $ $RUNTESTDIR/testlib/wait-on-file 10 auto-upgrade/.hg/store/lock |
|
2095 | 2095 | $ hg status -R auto-upgrade \ |
|
2096 | 2096 | > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories=yes \ |
|
2097 | 2097 | > --config format.use-dirstate-v2=no |
|
2098 | 2098 | $ hg debugformat -R auto-upgrade | grep dirstate-v2 |
|
2099 | 2099 | dirstate-v2: yes |
|
2100 | 2100 | |
|
2101 | 2101 | $ killdaemons.py |
General Comments 0
You need to be logged in to leave comments.
Login now