2020-01-31 05:40:49 +03:00
|
|
|
#require py2
|
2019-12-10 02:24:31 +03:00
|
|
|
#chg-compatible
|
|
|
|
|
2020-01-20 13:42:49 +03:00
|
|
|
$ disable treemanifest
|
2017-04-11 23:19:42 +03:00
|
|
|
$ SKIPREMOTEFILELOGCHECK=1
|
|
|
|
$ export SKIPREMOTEFILELOGCHECK
|
|
|
|
|
2020-01-11 05:59:42 +03:00
|
|
|
The fixcorrupt extension fixes pure revlog-based changelog. It is incompatible
|
|
|
|
with zstore-baked changelog.d:
|
|
|
|
|
|
|
|
$ setconfig format.use-zstore-commit-data=false
|
|
|
|
|
2017-04-11 23:19:42 +03:00
|
|
|
$ cat > noinline.py << EOF
|
2019-01-30 03:25:33 +03:00
|
|
|
> from edenscm.mercurial import revlog
|
2017-04-11 23:19:42 +03:00
|
|
|
> revlog.REVLOG_DEFAULT_FLAGS = 0
|
|
|
|
> revlog.REVLOG_DEFAULT_VERSION = revlog.REVLOG_DEFAULT_FORMAT
|
|
|
|
> EOF
|
|
|
|
|
|
|
|
$ cat >> $HGRCPATH << EOF
|
|
|
|
> [extensions]
|
|
|
|
> noinline=$TESTTMP/noinline.py
|
2018-01-09 14:06:09 +03:00
|
|
|
> fixcorrupt=
|
2017-04-11 23:19:42 +03:00
|
|
|
> 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
|
2020-02-18 20:36:04 +03:00
|
|
|
changelog: looks okay
|
|
|
|
manifest: looks okay
|
2017-04-11 23:19:42 +03:00
|
|
|
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)
|
2018-02-13 06:31:59 +03:00
|
|
|
changelog: will lose 3 revisions
|
2017-04-13 00:09:22 +03:00
|
|
|
truncating 00changelog.d from 275 to 110 bytes
|
|
|
|
truncating 00changelog.i from 320 to 128 bytes
|
2018-02-13 06:31:59 +03:00
|
|
|
manifest: will lose 3 revisions
|
2017-04-13 00:09:22 +03:00
|
|
|
truncating 00manifest.d from 264 to 99 bytes
|
|
|
|
truncating 00manifest.i from 320 to 128 bytes
|
2017-04-11 23:19:42 +03:00
|
|
|
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
|
2020-02-18 20:36:04 +03:00
|
|
|
changelog: looks okay
|
2017-04-11 23:19:42 +03:00
|
|
|
manifest: corrupted at rev 2 (linkrev=2)
|
2018-02-13 06:31:59 +03:00
|
|
|
changelog: will lose 3 revisions
|
2017-04-13 00:09:22 +03:00
|
|
|
truncating 00changelog.d from 275 to 110 bytes
|
|
|
|
truncating 00changelog.i from 320 to 128 bytes
|
2018-02-13 06:31:59 +03:00
|
|
|
manifest: will lose 3 revisions
|
2017-04-13 00:09:22 +03:00
|
|
|
truncating 00manifest.d from 264 to 99 bytes
|
|
|
|
truncating 00manifest.i from 320 to 128 bytes
|
2017-04-11 23:19:42 +03:00
|
|
|
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
|
2020-01-30 04:05:21 +03:00
|
|
|
> # PY3-compat
|
|
|
|
> stdin = sys.stdin.buffer if sys.version_info[0] >= 3 else sys.stdin
|
2017-04-11 23:19:42 +03:00
|
|
|
> s = hashlib.sha256()
|
2020-01-30 04:05:21 +03:00
|
|
|
> s.update(stdin.read())
|
2017-04-11 23:19:42 +03:00
|
|
|
> sys.stdout.write('%s' % s.hexdigest()[:8])
|
|
|
|
> EOF
|
|
|
|
|
2020-02-18 20:36:04 +03:00
|
|
|
$ ls .hg/store/truncate-backups | sort
|
2017-04-11 23:19:42 +03:00
|
|
|
*-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
|
2017-04-12 02:43:32 +03:00
|
|
|
*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)
|
2017-04-11 23:19:42 +03:00
|
|
|
|
|
|
|
$ 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: '
|
2020-02-18 20:36:04 +03:00
|
|
|
> cat .hg/store/$i .hg/store/truncate-backups/*-$i.backup* | $PYTHON sha256.py
|
2017-04-11 23:19:42 +03:00
|
|
|
> 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
|
2018-02-13 06:31:59 +03:00
|
|
|
|
|
|
|
Changelog.i ends with 0s
|
|
|
|
$ rebuildrepo
|
|
|
|
>>> with open('.hg/store/00changelog.i', 'ab') as f:
|
|
|
|
... f.write(b'\0' * 128)
|
|
|
|
$ hg debugfixcorrupt
|
|
|
|
changelog: corrupted at rev 5 (linkrev=0)
|
2020-02-18 20:36:04 +03:00
|
|
|
manifest: looks okay
|
2018-02-13 06:31:59 +03:00
|
|
|
changelog: will lose 2 revisions
|
|
|
|
truncating 00changelog.i from 448 to 320 bytes
|
|
|
|
re-run with --no-dryrun to fix.
|
|
|
|
|