1

背景

我正在尝试从 CVS 存储库中抢救代码。我正在reposurgeon为此目的使用,并且我尝试了以下工具来让自己git-fast-import流式传输:

  • cvs-fast-export, 出错(所谓的循环分支,但未提供详细信息)
  • cvs2git其次git-fast-export,它把事情混搭在了无法理解的范围之内
  • git-cvsimport其次是git-fast-export,它创造了迄今为止最好的结果,但最终也会把东西扔到他们不属于的树枝上。

此 CVS 存储库已在各种 CVS 版本上运行,并且标签和分支已被强制移动。我知道这意味着我不能再挽救那些分支和标签了。但就这样吧。

尽管如此,我有六个分支(在更多分支中),加上MAIN,我有兴趣在转换为git-fast-import流期间保留这些分支。我的目标 VCS不是Git,但关键是reposurgeon它以这种方式处理其输入并以这种方式输出。

为了理解工件并在预处理阶段通过rcs -o<rev>(当然是在我的 repo 的副本上)清理尽可能多的旧东西(包括孤立的修订版),我需要了解如何rcsfile格式工作的内部结构。

rcsfile.py修改模块后解析是小菜一碟rcsgrep。但这还没有为我提供任何有关修订号的信息,尤其是那些没有相应 delta+log 的修订号的含义。

我所看到的

根据RCS 文件手册页,不应该出现修订 ID 的第三段为 0 的情况。但我确实看到了这种情况。

这是我所做的(作为实验)。

  1. On MAIN: 提交文件 ( 1.1)
  2. MAIN: 分支到BranchX( 1.1)
  3. On BranchX: 更改文件 ( 1.1.2.1)
  4. On BranchX: 再次更改文件 ( 1.1.2.2)
  5. On MAIN: 更改文件 ( 1.2)
  6. On MAIN: 标记文件foobar( 1.2)
  7. MAIN: 分支到BranchX移动分支标记 ( 1.2),有效地将前一个分支孤立在1.1.2.x
  8. On BranchX: 删除文件 ( 1.2.2.1)
  9. On MAIN: 更改文件 ( 1.3)
  10. On MAIN: 强制标记文件foobar( 1.3)
  11. On MAIN: 更改文件 ( 1.4)
  12. On MAIN: 标记文件foobarbaz( 1.4)

正如您在上面的列表和下面完全复制的文件中看到的那样,没有1.2.0.2以带日志的 delta 形式进行的修订。

现在我的问题

如果我新分支修订版x.y(没有文件更改!),则生成的修订版 ID 为x.y.0.2. 这类似于我看到和询问的神秘修订 ID。

  • 是否0表明该文件没有增量,因此我必须返回其祖先以获取实际内容?
  • 还是 0 只是表示该分支的“根”,第四段是该分支的最新版本?

谁能阐明这些问题或指出比上面链接的手册页更全面的材料?


以下是完整的 RCS 文件:

head    1.4;
access;
symbols
    foobarbaz:1.3
    foobar:1.4
    BranchX:1.2.0.2;
locks; strict;
comment @# @;


1.4
date    2014.12.11.13.46.46;    author username;    state Exp;
branches;
next    1.3;

1.3
date    2014.12.11.13.44.49;    author username;    state Exp;
branches;
next    1.2;

1.2
date    2014.12.11.13.39.31;    author username;    state Exp;
branches
    1.2.2.1;
next    1.1;

1.1
date    2014.12.11.13.31.41;    author username;    state Exp;
branches
    1.1.2.1;
next    ;

1.1.2.1
date    2014.12.11.13.34.36;    author username;    state Exp;
branches;
next    1.1.2.2;

1.1.2.2
date    2014.12.11.13.35.08;    author username;    state Exp;
branches;
next    ;

1.2.2.1
date    2014.12.11.13.42.32;    author username;    state dead;
branches;
next    ;


desc
@@


