如果我在Libgit2Sharp中执行Index.Stage()然后执行Commit(),是否存在竞争条件?

时间:2013-09-02 09:31:02

标签: git libgit2sharp

在我的示例代码中,我这样做(在Windows上):

var repo = new Repository(command.RepoFolder);
for (int i = 0; i < 100; i++)
{
  string file = command.RepoFolder + "\\text.txt";
  File.WriteAllText(file, string.Format("File number {0}, written at {1}", i, DateTime.Now));

  repo.Index.Stage("text.txt");
  repo.Commit(string.Format("Written version {0}", i), new Signature("me through code", "email@email.com", DateTimeOffset.Now));
}

如果我使用调试器逐步执行此序列,则每个循环运行循环都会在text.txt文件中创建一个具有预期checge的新提交以及相应的提交消息。 但是,如果我在不阻塞它的情况下运行它,我会得到100次提交,包含预期的提交消息,但只有一些提交有真正的文件更改。它们通常具有以下形式:

- File number 54, written at 8/30/2013 10:27:38 AM
+ File number 88, written at 8/30/2013 10:27:39 AM

因此,似乎repo.Index.Stage()异步发生,并且在注意到文件系统更改之前完成提交。那是预期的吗?这是“活泼的git”行为吗?在Libgit2Sharp中是否有一种方法可以明确地等待索引获取更改?

另外:

  1. 如果我对文件进行追加而不是使用不同的行重写,一切正常
  2. 如果我使用git.exe在命令行上做同样的事情,我看不到这样的行为

2 个答案:

答案 0 :(得分:4)

LibGit2Sharp repo.Index.Stage()依赖于libgit2 diffing功能来确定哪些文件已在workdir中修改过,哪些文件没有。

在进行差异处理时,在比较实际文件内容之前,libgit2依赖于一些“技巧”来检查文件是否已被更改。例如:

  • 如果文件在索引和workdir中具有相同的大小
  • 如果文件修改日期/时间相同(窗口上的秒精度时间)
  • 以及其他属性(文件所有者,模式,...)是否相同

然后该文件被视为未修改,并且根本不会打开它以查看内容是否相同。这允许对具有数千个文件的大型回购进行大的优化。

在您的情况下,您的许多文件具有相同的大小和相同的修改日期/时间,这就是repo.Index.Stage()未提取这些文件的原因。


可能(脏)的解决方法是在修改之间添加Thread.Sleep(TimeSpan.FromSeconds(1));


处理同一问题的错误报告在LibGit2Sharp错误跟踪器上有recently been opened。如果您有关于此主题的真实示例或意见,请随意权衡!

答案 1 :(得分:1)

我遇到了同样的问题,但是Thread.Sleep技巧对我不起作用,不管我等了多久,但这确实

File.SetLastWriteTime(filePath, DateTime.UtcNow.AddHours(-1));