mirror of
https://github.com/facebook/sapling.git
synced 2024-10-11 01:07:15 +03:00
642dea7e2c
Summary: Update the fixcorrupt extension to look back as far as necessary in the revlog to find a good entry. Previously the user had to supply a good value using the --checklen argument. If --checklen was too small, fixcorrupt could end up trying to truncate in the middle of a corrupted section of the revlog, which would cause problems as it was still using corrupted data. This change ensures that fixcorrupt always looks back far enough to find a good entry. We start by looking at the last 10 entries, and double that amount each time the first item in the list is still bad. Test Plan: Used it to fix a corrupted fbsource repository where the corruption was 36 commits back. Reviewers: #mercurial, quark, stash Reviewed By: stash Subscribers: stash, net-systems-diffs@fb.com, yogeshwer, mjpieters Differential Revision: https://phabricator.intern.facebook.com/D4874243 Signature: t1:4874243:1492007518:7406b03a9967815a496a8c2fae394c5f21f7e60a
122 lines
3.4 KiB
Perl
122 lines
3.4 KiB
Perl
$ SKIPREMOTEFILELOGCHECK=1
|
|
$ export SKIPREMOTEFILELOGCHECK
|
|
|
|
$ cat > noinline.py << EOF
|
|
> from mercurial import revlog
|
|
> revlog.REVLOG_DEFAULT_FLAGS = 0
|
|
> revlog.REVLOG_DEFAULT_VERSION = revlog.REVLOG_DEFAULT_FORMAT
|
|
> EOF
|
|
|
|
$ cat >> $HGRCPATH << EOF
|
|
> [extensions]
|
|
> noinline=$TESTTMP/noinline.py
|
|
> fixcorrupt=$TESTDIR/../hgext3rd/fixcorrupt.py
|
|
> EOF
|
|
|
|
$ rebuildrepo() {
|
|
> cd $TESTTMP
|
|
> [ -d repo ] && rm -rf repo
|
|
> hg init repo
|
|
> cd repo
|
|
> for i in 1 2 3 4 5; do
|
|
> echo $i > $i
|
|
> hg commit -m $i -A $i
|
|
> done
|
|
> }
|
|
|
|
$ cat > rewrite.py <<EOF
|
|
> # change (sys.argv[2]) bytes at the end of (sys.argv[1]) file to zeros
|
|
> import sys
|
|
> path = sys.argv[1]
|
|
> n = int(sys.argv[2])
|
|
> with open(path, 'rb+') as f:
|
|
> f.seek(0, 2)
|
|
> filesize = f.tell()
|
|
> n = min(n, filesize)
|
|
> f.seek(filesize - n)
|
|
> f.write(b'\0' * n)
|
|
> EOF
|
|
|
|
$ corrupt() {
|
|
> $PYTHON $TESTTMP/rewrite.py .hg/store/"$1" "$2"
|
|
> }
|
|
|
|
Nothing wrong
|
|
|
|
$ rebuildrepo
|
|
$ hg debugfixcorrupt
|
|
changelog looks okay
|
|
manifest looks okay
|
|
nothing to do
|
|
[1]
|
|
|
|
Changelog corruption
|
|
|
|
$ corrupt 00changelog.d 150
|
|
$ hg verify -q 2>&1 | grep error
|
|
15 integrity errors encountered!
|
|
$ hg debugfixcorrupt --no-dryrun
|
|
changelog: corrupted at rev 2 (linkrev=2)
|
|
manifest: marked corrupted at rev 2 (linkrev=2)
|
|
changelog: will lose 2 revisions
|
|
truncating 00changelog.d from 275 to 110 bytes
|
|
truncating 00changelog.i from 320 to 128 bytes
|
|
manifest: will lose 2 revisions
|
|
truncating 00manifest.d from 264 to 99 bytes
|
|
truncating 00manifest.i from 320 to 128 bytes
|
|
fix completed. re-run to check more revisions.
|
|
$ hg verify -q 2>&1 | grep error
|
|
[1]
|
|
|
|
Manifest corruption
|
|
|
|
$ rebuildrepo
|
|
$ corrupt 00manifest.d 150
|
|
$ cp -R .hg/store .hg/store.bak
|
|
$ hg debugfixcorrupt --no-dryrun
|
|
changelog looks okay
|
|
manifest: corrupted at rev 2 (linkrev=2)
|
|
changelog: will lose 2 revisions
|
|
truncating 00changelog.d from 275 to 110 bytes
|
|
truncating 00changelog.i from 320 to 128 bytes
|
|
manifest: will lose 2 revisions
|
|
truncating 00manifest.d from 264 to 99 bytes
|
|
truncating 00manifest.i from 320 to 128 bytes
|
|
fix completed. re-run to check more revisions.
|
|
$ hg verify -q 2>&1 | grep error
|
|
[1]
|
|
|
|
Verify backups
|
|
|
|
$ cat > sha256.py << EOF
|
|
> import hashlib, sys
|
|
> s = hashlib.sha256()
|
|
> s.update(sys.stdin.read())
|
|
> sys.stdout.write('%s' % s.hexdigest()[:8])
|
|
> EOF
|
|
|
|
$ ls .hg/truncate-backups | sort
|
|
*-00changelog.d.backup-byte-110-to-275 (glob)
|
|
*-00changelog.i.backup-byte-128-to-320 (glob)
|
|
*-00manifest.d.backup-byte-99-to-264 (glob)
|
|
*-00manifest.i.backup-byte-128-to-320 (glob)
|
|
|
|
$ wc -c .hg/store/00changelog* .hg/store/00manifest* | sort
|
|
*99 .hg/store/00manifest.d (glob)
|
|
*110 .hg/store/00changelog.d (glob)
|
|
*128 .hg/store/00changelog.i (glob)
|
|
*128 .hg/store/00manifest.i (glob)
|
|
*465 total (glob)
|
|
|
|
$ for i in 00changelog.i 00changelog.d 00manifest.i 00manifest.d; do
|
|
> printf '%s: before fix: ' $i
|
|
> cat .hg/store.bak/$i | $PYTHON sha256.py
|
|
> printf ', restored from backup: '
|
|
> cat .hg/store/$i .hg/truncate-backups/*-$i.backup* | $PYTHON sha256.py
|
|
> printf '\n'
|
|
> done
|
|
00changelog.i: before fix: cd8b27c9, restored from backup: cd8b27c9
|
|
00changelog.d: before fix: 873f2076, restored from backup: 873f2076
|
|
00manifest.i: before fix: 1fbd16af, restored from backup: 1fbd16af
|
|
00manifest.d: before fix: 46207222, restored from backup: 46207222
|