Show More
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
@@ -71,6 +71,7 b' from . import (' | |||||
71 | registrar, |
|
71 | registrar, | |
72 | repair, |
|
72 | repair, | |
73 | repoview, |
|
73 | repoview, | |
|
74 | requirements, | |||
74 | revlog, |
|
75 | revlog, | |
75 | revset, |
|
76 | revset, | |
76 | revsetlang, |
|
77 | revsetlang, | |
@@ -105,6 +106,7 b' from .utils import (' | |||||
105 | from .revlogutils import ( |
|
106 | from .revlogutils import ( | |
106 | deltas as deltautil, |
|
107 | deltas as deltautil, | |
107 | nodemap, |
|
108 | nodemap, | |
|
109 | rewrite, | |||
108 | sidedata, |
|
110 | sidedata, | |
109 | ) |
|
111 | ) | |
110 |
|
112 | |||
@@ -1451,6 +1453,63 b' def debugfileset(ui, repo, expr, **opts)' | |||||
1451 | ui.write(b"%s\n" % f) |
|
1453 | ui.write(b"%s\n" % f) | |
1452 |
|
1454 | |||
1453 |
|
1455 | |||
|
1456 | @command( | |||
|
1457 | b"debug-repair-issue6528", | |||
|
1458 | [ | |||
|
1459 | ( | |||
|
1460 | b'', | |||
|
1461 | b'to-report', | |||
|
1462 | b'', | |||
|
1463 | _(b'build a report of affected revisions to this file'), | |||
|
1464 | _(b'FILE'), | |||
|
1465 | ), | |||
|
1466 | ( | |||
|
1467 | b'', | |||
|
1468 | b'from-report', | |||
|
1469 | b'', | |||
|
1470 | _(b'repair revisions listed in this report file'), | |||
|
1471 | _(b'FILE'), | |||
|
1472 | ), | |||
|
1473 | ] | |||
|
1474 | + cmdutil.dryrunopts, | |||
|
1475 | ) | |||
|
1476 | def debug_repair_issue6528(ui, repo, **opts): | |||
|
1477 | """find affected revisions and repair them. See issue6528 for more details. | |||
|
1478 | ||||
|
1479 | The `--to-report` and `--from-report` flags allow you to cache and reuse the | |||
|
1480 | computation of affected revisions for a given repository across clones. | |||
|
1481 | The report format is line-based (with empty lines ignored): | |||
|
1482 | ||||
|
1483 | ``` | |||
|
1484 | <ascii-hex of the affected revision>,... <unencoded filelog index filename> | |||
|
1485 | ``` | |||
|
1486 | ||||
|
1487 | There can be multiple broken revisions per filelog, they are separated by | |||
|
1488 | a comma with no spaces. The only space is between the revision(s) and the | |||
|
1489 | filename. | |||
|
1490 | ||||
|
1491 | Note that this does *not* mean that this repairs future affected revisions, | |||
|
1492 | that needs a separate fix at the exchange level that hasn't been written yet | |||
|
1493 | (as of 5.9rc0). | |||
|
1494 | """ | |||
|
1495 | cmdutil.check_incompatible_arguments( | |||
|
1496 | opts, 'to_report', ['from_report', 'dry_run'] | |||
|
1497 | ) | |||
|
1498 | dry_run = opts.get('dry_run') | |||
|
1499 | to_report = opts.get('to_report') | |||
|
1500 | from_report = opts.get('from_report') | |||
|
1501 | # TODO maybe add filelog pattern and revision pattern parameters to help | |||
|
1502 | # narrow down the search for users that know what they're looking for? | |||
|
1503 | ||||
|
1504 | if requirements.REVLOGV1_REQUIREMENT not in repo.requirements: | |||
|
1505 | msg = b"can only repair revlogv1 repositories, v2 is not affected" | |||
|
1506 | raise error.Abort(_(msg)) | |||
|
1507 | ||||
|
1508 | rewrite.repair_issue6528( | |||
|
1509 | ui, repo, dry_run=dry_run, to_report=to_report, from_report=from_report | |||
|
1510 | ) | |||
|
1511 | ||||
|
1512 | ||||
1454 | @command(b'debugformat', [] + cmdutil.formatteropts) |
|
1513 | @command(b'debugformat', [] + cmdutil.formatteropts) | |
1455 | def debugformat(ui, repo, **opts): |
|
1514 | def debugformat(ui, repo, **opts): | |
1456 | """display format information about the current repository |
|
1515 | """display format information about the current repository |
@@ -7,6 +7,7 b'' | |||||
7 | # This software may be used and distributed according to the terms of the |
|
7 | # This software may be used and distributed according to the terms of the | |
8 | # GNU General Public License version 2 or any later version. |
|
8 | # GNU General Public License version 2 or any later version. | |
9 |
|
9 | |||
|
10 | import binascii | |||
10 | import contextlib |
|
11 | import contextlib | |
11 | import os |
|
12 | import os | |
12 |
|
13 | |||
@@ -472,3 +473,224 b' def _rewrite_censor(' | |||||
472 | new_index_file.write(entry_bin) |
|
473 | new_index_file.write(entry_bin) | |
473 | revlog._docket.index_end = new_index_file.tell() |
|
474 | revlog._docket.index_end = new_index_file.tell() | |
474 | revlog._docket.data_end = new_data_file.tell() |
|
475 | revlog._docket.data_end = new_data_file.tell() | |
|
476 | ||||
|
477 | ||||
|
478 | def _get_filename_from_filelog_index(path): | |||
|
479 | # Drop the extension and the `data/` prefix | |||
|
480 | path_part = path.rsplit(b'.', 1)[0].split(b'/', 1) | |||
|
481 | if len(path_part) < 2: | |||
|
482 | msg = _(b"cannot recognize filelog from filename: '%s'") | |||
|
483 | msg %= path | |||
|
484 | raise error.Abort(msg) | |||
|
485 | ||||
|
486 | return path_part[1] | |||
|
487 | ||||
|
488 | ||||
|
489 | def _filelog_from_filename(repo, path): | |||
|
490 | """Returns the filelog for the given `path`. Stolen from `engine.py`""" | |||
|
491 | ||||
|
492 | from .. import filelog # avoid cycle | |||
|
493 | ||||
|
494 | fl = filelog.filelog(repo.svfs, path) | |||
|
495 | return fl | |||
|
496 | ||||
|
497 | ||||
|
498 | def _write_swapped_parents(repo, rl, rev, offset, fp): | |||
|
499 | """Swaps p1 and p2 and overwrites the revlog entry for `rev` in `fp`""" | |||
|
500 | from ..pure import parsers # avoid cycle | |||
|
501 | ||||
|
502 | if repo._currentlock(repo._lockref) is None: | |||
|
503 | # Let's be paranoid about it | |||
|
504 | msg = "repo needs to be locked to rewrite parents" | |||
|
505 | raise error.ProgrammingError(msg) | |||
|
506 | ||||
|
507 | index_format = parsers.IndexObject.index_format | |||
|
508 | entry = rl.index[rev] | |||
|
509 | new_entry = list(entry) | |||
|
510 | new_entry[5], new_entry[6] = entry[6], entry[5] | |||
|
511 | packed = index_format.pack(*new_entry[:8]) | |||
|
512 | fp.seek(offset) | |||
|
513 | fp.write(packed) | |||
|
514 | ||||
|
515 | ||||
|
516 | def _reorder_filelog_parents(repo, fl, to_fix): | |||
|
517 | """ | |||
|
518 | Swaps p1 and p2 for all `to_fix` revisions of filelog `fl` and writes the | |||
|
519 | new version to disk, overwriting the old one with a rename. | |||
|
520 | """ | |||
|
521 | from ..pure import parsers # avoid cycle | |||
|
522 | ||||
|
523 | ui = repo.ui | |||
|
524 | assert len(to_fix) > 0 | |||
|
525 | rl = fl._revlog | |||
|
526 | if rl._format_version != constants.REVLOGV1: | |||
|
527 | msg = "expected version 1 revlog, got version '%d'" % rl._format_version | |||
|
528 | raise error.ProgrammingError(msg) | |||
|
529 | ||||
|
530 | index_file = rl._indexfile | |||
|
531 | new_file_path = index_file + b'.tmp-parents-fix' | |||
|
532 | repaired_msg = _(b"repaired revision %d of 'filelog %s'\n") | |||
|
533 | ||||
|
534 | with ui.uninterruptible(): | |||
|
535 | try: | |||
|
536 | util.copyfile( | |||
|
537 | rl.opener.join(index_file), | |||
|
538 | rl.opener.join(new_file_path), | |||
|
539 | checkambig=rl._checkambig, | |||
|
540 | ) | |||
|
541 | ||||
|
542 | with rl.opener(new_file_path, mode=b"r+") as fp: | |||
|
543 | if rl._inline: | |||
|
544 | index = parsers.InlinedIndexObject(fp.read()) | |||
|
545 | for rev in fl.revs(): | |||
|
546 | if rev in to_fix: | |||
|
547 | offset = index._calculate_index(rev) | |||
|
548 | _write_swapped_parents(repo, rl, rev, offset, fp) | |||
|
549 | ui.write(repaired_msg % (rev, index_file)) | |||
|
550 | else: | |||
|
551 | index_format = parsers.IndexObject.index_format | |||
|
552 | for rev in to_fix: | |||
|
553 | offset = rev * index_format.size | |||
|
554 | _write_swapped_parents(repo, rl, rev, offset, fp) | |||
|
555 | ui.write(repaired_msg % (rev, index_file)) | |||
|
556 | ||||
|
557 | rl.opener.rename(new_file_path, index_file) | |||
|
558 | rl.clearcaches() | |||
|
559 | rl._loadindex() | |||
|
560 | finally: | |||
|
561 | util.tryunlink(new_file_path) | |||
|
562 | ||||
|
563 | ||||
|
564 | def _is_revision_affected(ui, fl, filerev, path): | |||
|
565 | """Mercurial currently (5.9rc0) uses `p1 == nullrev and p2 != nullrev` as a | |||
|
566 | special meaning compared to the reverse in the context of filelog-based | |||
|
567 | copytracing. issue6528 exists because new code assumed that parent ordering | |||
|
568 | didn't matter, so this detects if the revision contains metadata (since | |||
|
569 | it's only used for filelog-based copytracing) and its parents are in the | |||
|
570 | "wrong" order.""" | |||
|
571 | try: | |||
|
572 | raw_text = fl.rawdata(filerev) | |||
|
573 | except error.CensoredNodeError: | |||
|
574 | # We don't care about censored nodes as they never carry metadata | |||
|
575 | return False | |||
|
576 | has_meta = raw_text.startswith(b'\x01\n') | |||
|
577 | if has_meta: | |||
|
578 | (p1, p2) = fl.parentrevs(filerev) | |||
|
579 | if p1 != nullrev and p2 == nullrev: | |||
|
580 | return True | |||
|
581 | return False | |||
|
582 | ||||
|
583 | ||||
|
584 | def _from_report(ui, repo, context, from_report, dry_run): | |||
|
585 | """ | |||
|
586 | Fix the revisions given in the `from_report` file, but still checks if the | |||
|
587 | revisions are indeed affected to prevent an unfortunate cyclic situation | |||
|
588 | where we'd swap well-ordered parents again. | |||
|
589 | ||||
|
590 | See the doc for `debug_fix_issue6528` for the format documentation. | |||
|
591 | """ | |||
|
592 | ui.write(_(b"loading report file '%s'\n") % from_report) | |||
|
593 | ||||
|
594 | with context(), open(from_report, mode='rb') as f: | |||
|
595 | for line in f.read().split(b'\n'): | |||
|
596 | if not line: | |||
|
597 | continue | |||
|
598 | filenodes, filename = line.split(b' ', 1) | |||
|
599 | fl = _filelog_from_filename(repo, filename) | |||
|
600 | to_fix = set( | |||
|
601 | fl.rev(binascii.unhexlify(n)) for n in filenodes.split(b',') | |||
|
602 | ) | |||
|
603 | excluded = set() | |||
|
604 | ||||
|
605 | for filerev in to_fix: | |||
|
606 | if _is_revision_affected(ui, fl, filerev, filename): | |||
|
607 | msg = b"found affected revision %d for filelog '%s'\n" | |||
|
608 | ui.warn(msg % (filerev, filename)) | |||
|
609 | else: | |||
|
610 | msg = _(b"revision %s of file '%s' is not affected\n") | |||
|
611 | msg %= (binascii.hexlify(fl.node(filerev)), filename) | |||
|
612 | ui.warn(msg) | |||
|
613 | excluded.add(filerev) | |||
|
614 | ||||
|
615 | to_fix = to_fix - excluded | |||
|
616 | if not to_fix: | |||
|
617 | msg = _(b"no affected revisions were found for '%s'\n") | |||
|
618 | ui.write(msg % filename) | |||
|
619 | continue | |||
|
620 | if not dry_run: | |||
|
621 | _reorder_filelog_parents(repo, fl, sorted(to_fix)) | |||
|
622 | ||||
|
623 | ||||
|
624 | def repair_issue6528(ui, repo, dry_run=False, to_report=None, from_report=None): | |||
|
625 | from .. import store # avoid cycle | |||
|
626 | ||||
|
627 | @contextlib.contextmanager | |||
|
628 | def context(): | |||
|
629 | if dry_run or to_report: # No need for locking | |||
|
630 | yield | |||
|
631 | else: | |||
|
632 | with repo.wlock(), repo.lock(): | |||
|
633 | yield | |||
|
634 | ||||
|
635 | if from_report: | |||
|
636 | return _from_report(ui, repo, context, from_report, dry_run) | |||
|
637 | ||||
|
638 | report_entries = [] | |||
|
639 | ||||
|
640 | with context(): | |||
|
641 | files = list( | |||
|
642 | (file_type, path) | |||
|
643 | for (file_type, path, _e, _s) in repo.store.datafiles() | |||
|
644 | if path.endswith(b'.i') and file_type & store.FILEFLAGS_FILELOG | |||
|
645 | ) | |||
|
646 | ||||
|
647 | progress = ui.makeprogress( | |||
|
648 | _(b"looking for affected revisions"), | |||
|
649 | unit=_(b"filelogs"), | |||
|
650 | total=len(files), | |||
|
651 | ) | |||
|
652 | found_nothing = True | |||
|
653 | ||||
|
654 | for file_type, path in files: | |||
|
655 | if ( | |||
|
656 | not path.endswith(b'.i') | |||
|
657 | or not file_type & store.FILEFLAGS_FILELOG | |||
|
658 | ): | |||
|
659 | continue | |||
|
660 | progress.increment() | |||
|
661 | filename = _get_filename_from_filelog_index(path) | |||
|
662 | fl = _filelog_from_filename(repo, filename) | |||
|
663 | ||||
|
664 | # Set of filerevs (or hex filenodes if `to_report`) that need fixing | |||
|
665 | to_fix = set() | |||
|
666 | for filerev in fl.revs(): | |||
|
667 | # TODO speed up by looking at the start of the delta | |||
|
668 | # If it hasn't changed, it's not worth looking at the other revs | |||
|
669 | # in the same chain | |||
|
670 | affected = _is_revision_affected(ui, fl, filerev, path) | |||
|
671 | if affected: | |||
|
672 | msg = b"found affected revision %d for filelog '%s'\n" | |||
|
673 | ui.warn(msg % (filerev, path)) | |||
|
674 | found_nothing = False | |||
|
675 | if not dry_run: | |||
|
676 | if to_report: | |||
|
677 | to_fix.add(binascii.hexlify(fl.node(filerev))) | |||
|
678 | else: | |||
|
679 | to_fix.add(filerev) | |||
|
680 | ||||
|
681 | if to_fix: | |||
|
682 | to_fix = sorted(to_fix) | |||
|
683 | if to_report: | |||
|
684 | report_entries.append((filename, to_fix)) | |||
|
685 | else: | |||
|
686 | _reorder_filelog_parents(repo, fl, to_fix) | |||
|
687 | ||||
|
688 | if found_nothing: | |||
|
689 | ui.write(_(b"no affected revisions were found\n")) | |||
|
690 | ||||
|
691 | if to_report and report_entries: | |||
|
692 | with open(to_report, mode="wb") as f: | |||
|
693 | for path, to_fix in report_entries: | |||
|
694 | f.write(b"%s %s\n" % (b",".join(to_fix), path)) | |||
|
695 | ||||
|
696 | progress.complete() |
@@ -74,6 +74,7 b' Do not show debug commands if there are ' | |||||
74 |
|
74 | |||
75 | Show debug commands if there are no other candidates |
|
75 | Show debug commands if there are no other candidates | |
76 | $ hg debugcomplete debug |
|
76 | $ hg debugcomplete debug | |
|
77 | debug-repair-issue6528 | |||
77 | debugancestor |
|
78 | debugancestor | |
78 | debugantivirusrunning |
|
79 | debugantivirusrunning | |
79 | debugapplystreamclonebundle |
|
80 | debugapplystreamclonebundle | |
@@ -266,6 +267,7 b' Show all commands + options' | |||||
266 | config: untrusted, exp-all-known, edit, local, source, shared, non-shared, global, template |
|
267 | config: untrusted, exp-all-known, edit, local, source, shared, non-shared, global, template | |
267 | continue: dry-run |
|
268 | continue: dry-run | |
268 | copy: forget, after, at-rev, force, include, exclude, dry-run |
|
269 | copy: forget, after, at-rev, force, include, exclude, dry-run | |
|
270 | debug-repair-issue6528: to-report, from-report, dry-run | |||
269 | debugancestor: |
|
271 | debugancestor: | |
270 | debugantivirusrunning: |
|
272 | debugantivirusrunning: | |
271 | debugapplystreamclonebundle: |
|
273 | debugapplystreamclonebundle: |
@@ -975,6 +975,9 b' Test list of internal help commands' | |||||
975 | $ hg help debug |
|
975 | $ hg help debug | |
976 | debug commands (internal and unsupported): |
|
976 | debug commands (internal and unsupported): | |
977 |
|
977 | |||
|
978 | debug-repair-issue6528 | |||
|
979 | find affected revisions and repair them. See issue6528 for more | |||
|
980 | details. | |||
978 | debugancestor |
|
981 | debugancestor | |
979 | find the ancestor revision of two revisions in a given index |
|
982 | find the ancestor revision of two revisions in a given index | |
980 | debugantivirusrunning |
|
983 | debugantivirusrunning |
@@ -3,7 +3,7 b' Test non-regression on the corruption as' | |||||
3 | =============================================================== |
|
3 | =============================================================== | |
4 |
|
4 | |||
5 | Setup |
|
5 | Setup | |
6 | ----- |
|
6 | ===== | |
7 |
|
7 | |||
8 | $ hg init base-repo |
|
8 | $ hg init base-repo | |
9 | $ cd base-repo |
|
9 | $ cd base-repo | |
@@ -93,7 +93,7 b' Check commit Graph' | |||||
93 |
|
93 | |||
94 |
|
94 | |||
95 | Check the lack of corruption |
|
95 | Check the lack of corruption | |
96 | ---------------------------- |
|
96 | ============================ | |
97 |
|
97 | |||
98 | $ hg clone --pull base-repo cloned |
|
98 | $ hg clone --pull base-repo cloned | |
99 | requesting all changes |
|
99 | requesting all changes | |
@@ -166,3 +166,249 b' Check commit Graph' | |||||
166 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
166 | date: Thu Jan 01 00:00:00 1970 +0000 | |
167 | summary: c_base_c - create a.txt |
|
167 | summary: c_base_c - create a.txt | |
168 |
|
168 | |||
|
169 | ||||
|
170 | Test the command that fixes the issue | |||
|
171 | ===================================== | |||
|
172 | ||||
|
173 | Restore a broken repository with multiple broken revisions and a filename that | |||
|
174 | would get encoded to test the `report` options. | |||
|
175 | It's a tarball because unbundle might magically fix the issue later. | |||
|
176 | ||||
|
177 | $ cd .. | |||
|
178 | $ mkdir repo-to-fix | |||
|
179 | $ cd repo-to-fix | |||
|
180 | #if windows | |||
|
181 | tar interprets `:` in paths (like `C:`) as being remote, force local on Windows | |||
|
182 | only since some versions of tar don't have this flag. | |||
|
183 | ||||
|
184 | $ tar --force-local -xf $TESTDIR/bundles/issue6528.tar | |||
|
185 | #else | |||
|
186 | $ tar xf $TESTDIR/bundles/issue6528.tar | |||
|
187 | #endif | |||
|
188 | ||||
|
189 | Check that the issue is present | |||
|
190 | $ hg st | |||
|
191 | M D.txt | |||
|
192 | M b.txt | |||
|
193 | $ hg debugrevlogindex b.txt | |||
|
194 | rev linkrev nodeid p1 p2 | |||
|
195 | 0 2 05b806ebe5ea 000000000000 000000000000 | |||
|
196 | 1 3 a58b36ad6b65 05b806ebe5ea 000000000000 | |||
|
197 | 2 6 216a5fe8b8ed 000000000000 000000000000 | |||
|
198 | 3 7 ea4f2f2463cc 216a5fe8b8ed 000000000000 | |||
|
199 | $ hg debugrevlogindex D.txt | |||
|
200 | rev linkrev nodeid p1 p2 | |||
|
201 | 0 6 2a8d3833f2fb 000000000000 000000000000 | |||
|
202 | 1 7 2a80419dfc31 2a8d3833f2fb 000000000000 | |||
|
203 | ||||
|
204 | Dry-run the fix | |||
|
205 | $ hg debug-repair-issue6528 --dry-run | |||
|
206 | found affected revision 1 for filelog 'data/D.txt.i' | |||
|
207 | found affected revision 1 for filelog 'data/b.txt.i' | |||
|
208 | found affected revision 3 for filelog 'data/b.txt.i' | |||
|
209 | $ hg st | |||
|
210 | M D.txt | |||
|
211 | M b.txt | |||
|
212 | $ hg debugrevlogindex b.txt | |||
|
213 | rev linkrev nodeid p1 p2 | |||
|
214 | 0 2 05b806ebe5ea 000000000000 000000000000 | |||
|
215 | 1 3 a58b36ad6b65 05b806ebe5ea 000000000000 | |||
|
216 | 2 6 216a5fe8b8ed 000000000000 000000000000 | |||
|
217 | 3 7 ea4f2f2463cc 216a5fe8b8ed 000000000000 | |||
|
218 | $ hg debugrevlogindex D.txt | |||
|
219 | rev linkrev nodeid p1 p2 | |||
|
220 | 0 6 2a8d3833f2fb 000000000000 000000000000 | |||
|
221 | 1 7 2a80419dfc31 2a8d3833f2fb 000000000000 | |||
|
222 | ||||
|
223 | Run the fix | |||
|
224 | $ hg debug-repair-issue6528 | |||
|
225 | found affected revision 1 for filelog 'data/D.txt.i' | |||
|
226 | repaired revision 1 of 'filelog data/D.txt.i' | |||
|
227 | found affected revision 1 for filelog 'data/b.txt.i' | |||
|
228 | found affected revision 3 for filelog 'data/b.txt.i' | |||
|
229 | repaired revision 1 of 'filelog data/b.txt.i' | |||
|
230 | repaired revision 3 of 'filelog data/b.txt.i' | |||
|
231 | ||||
|
232 | Check that the fix worked and that running it twice does nothing | |||
|
233 | $ hg st | |||
|
234 | $ hg debugrevlogindex b.txt | |||
|
235 | rev linkrev nodeid p1 p2 | |||
|
236 | 0 2 05b806ebe5ea 000000000000 000000000000 | |||
|
237 | 1 3 a58b36ad6b65 000000000000 05b806ebe5ea | |||
|
238 | 2 6 216a5fe8b8ed 000000000000 000000000000 | |||
|
239 | 3 7 ea4f2f2463cc 000000000000 216a5fe8b8ed | |||
|
240 | $ hg debugrevlogindex D.txt | |||
|
241 | rev linkrev nodeid p1 p2 | |||
|
242 | 0 6 2a8d3833f2fb 000000000000 000000000000 | |||
|
243 | 1 7 2a80419dfc31 000000000000 2a8d3833f2fb | |||
|
244 | $ hg debug-repair-issue6528 | |||
|
245 | no affected revisions were found | |||
|
246 | $ hg st | |||
|
247 | $ hg debugrevlogindex b.txt | |||
|
248 | rev linkrev nodeid p1 p2 | |||
|
249 | 0 2 05b806ebe5ea 000000000000 000000000000 | |||
|
250 | 1 3 a58b36ad6b65 000000000000 05b806ebe5ea | |||
|
251 | 2 6 216a5fe8b8ed 000000000000 000000000000 | |||
|
252 | 3 7 ea4f2f2463cc 000000000000 216a5fe8b8ed | |||
|
253 | $ hg debugrevlogindex D.txt | |||
|
254 | rev linkrev nodeid p1 p2 | |||
|
255 | 0 6 2a8d3833f2fb 000000000000 000000000000 | |||
|
256 | 1 7 2a80419dfc31 000000000000 2a8d3833f2fb | |||
|
257 | ||||
|
258 | Try the using the report options | |||
|
259 | -------------------------------- | |||
|
260 | ||||
|
261 | $ cd .. | |||
|
262 | $ mkdir repo-to-fix-report | |||
|
263 | $ cd repo-to-fix | |||
|
264 | #if windows | |||
|
265 | tar interprets `:` in paths (like `C:`) as being remote, force local on Windows | |||
|
266 | only since some versions of tar don't have this flag. | |||
|
267 | ||||
|
268 | $ tar --force-local -xf $TESTDIR/bundles/issue6528.tar | |||
|
269 | #else | |||
|
270 | $ tar xf $TESTDIR/bundles/issue6528.tar | |||
|
271 | #endif | |||
|
272 | ||||
|
273 | $ hg debug-repair-issue6528 --to-report $TESTTMP/report.txt | |||
|
274 | found affected revision 1 for filelog 'data/D.txt.i' | |||
|
275 | found affected revision 1 for filelog 'data/b.txt.i' | |||
|
276 | found affected revision 3 for filelog 'data/b.txt.i' | |||
|
277 | $ cat $TESTTMP/report.txt | |||
|
278 | 2a80419dfc31d7dfb308ac40f3f138282de7d73b D.txt | |||
|
279 | a58b36ad6b6545195952793099613c2116f3563b,ea4f2f2463cca5b29ddf3461012b8ce5c6dac175 b.txt | |||
|
280 | ||||
|
281 | $ hg debug-repair-issue6528 --from-report $TESTTMP/report.txt --dry-run | |||
|
282 | loading report file '$TESTTMP/report.txt' | |||
|
283 | found affected revision 1 for filelog 'D.txt' | |||
|
284 | found affected revision 1 for filelog 'b.txt' | |||
|
285 | found affected revision 3 for filelog 'b.txt' | |||
|
286 | $ hg st | |||
|
287 | M D.txt | |||
|
288 | M b.txt | |||
|
289 | $ hg debugrevlogindex b.txt | |||
|
290 | rev linkrev nodeid p1 p2 | |||
|
291 | 0 2 05b806ebe5ea 000000000000 000000000000 | |||
|
292 | 1 3 a58b36ad6b65 05b806ebe5ea 000000000000 | |||
|
293 | 2 6 216a5fe8b8ed 000000000000 000000000000 | |||
|
294 | 3 7 ea4f2f2463cc 216a5fe8b8ed 000000000000 | |||
|
295 | $ hg debugrevlogindex D.txt | |||
|
296 | rev linkrev nodeid p1 p2 | |||
|
297 | 0 6 2a8d3833f2fb 000000000000 000000000000 | |||
|
298 | 1 7 2a80419dfc31 2a8d3833f2fb 000000000000 | |||
|
299 | ||||
|
300 | $ hg debug-repair-issue6528 --from-report $TESTTMP/report.txt | |||
|
301 | loading report file '$TESTTMP/report.txt' | |||
|
302 | found affected revision 1 for filelog 'D.txt' | |||
|
303 | repaired revision 1 of 'filelog data/D.txt.i' | |||
|
304 | found affected revision 1 for filelog 'b.txt' | |||
|
305 | found affected revision 3 for filelog 'b.txt' | |||
|
306 | repaired revision 1 of 'filelog data/b.txt.i' | |||
|
307 | repaired revision 3 of 'filelog data/b.txt.i' | |||
|
308 | $ hg st | |||
|
309 | $ hg debugrevlogindex b.txt | |||
|
310 | rev linkrev nodeid p1 p2 | |||
|
311 | 0 2 05b806ebe5ea 000000000000 000000000000 | |||
|
312 | 1 3 a58b36ad6b65 000000000000 05b806ebe5ea | |||
|
313 | 2 6 216a5fe8b8ed 000000000000 000000000000 | |||
|
314 | 3 7 ea4f2f2463cc 000000000000 216a5fe8b8ed | |||
|
315 | $ hg debugrevlogindex D.txt | |||
|
316 | rev linkrev nodeid p1 p2 | |||
|
317 | 0 6 2a8d3833f2fb 000000000000 000000000000 | |||
|
318 | 1 7 2a80419dfc31 000000000000 2a8d3833f2fb | |||
|
319 | ||||
|
320 | Check that the revision is not "fixed" again | |||
|
321 | ||||
|
322 | $ hg debug-repair-issue6528 --from-report $TESTTMP/report.txt | |||
|
323 | loading report file '$TESTTMP/report.txt' | |||
|
324 | revision 2a80419dfc31d7dfb308ac40f3f138282de7d73b of file 'D.txt' is not affected | |||
|
325 | no affected revisions were found for 'D.txt' | |||
|
326 | revision a58b36ad6b6545195952793099613c2116f3563b of file 'b.txt' is not affected | |||
|
327 | revision ea4f2f2463cca5b29ddf3461012b8ce5c6dac175 of file 'b.txt' is not affected | |||
|
328 | no affected revisions were found for 'b.txt' | |||
|
329 | $ hg st | |||
|
330 | $ hg debugrevlogindex b.txt | |||
|
331 | rev linkrev nodeid p1 p2 | |||
|
332 | 0 2 05b806ebe5ea 000000000000 000000000000 | |||
|
333 | 1 3 a58b36ad6b65 000000000000 05b806ebe5ea | |||
|
334 | 2 6 216a5fe8b8ed 000000000000 000000000000 | |||
|
335 | 3 7 ea4f2f2463cc 000000000000 216a5fe8b8ed | |||
|
336 | $ hg debugrevlogindex D.txt | |||
|
337 | rev linkrev nodeid p1 p2 | |||
|
338 | 0 6 2a8d3833f2fb 000000000000 000000000000 | |||
|
339 | 1 7 2a80419dfc31 000000000000 2a8d3833f2fb | |||
|
340 | ||||
|
341 | Try it with a non-inline revlog | |||
|
342 | ------------------------------- | |||
|
343 | ||||
|
344 | $ cd .. | |||
|
345 | $ mkdir $TESTTMP/ext | |||
|
346 | $ cat << EOF > $TESTTMP/ext/small_inline.py | |||
|
347 | > from mercurial import revlog | |||
|
348 | > revlog._maxinline = 8 | |||
|
349 | > EOF | |||
|
350 | ||||
|
351 | $ cat << EOF >> $HGRCPATH | |||
|
352 | > [extensions] | |||
|
353 | > small_inline=$TESTTMP/ext/small_inline.py | |||
|
354 | > EOF | |||
|
355 | ||||
|
356 | $ mkdir repo-to-fix-not-inline | |||
|
357 | $ cd repo-to-fix-not-inline | |||
|
358 | #if windows | |||
|
359 | tar interprets `:` in paths (like `C:`) as being remote, force local on Windows | |||
|
360 | only since some versions of tar don't have this flag. | |||
|
361 | ||||
|
362 | $ tar --force-local -xf $TESTDIR/bundles/issue6528.tar | |||
|
363 | #else | |||
|
364 | $ tar xf $TESTDIR/bundles/issue6528.tar | |||
|
365 | #endif | |||
|
366 | $ echo b >> b.txt | |||
|
367 | $ hg commit -qm "inline -> separate" | |||
|
368 | $ find .hg -name *b.txt.d | |||
|
369 | .hg/store/data/b.txt.d | |||
|
370 | ||||
|
371 | Status is correct, but the problem is still there, in the earlier revision | |||
|
372 | $ hg st | |||
|
373 | $ hg up 3 | |||
|
374 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved | |||
|
375 | $ hg st | |||
|
376 | M b.txt | |||
|
377 | $ hg debugrevlogindex b.txt | |||
|
378 | rev linkrev nodeid p1 p2 | |||
|
379 | 0 2 05b806ebe5ea 000000000000 000000000000 | |||
|
380 | 1 3 a58b36ad6b65 05b806ebe5ea 000000000000 | |||
|
381 | 2 6 216a5fe8b8ed 000000000000 000000000000 | |||
|
382 | 3 7 ea4f2f2463cc 216a5fe8b8ed 000000000000 | |||
|
383 | 4 8 db234885e2fe ea4f2f2463cc 000000000000 | |||
|
384 | $ hg debugrevlogindex D.txt | |||
|
385 | rev linkrev nodeid p1 p2 | |||
|
386 | 0 6 2a8d3833f2fb 000000000000 000000000000 | |||
|
387 | 1 7 2a80419dfc31 2a8d3833f2fb 000000000000 | |||
|
388 | 2 8 65aecc89bb5d 2a80419dfc31 000000000000 | |||
|
389 | ||||
|
390 | Run the fix on the non-inline revlog | |||
|
391 | $ hg debug-repair-issue6528 | |||
|
392 | found affected revision 1 for filelog 'data/D.txt.i' | |||
|
393 | repaired revision 1 of 'filelog data/D.txt.i' | |||
|
394 | found affected revision 1 for filelog 'data/b.txt.i' | |||
|
395 | found affected revision 3 for filelog 'data/b.txt.i' | |||
|
396 | repaired revision 1 of 'filelog data/b.txt.i' | |||
|
397 | repaired revision 3 of 'filelog data/b.txt.i' | |||
|
398 | ||||
|
399 | Check that it worked | |||
|
400 | $ hg debugrevlogindex b.txt | |||
|
401 | rev linkrev nodeid p1 p2 | |||
|
402 | 0 2 05b806ebe5ea 000000000000 000000000000 | |||
|
403 | 1 3 a58b36ad6b65 000000000000 05b806ebe5ea | |||
|
404 | 2 6 216a5fe8b8ed 000000000000 000000000000 | |||
|
405 | 3 7 ea4f2f2463cc 000000000000 216a5fe8b8ed | |||
|
406 | 4 8 db234885e2fe ea4f2f2463cc 000000000000 | |||
|
407 | $ hg debugrevlogindex D.txt | |||
|
408 | rev linkrev nodeid p1 p2 | |||
|
409 | 0 6 2a8d3833f2fb 000000000000 000000000000 | |||
|
410 | 1 7 2a80419dfc31 000000000000 2a8d3833f2fb | |||
|
411 | 2 8 65aecc89bb5d 2a80419dfc31 000000000000 | |||
|
412 | $ hg debug-repair-issue6528 | |||
|
413 | no affected revisions were found | |||
|
414 | $ hg st |
General Comments 0
You need to be logged in to leave comments.
Login now