检查当前目录是否在Mercurial下的最快方法是什么?

6
我正在尝试加快我的zsh主题提示,但hg检查比git慢一些。这导致在使用hg插件时显示提示较慢。
对于git,我们使用标准的git rev-parse --is-inside-work-tree,速度相当快。
对于hg,我尝试找到类似的命令,但没有一个像这个快:
  • hg --cwd $PWD root
  • hg summary
  • hg root
  • hg -q stat
所有这些命令都有效,但不如git rev-parse --is-inside-work-tree高效。
也尝试了这个小脚本,它是目前最好的。有什么方法可以使这个脚本运行得更快吗?
is_dir_hg() {
  local root="$(pwd -P)"
  while [[ $root && ! -d $root/.hg ]]
  do
    root="${root%/*}"
  done

  echo "$root"
}

请注意,该解决方案必须在不在根目录时也能检测到hg目录。
2个回答

6

我怀疑除非你编写一个等效的已编译程序,否则你无法比你的脚本做得更好。

Git的测试使用git rev-parse,它是用C编码并编译成简单的二进制文件,因此运行速度非常快。Mercurial的测试使用Python编码,因此需要支付Python启动开销。此外,您在Mercurial中加载的任何扩展都需要搜索扩展路径和额外的运行时加载,这使得Mercurial比Git更灵活但更慢。

如果hg root足够快,您可以运行hg rootgit rev-parse --show-toplevel(然后可能解析符号链接,如果需要),看看哪个更接近当前目录(再次解析符号链接),如果两者都成功。您可能已经尝试过这种方法,但速度不够快。

您可以采用自己的路径搜索,就像示例代码中所做的那样。但是,与其仅仅搜索.hg,您可以同时搜索.hg.git,并在找到其中一个时停止搜索。许多shell都有许多提示库,其中几个使用了这种方法。

所有方法都有一些错误风险,特别是因为可能在Mercurial存储库中包含Git存储库,反之亦然(例如,/path/to/current/working/dir可以在当前级别上是Mercurial,在dir级别上是Git,或反之亦然)。同时,.git目录的存在并不能保证您处于有效的Git工作树中。例如,Git仅在以下情况下认为目录是存储库:

  • 它可以找到Git目录本身(也许使用$GIT_DIR;Mercurial似乎没有像Git那样覆盖环境变量的方式;如果没有$GIT_DIR,从当前目录开始并根据需要向上爬);和
  • 找到的Git目录包含一个名为HEAD的文件;和
  • 找到的目录包含一个refs目录;和
  • $GIT_OBJECT_DIRECTORY指向一个目录,或者找到的目录包含一个objects/目录。

向上爬的搜索通常会测试并停止在挂载点,因此如果$HOME/foo是Git存储库,但您的当前工作目录是$HOME/foo/bar,这是一个挂载点,而且这不是Git存储库,Git将无法检测到$HOME/foo作为存储库。一个简单的shell路径搜索将检测到$HOME/foo作为存储库。

Mercurial默认只在每个父目录中查找.hg目录,因此您在这里更加稳妥。

请注意,您甚至可以拥有一个单独的目录,其中包含.hg.git子目录,两者都是有效的存储库(出于实验目的,我已经这样做过;它可以工作,只是有点棘手:您需要忽略其他VCS的控制文件)。这可能不是您需要处理的内容,这很好,因为没有明显正确的处理方式。 :-)


经过多次测试和搜索,这个小脚本似乎是我目前能做到的最快的。实际上比之前的要快得多,所以现在就这样吧。谢谢! - dguay

1
我会使用hg id命令,它可以很方便地返回有用的返回码。至少这样打起来很快 :-)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接