在未使用 Mercurial 检出编辑时将文件设置为只读
Make files read-only when not checked out for editing with Mercurial
有没有办法让 Mercurial 将存储库的工作副本设为只读,并要求我在开始编辑文件之前明确告诉 Mercurial 我想编辑文件?
我不是询问有关锁定以防止并发编辑的问题,也不是有关防止意外更改进入存储库的问题。 这是为了防止工作副本本身发生意外的未提交更改。
我已经尝试创建一个批处理文件 checkout.bat 来删除只读文件属性和另一个 checkin.bat 提交更改并再次使文件只读,但是当您执行 hg 更新时,Hg 期望文件是可写的。
我知道这不是使用 Mercurial 的正常方式(让我们避免争论是否最好避免检出-编辑-检入模型)。但是切换到另一个版本控制系统不是一种选择。 (我在大多数项目中使用 TFS,但这个项目需要 Mercurial。)
每当对 Mercurial 存储库或工作副本执行某些操作时,都会调用许多 hooks。您需要的是一个 update
挂钩,理论上您可以在其中更改属性。
请注意,默认情况下挂钩是 "local",这意味着它们不会传播到存储库的克隆。要解决这个问题,有一个 ProjRc 扩展,您可以使用它来 "distribute" 挂钩设置。
您可能最好使用一对 preupdate
和 update
挂钩,其中第一个使存储库中的所有文件都可写,第二个使它们只读。
例如:
[hooks]
preupdate = hg files -0 | xargs -0 chmod u+w 2>/dev/null || true
update = hg files -0 | xargs -0 chmod u-w 2>/dev/null || true
因为您似乎在使用 Windows,Unix shell 脚本可能不是最佳解决方案,您可能必须恢复到 Python(使用 Python也将消除调用 hg
两次的开销)。这将是以下几行:
[hooks]
preupdate = python:.hg/pyhooks.py:make_writable
update = python:.hg/pyhooks.py:make_readonly
这需要 .hg
中的 pyhooks.py
文件,其中包含以下内容:
import os, stat
from mercurial import scmutil
def make_writable(ui, repo, hooktype, node=None, source=None, **kwargs):
ctx = scmutil.revsingle(repo, ".")
for f in ctx:
try:
perm = os.stat(f)[0]
os.chmod(f, perm | stat.S_IWUSR)
except:
pass
def make_readonly(ui, repo, hooktype, node=None, source=None, **kwargs):
ctx = scmutil.revsingle(repo, ".")
wflags = stat.S_IWUSR or stat.S_IWGRP or stat.S_IWOTH
for f in ctx:
try:
perm = os.stat(f)[0]
os.chmod(f, perm & ~wflags)
except:
pass
上面的代码仍然是为 Unix 编写的,但也应该适用于 Windows(至少根据文档,S_IWRITE == S_IWUSR
是唯一为 os.stat()
查看的标志os.chmod()
Windows).
您显然也可以通过调整挂钩中的路径将文件放在不同的位置。挂钩也不是存储库本身的一部分,如果您在其他地方克隆存储库,则必须将它们再次添加到您的 .hg/hgrc
文件中。
最后,请注意这里存在潜在的性能影响:这些挂钩每次更新都会更改存储库中 所有 文件的权限两次,这在大型存储库中可能代价高昂。
有没有办法让 Mercurial 将存储库的工作副本设为只读,并要求我在开始编辑文件之前明确告诉 Mercurial 我想编辑文件?
我不是询问有关锁定以防止并发编辑的问题,也不是有关防止意外更改进入存储库的问题。 这是为了防止工作副本本身发生意外的未提交更改。
我已经尝试创建一个批处理文件 checkout.bat 来删除只读文件属性和另一个 checkin.bat 提交更改并再次使文件只读,但是当您执行 hg 更新时,Hg 期望文件是可写的。
我知道这不是使用 Mercurial 的正常方式(让我们避免争论是否最好避免检出-编辑-检入模型)。但是切换到另一个版本控制系统不是一种选择。 (我在大多数项目中使用 TFS,但这个项目需要 Mercurial。)
每当对 Mercurial 存储库或工作副本执行某些操作时,都会调用许多 hooks。您需要的是一个 update
挂钩,理论上您可以在其中更改属性。
请注意,默认情况下挂钩是 "local",这意味着它们不会传播到存储库的克隆。要解决这个问题,有一个 ProjRc 扩展,您可以使用它来 "distribute" 挂钩设置。
您可能最好使用一对 preupdate
和 update
挂钩,其中第一个使存储库中的所有文件都可写,第二个使它们只读。
例如:
[hooks]
preupdate = hg files -0 | xargs -0 chmod u+w 2>/dev/null || true
update = hg files -0 | xargs -0 chmod u-w 2>/dev/null || true
因为您似乎在使用 Windows,Unix shell 脚本可能不是最佳解决方案,您可能必须恢复到 Python(使用 Python也将消除调用 hg
两次的开销)。这将是以下几行:
[hooks]
preupdate = python:.hg/pyhooks.py:make_writable
update = python:.hg/pyhooks.py:make_readonly
这需要 .hg
中的 pyhooks.py
文件,其中包含以下内容:
import os, stat
from mercurial import scmutil
def make_writable(ui, repo, hooktype, node=None, source=None, **kwargs):
ctx = scmutil.revsingle(repo, ".")
for f in ctx:
try:
perm = os.stat(f)[0]
os.chmod(f, perm | stat.S_IWUSR)
except:
pass
def make_readonly(ui, repo, hooktype, node=None, source=None, **kwargs):
ctx = scmutil.revsingle(repo, ".")
wflags = stat.S_IWUSR or stat.S_IWGRP or stat.S_IWOTH
for f in ctx:
try:
perm = os.stat(f)[0]
os.chmod(f, perm & ~wflags)
except:
pass
上面的代码仍然是为 Unix 编写的,但也应该适用于 Windows(至少根据文档,S_IWRITE == S_IWUSR
是唯一为 os.stat()
查看的标志os.chmod()
Windows).
您显然也可以通过调整挂钩中的路径将文件放在不同的位置。挂钩也不是存储库本身的一部分,如果您在其他地方克隆存储库,则必须将它们再次添加到您的 .hg/hgrc
文件中。
最后,请注意这里存在潜在的性能影响:这些挂钩每次更新都会更改存储库中 所有 文件的权限两次,这在大型存储库中可能代价高昂。