
这种损坏是与项目的历史记录相关的,尤其是与 .hg/store 中的文件相关。这种损坏可能由多种原因引起,大部分情况下是由用户的错误操作(比如,删除其文件名中包含'foo.c'的所有文件)引起的。例如:
crosschecking files in changesets and manifests
1213 files, 8591 changesets, 17158 total revisions
$ rm .hg/store/data/mercurial/error.py.i # 注意,做了错事了!
crosschecking files in changesets and manifests
data/mercurial/error.py.i@7633: missing revlog!
7633: empty or missing mercurial/error.py
mercurial/error.py@7633: f6aad9f78a08 in manifests not found
mercurial/error.py@7636: 4fb29207f327 in manifests not found
mercurial/error.py@7637: 3bfff9613e8b in manifests not found
mercurial/error.py@7640: 40ee894622ad in manifests not found
mercurial/error.py@7641: e640820306d6 in manifests not found
mercurial/error.py@7643: f43c616251f5 in manifests not found
mercurial/error.py@7644: 455d738b74c7 in manifests not found
mercurial/error.py@7646: a3128b43b03f in manifests not found
mercurial/error.py@7947: b4a8b72bfa1c in manifests not found
mercurial/error.py@8144: 1f996809c441 in manifests not found
mercurial/error.py@8225: e1537136a8d0 in manifests not found
mercurial/error.py@8226: 5f91269779c0 in manifests not found
mercurial/error.py@8227: 6706abc98ab2 in manifests not found
1213 files, 8591 changesets, 17145 total revisions
15 integrity errors encountered!
(first damaged changeset appears to be 7633)
在这个例子中,我们损坏了仓库中从修订版本7633(注意看输出中的最后一行)开始的记录。好在Mercurial 中对于历史信息都是采用追加的形式来记录的,所以,我们可以使用以下命令来将仓库恢复到出问题之前的那个点:
$ hg clone -r 7632 damage fixed
added 7633 changesets with 14944 changes to 1126 files
964 files updated, 0 files merged, 0 files removed, 0 files unresolved
crosschecking files in changesets and manifests
1126 files, 7633 changesets, 14944 total revisions
我们还可以使用'pull -r'来渐进式地尝试每次将更大的一组修订集拉取到一个包含有其中某些被丢失的文件的修订记录的仓库中去。还可能可以从某个备份仓库中将这里被损坏的变更记录(revlog)文件的完整副本复制出来。
在少数情况下,只有某个包含着单条变更记录的记录文件被损坏。如果妳还在别处有着那个变更文件的 精确副本 ( exact copy )的话(假设它位于 mybackuplocation ,我们稍后将用到),那么,这种情况就狠容易手动重新构造。举个例子,假设有一个仓库,名为"broken",其中根目录的变更记录文件"f2.i"已经丢失:
crosschecking files in changesets and manifests
f2@1: 5266937d3e5f in manifests not found
3 files, 3 changesets, 2 total revisions
3 integrity errors encountered!
(first damaged changeset appears to be 1)
注意,"@1"表示所丢失的变更记录文件是在变更集(changeset)1中被引用的。为了重新构造这个文件,我们需要创建一个新的仓库,以重新制造出那次提交过程中的条件。(在复制仓库(cloning)时,妳可能需要修改复制命令,以确保新的仓库与已有的仓库具有相同的 仓库格式 。)
$ hg clone -r 0 broken fix # 比被损坏的变更集的编号小1
现在,我们已经创建了一个新的"f2.i",其中包含着单条变更记录,并且被标记为属于变更集1.现在我们可以将这个文件复制到被损坏的仓库中去了:
$ cp .hg/store/data/f2.i ../broken/.hg/store/data/f2.i
crosschecking files in changesets and manifests
3 files, 3 changesets, 3 total revisions
妳可能需要编辑 .hg/store/fncache 以让verify命令知道妳在这里重新引入的文件的存在。
如果想要修复的变更记录是某个已被应用的补丁队列中的一部分,那么,修复过程将会更加复杂,因为,从备份仓库中复制出来的索引文件将会引用到错误的变更集:
crosschecking files in changesets and manifests
f2@?: rev 0 points to unexpected changeset 2
3 files, 3 changesets, 2 total revisions
2 integrity errors encountered!
(first damaged changeset appears to be 3)
对于这种情况,可以使用以下Python 脚本来直接编辑索引文件中的引用目标,以便修复:
f = open('.hg/store/data/f2.i', 'r+')
unpacked_index = list(struct.unpack(revlog.indexformatng, raw[:64]))
unpacked_index[4] = 3 # 使用妳自己的“预期的变更集编号”替换这里的值
new_raw = struct.pack(revlog.indexformatng, *unpacked_index)
注意:索引文件的格式在这个文档中有说明: http://selenic.com/repo/hg-stable/file/tip/mercurial/revlog.py#l156
或者,妳可以试着使用convert 扩展来强制重新构建整个仓库。首先要警告妳,这种操作会导致所有的变更记录的散列制发生改变,并且要求 所有用户 都要从修复后的仓库中重新复制副本 。
第一步就是启用convert扩展,假设仓库位于REPO 目录中:
尽管是有可能在原地恢复(convert)的,但是,为了安全起见,妳最好还是恢复到一个空白的目录中去:
$ hg convert --config convert.hg.ignoreerrors=True REPO REPOFIX
ignoring: data/.DS_Store.i@26a47e9188c: no match found
.hgtags@78ff9079978f, line 1: tag '1.0b1' refers to unknown node
当妳执行这个命令时,看到的输出应该会跟这里示例的有狠大的不同,但是,最重要的一点就是,损坏的文件已被忽略,其它的文件会进入到新的仓库中。
如果妳仍然遇到了错误(abort),那么,妳可以绕过它,具体做法就是删除 .hg/store/data/{corrupted-file}.i 。在尝试对仓库进行修改之前,要做备份。
雞排妹
HxLauncher: Launch Android applications by voice commands