1.4
log
@Change on MAIN
@
text
@NOTE: this file will be removed!

Another change on MAIN@


1.3
log
@Change on MAIN
@
text
@d3 1
a3 1
ANother change on MAIN@


1.2
log
@Change on MAIN
@
text
@d3 1
a3 1
File on MAIN will be forcibly tagged X again ... how does this affect the rev ID?@


1.2.2.1
log
@Removing the two files from X
@
text
@@


1.1
log
@Adding the experiment file
@
text
@d3 1
a3 1
Introducing file on MAIN@


1.1.2.1
log
@Changing the file on the X branch
@
text
@d3 1
a3 1
Changing on X branch@


1.1.2.2
log
@Another change on the X branch
@
text
@d3 1
a3 1
Another change on the X branch@
4

1 回答 1

1

好的,事实证明这个问题的答案深埋在 CVS 源代码中。

对于初学者来说,如果您正在查看 CVS 源代码树,这里是重要的文件:

  • src/rcs.c
  • src/rcs.h
  • doc/RCSFILES

除此之外,您还有rcsfile(5)手册页。并且不要忘记grep最大限度地使用(除非您有更复杂的东西可供使用)。

要点:

  • 分支修订由前三个(或更大的奇数)段定义,即x.y.z,例如1.1.2,它是修订的分支1.1
    • 这种分支的符号将指向修订版x.y.0.z,或1.1.0.2RCS_MAGIC_BRANCH其中 0 是CVS 代码中定义的魔法值。请注意,任何增量都不会将第三段设置为0,因为这些是“虚拟修订号”。
  • CVS z(分支修订的第三部分,虚拟修订号的第四部分)永远只会是等于或大于 2 的偶数
    • assert((z >= 2) && (z % 2 == 0))
  • 根据(见下文)1中的注释,还为供应商分支保留分支编号。rcs.h
  • 要检查分支,只需在symbolsRCS 文件的管理部分的列表中查看(例如rlog -h <file>,如果您不想解析它,请通过 )查找倒数第二段设置为0. 也就是说,您有一个与 (PCRE) 正则表达式匹配的修订版(?:\d+\.\d+\.)+0\.\d+(希望我猜对了)。

从评论中rcs.h

CVS 保留所有偶数分支供自己使用。“魔术”分支(请参阅rcs.c)作为虚拟修订号(仅在符号标签内)包含RCS_MAGIC_BRANCH0. CVS 还为供应商修订保留".1"分支。所以,如果你自己做分支,你应该限制使用从 . 开始的奇数分支号3

RCS_MAGIC_BRANCH使用areRCS_tag2rev()和的有趣函数RCS_gettag

从评论中rcs.c

评论RCS_magicrev()

返回一个“神奇”版本作为 RCS 文件的虚拟分支REV。“神奇”版本是 RCS 文件中唯一的版本。唯一的意思是我们返回一个修订版:

  • 有一个分支0(见rcs.h RCS_MAGIC_BRANCH
  • 有一个不是现有分支的修订组件REV
  • 有一个修订组件,它不是现有的魔法修订
  • 是一个偶数版本,以避免与供应商分支冲突。第一点是它“神奇”的原因。

例如,如果我们传入1.37as REV,我们将寻找一个名为 的现有分支1.37.2。如果它不存在,我们将寻找一个现有的符号标签,其数字部分等于1.37.0.2。如果那不存在,那么我们知道1.37.2可以通过创建一个符号标签来保留分支,并将其1.37.0.2作为数字部分。

[...]

注意:我们假设 REV 是 RCS 版本,而不是分支号。

答案

  • 是否0表明该文件没有增量,因此我必须返回其祖先以获取实际内容?
    • 基本上是的。当倒数第二个段是0时,修订号是一个虚拟修订号,用于为分支号进行“保留”。
  • 还是0简单地表示该分支的“根”,第四段是该分支的最新版本?
    • 不,见上文。
于 2014-12-11T21:46:34.737 回答