mirror of
https://github.com/facebook/sapling.git
synced 2024-10-06 23:07:18 +03:00
Ignore redirection for nested mount
Summary: Currently eden redirection list will list all redirections include its nested mounts and redirection in the nested mounts. It is better to ignore the nested mounts and redirection in the nested mounts if list redirection from its ancestor mount. Reviewed By: chadaustin Differential Revision: D34156017 fbshipit-source-id: ba3ed5e6b5c79b4a62034f5f8563705cf886a44d
This commit is contained in:
parent
9c903e35f2
commit
211e0f9dc5
@ -22,7 +22,7 @@ def check_redirections(
|
|||||||
checkout: EdenCheckout,
|
checkout: EdenCheckout,
|
||||||
mount_table: mtab.MountTable,
|
mount_table: mtab.MountTable,
|
||||||
) -> None:
|
) -> None:
|
||||||
redirs = get_effective_redirections(checkout, mount_table)
|
redirs = get_effective_redirections(checkout, mount_table, instance)
|
||||||
|
|
||||||
for redir in redirs.values():
|
for redir in redirs.values():
|
||||||
if redir.state == RedirectionState.MATCHES_CONFIGURATION:
|
if redir.state == RedirectionState.MATCHES_CONFIGURATION:
|
||||||
|
@ -244,7 +244,7 @@ files outside the repo rather than to ignore and clean them up.\n""",
|
|||||||
|
|
||||||
for mount in mounts:
|
for mount in mounts:
|
||||||
instance, checkout, _rel_path = require_checkout(args, mount)
|
instance, checkout, _rel_path = require_checkout(args, mount)
|
||||||
self.usage_for_redirections(checkout, all_redirections, clean)
|
self.usage_for_redirections(checkout, all_redirections, clean, instance)
|
||||||
|
|
||||||
if not all_redirections:
|
if not all_redirections:
|
||||||
self.writeln_ui("No redirection")
|
self.writeln_ui("No redirection")
|
||||||
@ -461,9 +461,15 @@ space by running:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def usage_for_redirections(
|
def usage_for_redirections(
|
||||||
self, checkout: EdenCheckout, redirection_repos: Set[str], clean: bool
|
self,
|
||||||
|
checkout: EdenCheckout,
|
||||||
|
redirection_repos: Set[str],
|
||||||
|
clean: bool,
|
||||||
|
instance: EdenInstance,
|
||||||
) -> None:
|
) -> None:
|
||||||
redirections = redirect_mod.get_effective_redirections(checkout, mtab.new())
|
redirections = redirect_mod.get_effective_redirections(
|
||||||
|
checkout, mtab.new(), instance
|
||||||
|
)
|
||||||
seen_paths = set()
|
seen_paths = set()
|
||||||
if len(redirections) > 0:
|
if len(redirections) > 0:
|
||||||
for redir in redirections.values():
|
for redir in redirections.values():
|
||||||
@ -1287,7 +1293,7 @@ class ChownCmd(Subcmd):
|
|||||||
|
|
||||||
if not args.skip_redirection:
|
if not args.skip_redirection:
|
||||||
for redir in redirect_mod.get_effective_redirections(
|
for redir in redirect_mod.get_effective_redirections(
|
||||||
checkout, mtab.new()
|
checkout, mtab.new(), instance
|
||||||
).values():
|
).values():
|
||||||
target = redir.expand_target_abspath(checkout)
|
target = redir.expand_target_abspath(checkout)
|
||||||
print(f"Chowning redirection: {redir.repo_path}...", end="", flush=True)
|
print(f"Chowning redirection: {redir.repo_path}...", end="", flush=True)
|
||||||
|
@ -335,7 +335,7 @@ def print_eden_redirections(instance: EdenInstance, out: IO[bytes]) -> None:
|
|||||||
checkouts = instance.get_checkouts()
|
checkouts = instance.get_checkouts()
|
||||||
for checkout in checkouts:
|
for checkout in checkouts:
|
||||||
out.write(bytes(checkout.path) + b"\n")
|
out.write(bytes(checkout.path) + b"\n")
|
||||||
output = redirect_mod.prepare_redirection_list(checkout)
|
output = redirect_mod.prepare_redirection_list(checkout, instance)
|
||||||
# append a tab at the beginning of every new line to indent
|
# append a tab at the beginning of every new line to indent
|
||||||
output = output.replace("\n", "\n\t")
|
output = output.replace("\n", "\n\t")
|
||||||
out.write(b"\t" + output.encode() + b"\n")
|
out.write(b"\t" + output.encode() + b"\n")
|
||||||
|
@ -16,7 +16,7 @@ import stat
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, Iterable, Optional
|
from typing import Set, Dict, Iterable, Optional
|
||||||
|
|
||||||
from thrift.Thrift import TApplicationException
|
from thrift.Thrift import TApplicationException
|
||||||
|
|
||||||
@ -493,8 +493,34 @@ def get_configured_redirections(checkout: EdenCheckout) -> Dict[str, Redirection
|
|||||||
return redirs
|
return redirs
|
||||||
|
|
||||||
|
|
||||||
|
def is_strict_subdir(base: bytes, sub_dir: bytes) -> bool:
|
||||||
|
return base != sub_dir and sub_dir.startswith(base)
|
||||||
|
|
||||||
|
|
||||||
|
def get_nested_mounts(instance: EdenInstance, checkout_path_bytes: bytes) -> Set[bytes]:
|
||||||
|
"""
|
||||||
|
Find out nested EdenFS mounts in the checkout path
|
||||||
|
"""
|
||||||
|
nested_mounts = set()
|
||||||
|
|
||||||
|
for eden_mount in instance.get_mount_paths():
|
||||||
|
eden_mount_path_byte = bytes(Path(eden_mount)) + b"/"
|
||||||
|
if is_strict_subdir(checkout_path_bytes, eden_mount_path_byte):
|
||||||
|
nested_mounts.add(eden_mount_path_byte)
|
||||||
|
return nested_mounts
|
||||||
|
|
||||||
|
|
||||||
|
def in_nested_mount(nested_mounts: Set[bytes], mount_point: bytes) -> bool:
|
||||||
|
for nested_mount in nested_mounts:
|
||||||
|
if os.path.realpath(nested_mount) == os.path.realpath(
|
||||||
|
mount_point
|
||||||
|
) or mount_point.startswith(nested_mount):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_effective_redirections(
|
def get_effective_redirections(
|
||||||
checkout: EdenCheckout, mount_table: mtab.MountTable
|
checkout: EdenCheckout, mount_table: mtab.MountTable, instance: EdenInstance
|
||||||
) -> Dict[str, Redirection]:
|
) -> Dict[str, Redirection]:
|
||||||
"""Computes the complete set of redirections that are currently in effect.
|
"""Computes the complete set of redirections that are currently in effect.
|
||||||
This is based on the explicitly configured settings but also factors in
|
This is based on the explicitly configured settings but also factors in
|
||||||
@ -502,32 +528,40 @@ def get_effective_redirections(
|
|||||||
"""
|
"""
|
||||||
redirs = {}
|
redirs = {}
|
||||||
checkout_path_bytes = bytes(checkout.path) + b"/"
|
checkout_path_bytes = bytes(checkout.path) + b"/"
|
||||||
|
|
||||||
|
nested_mounts = get_nested_mounts(instance, checkout_path_bytes)
|
||||||
|
|
||||||
for mount_info in mount_table.read():
|
for mount_info in mount_table.read():
|
||||||
mount_point = mount_info.mount_point
|
mount_point = mount_info.mount_point
|
||||||
if mount_point.startswith(checkout_path_bytes):
|
if not mount_point.startswith(checkout_path_bytes) or in_nested_mount(
|
||||||
rel_path = os.fsdecode(mount_point[len(checkout_path_bytes) :])
|
nested_mounts, mount_point
|
||||||
# The is_bind_mount test may appear to be redundant but it is
|
):
|
||||||
# possible for mounts to layer such that we have:
|
continue
|
||||||
#
|
|
||||||
# /my/repo <-- fuse at the top of the vfs
|
rel_path = os.fsdecode(mount_point[len(checkout_path_bytes) :])
|
||||||
# /my/repo/buck-out
|
|
||||||
# /my/repo <-- earlier generation fuse at bottom
|
# The is_bind_mount test may appear to be redundant but it is
|
||||||
#
|
# possible for mounts to layer such that we have:
|
||||||
# The buck-out bind mount in the middle is visible in the
|
#
|
||||||
# mount table but is not visible via the VFS because there
|
# /my/repo <-- fuse at the top of the vfs
|
||||||
# is a different /my/repo mounted over the top.
|
# /my/repo/buck-out
|
||||||
#
|
# /my/repo <-- earlier generation fuse at bottom
|
||||||
# We test whether we can see a mount point at that location
|
#
|
||||||
# before recording it in the effective redirection list so
|
# The buck-out bind mount in the middle is visible in the
|
||||||
# that we don't falsely believe that the bind mount is up.
|
# mount table but is not visible via the VFS because there
|
||||||
if rel_path and is_bind_mount(Path(os.fsdecode(mount_point))):
|
# is a different /my/repo mounted over the top.
|
||||||
redirs[rel_path] = Redirection(
|
#
|
||||||
repo_path=Path(rel_path),
|
# We test whether we can see a mount point at that location
|
||||||
redir_type=RedirectionType.UNKNOWN,
|
# before recording it in the effective redirection list so
|
||||||
target=None,
|
# that we don't falsely believe that the bind mount is up.
|
||||||
source="mount",
|
if rel_path and is_bind_mount(Path(os.fsdecode(mount_point))):
|
||||||
state=RedirectionState.UNKNOWN_MOUNT,
|
redirs[rel_path] = Redirection(
|
||||||
)
|
repo_path=Path(rel_path),
|
||||||
|
redir_type=RedirectionType.UNKNOWN,
|
||||||
|
target=None,
|
||||||
|
source="mount",
|
||||||
|
state=RedirectionState.UNKNOWN_MOUNT,
|
||||||
|
)
|
||||||
|
|
||||||
for rel_path, redir in get_configured_redirections(checkout).items():
|
for rel_path, redir in get_configured_redirections(checkout).items():
|
||||||
is_in_mount_table = rel_path in redirs
|
is_in_mount_table = rel_path in redirs
|
||||||
@ -630,9 +664,9 @@ def is_empty_dir(path: Path) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def prepare_redirection_list(checkout: EdenCheckout) -> str:
|
def prepare_redirection_list(checkout: EdenCheckout, instance: EdenInstance) -> str:
|
||||||
mount_table = mtab.new()
|
mount_table = mtab.new()
|
||||||
redirs = get_effective_redirections(checkout, mount_table)
|
redirs = get_effective_redirections(checkout, mount_table, instance)
|
||||||
return create_redirection_configs(checkout, redirs.values(), False)
|
return create_redirection_configs(checkout, redirs.values(), False)
|
||||||
|
|
||||||
|
|
||||||
@ -671,7 +705,7 @@ class ListCmd(Subcmd):
|
|||||||
instance, checkout, _rel_path = cmd_util.require_checkout(args, args.mount)
|
instance, checkout, _rel_path = cmd_util.require_checkout(args, args.mount)
|
||||||
|
|
||||||
mount_table = mtab.new()
|
mount_table = mtab.new()
|
||||||
redirs = get_effective_redirections(checkout, mount_table)
|
redirs = get_effective_redirections(checkout, mount_table, instance)
|
||||||
print_redirection_configs(checkout, redirs.values(), args.json)
|
print_redirection_configs(checkout, redirs.values(), args.json)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -745,7 +779,7 @@ class UnmountCmd(Subcmd):
|
|||||||
def run(self, args: argparse.Namespace) -> int:
|
def run(self, args: argparse.Namespace) -> int:
|
||||||
instance, checkout, _rel_path = cmd_util.require_checkout(args, args.mount)
|
instance, checkout, _rel_path = cmd_util.require_checkout(args, args.mount)
|
||||||
mount_table = mtab.new()
|
mount_table = mtab.new()
|
||||||
redirs = get_effective_redirections(checkout, mount_table)
|
redirs = get_effective_redirections(checkout, mount_table, instance)
|
||||||
|
|
||||||
for redir in redirs.values():
|
for redir in redirs.values():
|
||||||
redir.remove_existing(checkout)
|
redir.remove_existing(checkout)
|
||||||
@ -753,7 +787,7 @@ class UnmountCmd(Subcmd):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# recompute and display the current state
|
# recompute and display the current state
|
||||||
redirs = get_effective_redirections(checkout, mount_table)
|
redirs = get_effective_redirections(checkout, mount_table, instance)
|
||||||
ok = True
|
ok = True
|
||||||
for redir in redirs.values():
|
for redir in redirs.values():
|
||||||
if redir.state == RedirectionState.MATCHES_CONFIGURATION:
|
if redir.state == RedirectionState.MATCHES_CONFIGURATION:
|
||||||
@ -794,9 +828,9 @@ class FixupCmd(Subcmd):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def run(self, args: argparse.Namespace) -> int:
|
def run(self, args: argparse.Namespace) -> int:
|
||||||
_instance, checkout, _rel_path = cmd_util.require_checkout(args, args.mount)
|
instance, checkout, _rel_path = cmd_util.require_checkout(args, args.mount)
|
||||||
mount_table = mtab.new()
|
mount_table = mtab.new()
|
||||||
redirs = get_effective_redirections(checkout, mount_table)
|
redirs = get_effective_redirections(checkout, mount_table, instance)
|
||||||
for redir in redirs.values():
|
for redir in redirs.values():
|
||||||
if redir.state == RedirectionState.MATCHES_CONFIGURATION and not (
|
if redir.state == RedirectionState.MATCHES_CONFIGURATION and not (
|
||||||
args.force_remount_bind_mounts and redir.type == RedirectionType.BIND
|
args.force_remount_bind_mounts and redir.type == RedirectionType.BIND
|
||||||
@ -813,7 +847,7 @@ class FixupCmd(Subcmd):
|
|||||||
redir.apply(checkout)
|
redir.apply(checkout)
|
||||||
|
|
||||||
# recompute and display the current state
|
# recompute and display the current state
|
||||||
redirs = get_effective_redirections(checkout, mount_table)
|
redirs = get_effective_redirections(checkout, mount_table, instance)
|
||||||
ok = True
|
ok = True
|
||||||
for redir in redirs.values():
|
for redir in redirs.values():
|
||||||
if redir.state != RedirectionState.MATCHES_CONFIGURATION:
|
if redir.state != RedirectionState.MATCHES_CONFIGURATION:
|
||||||
@ -984,7 +1018,7 @@ class AddCmd(Subcmd):
|
|||||||
# bring the redirection back online.
|
# bring the redirection back online.
|
||||||
# However, we keep this separate from the `redirs` list below for
|
# However, we keep this separate from the `redirs` list below for
|
||||||
# the reasons stated in the comment above.
|
# the reasons stated in the comment above.
|
||||||
effective_redirs = get_effective_redirections(checkout, mtab.new())
|
effective_redirs = get_effective_redirections(checkout, mtab.new(), instance)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
args.repo_path = str(
|
args.repo_path = str(
|
||||||
@ -1078,7 +1112,7 @@ class DelCmd(Subcmd):
|
|||||||
checkout.save_config(config)
|
checkout.save_config(config)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
redirs = get_effective_redirections(checkout, mtab.new())
|
redirs = get_effective_redirections(checkout, mtab.new(), instance)
|
||||||
redir = redirs.get(args.repo_path)
|
redir = redirs.get(args.repo_path)
|
||||||
if redir:
|
if redir:
|
||||||
# This path isn't possible to trigger until we add profiles,
|
# This path isn't possible to trigger until we add profiles,
|
||||||
|
Loading…
Reference in New Issue
Block a user