symlinks: add gating for Windows symlinks through store requirements

Summary: This should allow in later diffs to enable symlinks on Windows if users have `windowssymlinks` on their repo store requirements. Additionally, it adds the aforementioned requirement to new repos cloned with the `symlinks.force-enable` config.

Reviewed By: muirdm

Differential Revision: D43456961

fbshipit-source-id: bd2f5a1cb6c3b647ebccb0de556959758a4d7fe2
This commit is contained in:
Saul Gutierrez 2023-03-16 07:33:58 -07:00 committed by Facebook GitHub Bot
parent 0d039f7f25
commit e091385d09
5 changed files with 36 additions and 9 deletions

View File

@ -267,6 +267,8 @@ class dirstate(object):
@util.propertycache
def _checklink(self) -> bool:
if pycompat.iswindows and "windowssymlinks" not in self._repo.requirements:
return False
return util.checklink(self._root)
@util.propertycache

View File

@ -280,8 +280,13 @@ def share(
checkout = None
sharedpath = srcrepo.sharedpath # if our source is already sharing
requirements = srcrepo.requirements.copy()
destwvfs = vfsmod.vfs(dest, realpath=True)
destwvfs = vfsmod.vfs(
dest,
realpath=True,
disablesymlinks=pycompat.iswindows and "windowssymlinks" not in requirements,
)
destvfs = vfsmod.vfs(
os.path.join(destwvfs.base, ui.identity.dotdir()), realpath=True
)
@ -293,8 +298,6 @@ def share(
destwvfs.mkdir()
destvfs.makedir()
requirements = srcrepo.requirements.copy()
if relative:
try:
sharedpath = os.path.relpath(sharedpath, destvfs.base)

View File

@ -336,6 +336,8 @@ class localrepository(object):
"treestate",
"storerequirements",
"lfs",
# enable symlinks on Windows
"windowssymlinks",
}
_basestoresupported = {
"visibleheads",
@ -428,9 +430,7 @@ class localrepository(object):
self.requirements = set()
self.storerequirements = set()
# wvfs: rooted at the repository root, used to access the working copy
self.wvfs = vfsmod.vfs(path, expandpath=True, realpath=True, cacheaudited=False)
self.root = self.wvfs.base
self.root = os.path.realpath(util.expandpath(path))
self.baseui = baseui
self.ui = baseui.copy()
@ -468,9 +468,6 @@ class localrepository(object):
self._loadextensions()
cacheaudited = self.ui.configbool("unsafe", "wvfsauditorcache")
self.wvfs.audit._cached = cacheaudited
self.supported = self._featuresetup(self.featuresetupfuncs, self._basesupported)
self.storesupported = self._featuresetup(
self.storefeaturesetupfuncs, self._basestoresupported
@ -489,6 +486,21 @@ class localrepository(object):
if inst.errno != errno.ENOENT:
raise
# wvfs: rooted at the repository root, used to access the working copy
disablesymlinks = (
pycompat.iswindows and "windowssymlinks" not in self.requirements
)
self.wvfs = vfsmod.vfs(
path,
expandpath=True,
realpath=True,
cacheaudited=False,
disablesymlinks=disablesymlinks,
)
cacheaudited = self.ui.configbool("unsafe", "wvfsauditorcache")
self.wvfs.audit._cached = cacheaudited
cachepath = self.localvfs.join("cache")
self.sharedpath = self.path
self.sharedroot = self.root

View File

@ -411,6 +411,7 @@ class vfs(abstractvfs):
cacheaudited: bool = False,
expandpath: bool = False,
realpath: bool = False,
disablesymlinks: bool = False,
) -> None:
if expandpath:
base = util.expandpath(base)
@ -424,9 +425,12 @@ class vfs(abstractvfs):
self.audit = lambda path, mode=None: True
self.createmode = None
self._trustnlink = None
self._disablesymlinks = disablesymlinks
@util.propertycache
def _cansymlink(self) -> bool:
if self._disablesymlinks:
return False
return util.checklink(self.base)
@util.propertycache

View File

@ -137,6 +137,12 @@ fn write_requirements(path: &Path, config: &ConfigSet) -> Result<(), InitError>
{
requirements.insert("generaldelta");
}
if config
.get_or_default("experimental", "windows-symlinks")
.unwrap_or_default()
{
requirements.insert("windowssymlinks");
}
write_requirements_file(path, requirements)
}