mirror of
https://github.com/facebook/sapling.git
synced 2024-12-29 08:02:24 +03:00
remove the "edenfsctl repository" subcommand
Summary: We no longer use repository configs, so remove the `repository` subcommand that supported adding and listing these configurations. The main information that used to be included in the repository configuration was the bind mount settings. This has since been replaced with the `.eden-redirections` file that is placed directly in each repository. Reviewed By: wez Differential Revision: D20876462 fbshipit-source-id: cc7d8e6f0a6a2e04fbf3159417af41a44908b3a8
This commit is contained in:
parent
4910c924a8
commit
ef8c3435c4
@ -293,12 +293,9 @@ class EdenInstance:
|
||||
"""
|
||||
return version.format_eden_version(self.get_running_version_parts())
|
||||
|
||||
def get_repository_list(
|
||||
self, parser: Union[configutil.EdenConfigParser, "ConfigUpdater", None] = None
|
||||
) -> List[str]:
|
||||
def get_repository_list(self) -> List[str]:
|
||||
result = []
|
||||
if not parser:
|
||||
parser = self._loadConfig()
|
||||
parser = self._loadConfig()
|
||||
for section in parser.sections():
|
||||
header = section.split(" ")
|
||||
if len(header) == 2 and header[0] == "repository":
|
||||
@ -415,21 +412,6 @@ class EdenInstance:
|
||||
]
|
||||
)
|
||||
|
||||
def add_repository(self, name: str, repo_type: str, source: str) -> None:
|
||||
# Check if repository already exists
|
||||
with ConfigUpdater(self._user_config_path) as config:
|
||||
if name in self.get_repository_list(config):
|
||||
raise UsageError(
|
||||
"""\
|
||||
repository %s already exists. You will need to edit the ~/.edenrc config file \
|
||||
by hand to make changes to the repository or remove it."""
|
||||
% name
|
||||
)
|
||||
|
||||
# Add repository to INI file
|
||||
config["repository " + name] = {"type": repo_type, "path": source}
|
||||
config.save()
|
||||
|
||||
def clone(
|
||||
self, checkout_config: CheckoutConfig, path: str, snapshot_id: str
|
||||
) -> None:
|
||||
@ -894,140 +876,6 @@ Do you want to run `eden mount %s` instead?"""
|
||||
return now - since
|
||||
|
||||
|
||||
class ConfigUpdater(object):
|
||||
"""
|
||||
A helper class to safely update an eden config file.
|
||||
|
||||
This acquires a lock on the config file, reads it in, and then provide APIs
|
||||
to save it back. This ensures that another process cannot change the file
|
||||
in between the time that we read it and when we write it back.
|
||||
|
||||
This also saves the file to a temporary name first, then renames it into
|
||||
place, so that the main config file is always in a good state, and never
|
||||
has partially written contents.
|
||||
"""
|
||||
|
||||
def __init__(self, path: Path) -> None:
|
||||
self.path = path
|
||||
self._lock_path = self.path.with_suffix(".lock")
|
||||
self._lock_file: Optional[typing.TextIO] = None
|
||||
self.config = configutil.EdenConfigParser()
|
||||
|
||||
# Acquire a lock.
|
||||
# This makes sure that another process can't modify the config in the
|
||||
# middle of a read-modify-write operation. (We can't stop a user
|
||||
# from manually editing the file while we work, but we can stop
|
||||
# other eden CLI processes.)
|
||||
self._acquire_lock()
|
||||
try:
|
||||
toml_cfg = load_toml_config(self.path)
|
||||
self.config.read_dict(toml_cfg)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
def __enter__(self) -> "ConfigUpdater":
|
||||
return self
|
||||
|
||||
def __exit__(
|
||||
self,
|
||||
exc_type: Optional[Type[BaseException]],
|
||||
exc_value: Optional[BaseException],
|
||||
exc_traceback: Optional[types.TracebackType],
|
||||
) -> bool:
|
||||
self.close()
|
||||
return False
|
||||
|
||||
def __del__(self) -> None:
|
||||
self.close()
|
||||
|
||||
def sections(self) -> List[str]:
|
||||
return self.config.sections()
|
||||
|
||||
def __setitem__(self, key: str, value: Dict[str, Any]) -> None:
|
||||
self.config[key] = value
|
||||
|
||||
def _acquire_lock(self) -> None:
|
||||
# Skipping locks on Windows for two reasons:
|
||||
# First, locking the config file is not a strict requirement even on
|
||||
# POSIX. Plus we don't have a similar flock implementation on Windows.
|
||||
# We could make a locking scheme with LockFileEx(), but it would
|
||||
# have different symentics than flock (For one, we can't unlink a
|
||||
# locked file).
|
||||
if sys.platform == "win32":
|
||||
return
|
||||
while True:
|
||||
self._lock_file = typing.cast(typing.TextIO, open(self._lock_path, "w+"))
|
||||
# pyre-fixme[16]: `Optional` has no attribute `fileno`.
|
||||
fcntl.flock(self._lock_file.fileno(), fcntl.LOCK_EX)
|
||||
# The original creator of the lock file will unlink it when
|
||||
# it is finished. Make sure we grab the lock on the file still on
|
||||
# disk, and not an unlinked file.
|
||||
st1 = os.fstat(self._lock_file.fileno())
|
||||
st2 = os.lstat(self._lock_path)
|
||||
if st1.st_dev == st2.st_dev and st1.st_ino == st2.st_ino:
|
||||
# We got the real lock
|
||||
return
|
||||
|
||||
# We acquired a lock on an old deleted file.
|
||||
# Close it, and try to acquire the current lock file again.
|
||||
# pyre-fixme[16]: `Optional` has no attribute `close`.
|
||||
self._lock_file.close()
|
||||
self._lock_file = None
|
||||
continue
|
||||
|
||||
def _unlock(self) -> None:
|
||||
if sys.platform == "win32":
|
||||
return
|
||||
assert self._lock_file is not None
|
||||
# Remove the file on disk before we unlock it.
|
||||
# This way processes currently waiting in _acquire_lock() that already
|
||||
# opened our lock file will see that it isn't the current file on disk
|
||||
# once they acquire the lock.
|
||||
os.unlink(self._lock_path)
|
||||
# pyre-fixme[16]: `Optional` has no attribute `close`.
|
||||
self._lock_file.close()
|
||||
self._lock_file = None
|
||||
|
||||
def close(self) -> None:
|
||||
if self._lock_file is not None:
|
||||
self._unlock()
|
||||
|
||||
def save(self) -> None:
|
||||
if self._lock_file is None:
|
||||
raise Exception("Cannot save the config without holding the lock")
|
||||
|
||||
try:
|
||||
st = os.stat(self.path)
|
||||
perms = st.st_mode & 0o777
|
||||
except OSError as ex:
|
||||
if ex.errno != errno.ENOENT:
|
||||
raise
|
||||
perms = 0o644
|
||||
|
||||
# Write the contents to a temporary file first, then atomically rename
|
||||
# it to the desired destination. This makes sure the .edenrc file
|
||||
# always has valid contents at all points in time.
|
||||
prefix = USER_CONFIG + ".tmp."
|
||||
dirname = self.path.parent
|
||||
tmpf = tempfile.NamedTemporaryFile(
|
||||
"w", dir=str(dirname), prefix=prefix, delete=False
|
||||
)
|
||||
try:
|
||||
toml_config = self.config.to_raw_dict()
|
||||
toml_data = toml.dumps(typing.cast(Mapping[str, Any], toml_config))
|
||||
tmpf.write(toml_data)
|
||||
tmpf.close()
|
||||
os.chmod(tmpf.name, perms)
|
||||
os.rename(tmpf.name, self.path)
|
||||
except BaseException:
|
||||
# Remove temporary file on error
|
||||
try:
|
||||
os.unlink(tmpf.name)
|
||||
except Exception:
|
||||
pass
|
||||
raise
|
||||
|
||||
|
||||
class EdenCheckout:
|
||||
"""Information about a particular Eden checkout."""
|
||||
|
||||
|
@ -352,40 +352,6 @@ class StatusCmd(Subcmd):
|
||||
return 1
|
||||
|
||||
|
||||
@subcmd("repository", "List all repositories")
|
||||
class RepositoryCmd(Subcmd):
|
||||
def setup_parser(self, parser: argparse.ArgumentParser) -> None:
|
||||
parser.add_argument(
|
||||
"name", nargs="?", default=None, help="Name of the checkout to mount"
|
||||
)
|
||||
parser.add_argument(
|
||||
"path", nargs="?", default=None, help="Path to the repository to import"
|
||||
)
|
||||
|
||||
def run(self, args: argparse.Namespace) -> int:
|
||||
instance = get_eden_instance(args)
|
||||
if args.name and args.path:
|
||||
repo = util.get_repo(args.path)
|
||||
if repo is None:
|
||||
print_stderr("%s does not look like a git or hg repository" % args.path)
|
||||
return 1
|
||||
try:
|
||||
instance.add_repository(
|
||||
args.name, repo_type=repo.type, source=repo.source
|
||||
)
|
||||
except config_mod.UsageError as ex:
|
||||
print_stderr("error: {}", ex)
|
||||
return 1
|
||||
elif args.name or args.path:
|
||||
print_stderr("repository command called with incorrect arguments")
|
||||
return 1
|
||||
else:
|
||||
repo_list = instance.get_repository_list()
|
||||
for repo_name in sorted(repo_list):
|
||||
print(repo_name)
|
||||
return 0
|
||||
|
||||
|
||||
class ListMountInfo(typing.NamedTuple):
|
||||
path: Path
|
||||
data_dir: Path
|
||||
|
@ -213,40 +213,6 @@ class TomlConfigTest(
|
||||
self.assertEqual(cc.scm_type, "hg")
|
||||
self.assertEqual(cc.default_revision, "master")
|
||||
|
||||
def test_add_existing_repo(self) -> None:
|
||||
self.copy_config_files()
|
||||
|
||||
cfg = self.get_config()
|
||||
with self.assertRaisesRegex(
|
||||
config_mod.UsageError,
|
||||
"repository fbsource already exists. You will need to edit "
|
||||
"the ~/.edenrc config file by hand to make changes to the "
|
||||
"repository or remove it.",
|
||||
):
|
||||
cfg.add_repository("fbsource", "hg", f"/data/users/{self._user}/fbsource")
|
||||
|
||||
def test_add_repo(self) -> None:
|
||||
self.copy_config_files()
|
||||
|
||||
cfg = self.get_config()
|
||||
cfg.add_repository("fbandroid", "hg", f"/data/users/{self._user}/fbandroid")
|
||||
|
||||
# Lets reload our config
|
||||
cfg = self.get_config()
|
||||
# Check the various config sections
|
||||
self.assert_core_config(cfg)
|
||||
exp_repos = ["fbandroid", "fbsource", "git"]
|
||||
self.assertEqual(cfg.get_repository_list(), exp_repos)
|
||||
self.assert_fbsource_repo_config(cfg)
|
||||
self.assert_git_repo_config(cfg)
|
||||
|
||||
# Check the newly added repo
|
||||
cc = cfg.find_config_for_alias("fbandroid")
|
||||
assert cc is not None
|
||||
self.assertEqual(cc.backing_repo, Path(f"/data/users/{self._user}/fbandroid"))
|
||||
self.assertEqual(cc.scm_type, "hg")
|
||||
self.assertEqual(cc.default_revision, "master")
|
||||
|
||||
def test_missing_type_option_in_repository_is_an_error(self) -> None:
|
||||
self.write_user_config(
|
||||
"""
|
||||
|
@ -240,7 +240,7 @@ class BasicTest(testcase.EdenRepoTest):
|
||||
self.assertFalse(self.eden.in_proc_mounts(self.mount))
|
||||
self.assertFalse(os.path.exists(self.mount))
|
||||
|
||||
self.eden.clone(self.repo_name, self.mount)
|
||||
self.eden.clone(self.repo.path, self.mount)
|
||||
|
||||
self.assert_checkout_root_entries(self.expected_mount_entries)
|
||||
self.assertTrue(self.eden.in_proc_mounts(self.mount))
|
||||
|
@ -26,10 +26,6 @@ from .lib.service_test_case import (
|
||||
)
|
||||
|
||||
|
||||
# This is the name of the default repository created by EdenRepoTestBase.
|
||||
repo_name = "main"
|
||||
|
||||
|
||||
@testcase.eden_repo_test
|
||||
class CloneTest(testcase.EdenRepoTest):
|
||||
def populate_repo(self) -> None:
|
||||
@ -40,7 +36,7 @@ class CloneTest(testcase.EdenRepoTest):
|
||||
tmp = self.make_temporary_directory()
|
||||
non_existent_dir = os.path.join(tmp, "foo/bar/baz")
|
||||
|
||||
self.eden.run_cmd("clone", repo_name, non_existent_dir)
|
||||
self.eden.run_cmd("clone", self.repo.path, non_existent_dir)
|
||||
self.assertTrue(
|
||||
os.path.isfile(os.path.join(non_existent_dir, "hello")),
|
||||
msg="clone should succeed in non-existent directory",
|
||||
@ -56,7 +52,7 @@ class CloneTest(testcase.EdenRepoTest):
|
||||
|
||||
symlinked_target = os.path.join(symlink_dir, "bar")
|
||||
|
||||
self.eden.run_cmd("clone", repo_name, symlinked_target)
|
||||
self.eden.run_cmd("clone", self.repo.path, symlinked_target)
|
||||
self.assertTrue(
|
||||
os.path.isfile(os.path.join(empty_dir, "hello")),
|
||||
msg="clone should succeed in empty directory",
|
||||
@ -77,7 +73,7 @@ class CloneTest(testcase.EdenRepoTest):
|
||||
empty_dir = os.path.join(tmp, "foo/bar/baz")
|
||||
os.makedirs(empty_dir)
|
||||
|
||||
self.eden.run_cmd("clone", repo_name, empty_dir)
|
||||
self.eden.run_cmd("clone", self.repo.path, empty_dir)
|
||||
self.assertTrue(
|
||||
os.path.isfile(os.path.join(empty_dir, "hello")),
|
||||
msg="clone should succeed in empty directory",
|
||||
@ -137,26 +133,9 @@ class CloneTest(testcase.EdenRepoTest):
|
||||
)
|
||||
|
||||
def test_clone_from_eden_repo(self) -> None:
|
||||
# Add a config alias for a repo with some bind mounts.
|
||||
edenrc = os.path.join(self.home_dir, ".edenrc")
|
||||
with open(edenrc, "w") as f:
|
||||
f.write(
|
||||
dedent(
|
||||
f"""\
|
||||
["repository {repo_name}"]
|
||||
path = "{self.repo.get_canonical_root()}"
|
||||
type = "{self.repo.get_type()}"
|
||||
|
||||
["bindmounts {repo_name}"]
|
||||
bm1 = "tmp/bm1"
|
||||
bm2 = "tmp/bm2"
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
# Create an Eden mount from the config alias.
|
||||
eden_clone1 = self.make_temporary_directory()
|
||||
self.eden.run_cmd("clone", repo_name, eden_clone1)
|
||||
self.eden.run_cmd("clone", self.repo.path, eden_clone1)
|
||||
|
||||
self.assertFalse(
|
||||
os.path.isdir(os.path.join(eden_clone1, "tmp/bm1")),
|
||||
@ -168,16 +147,12 @@ class CloneTest(testcase.EdenRepoTest):
|
||||
self.eden.run_cmd(
|
||||
"clone", "--rev", self.repo.get_head_hash(), eden_clone1, eden_clone2
|
||||
)
|
||||
self.assertFalse(
|
||||
os.path.isdir(os.path.join(eden_clone2, "tmp/bm1")),
|
||||
msg="clone should not mount legacy bind mounts",
|
||||
)
|
||||
|
||||
def test_clone_with_valid_revision_cmd_line_arg_works(self) -> None:
|
||||
tmp = self.make_temporary_directory()
|
||||
target = os.path.join(tmp, "foo/bar/baz")
|
||||
self.eden.run_cmd(
|
||||
"clone", "--rev", self.repo.get_head_hash(), repo_name, target
|
||||
"clone", "--rev", self.repo.get_head_hash(), self.repo.path, target
|
||||
)
|
||||
self.assertTrue(
|
||||
os.path.isfile(os.path.join(target, "hello")),
|
||||
@ -188,7 +163,7 @@ class CloneTest(testcase.EdenRepoTest):
|
||||
tmp = self.make_temporary_directory()
|
||||
target = os.path.join(tmp, "foo/bar/baz")
|
||||
short = self.repo.get_head_hash()[:6]
|
||||
self.eden.run_cmd("clone", "--rev", short, repo_name, target)
|
||||
self.eden.run_cmd("clone", "--rev", short, self.repo.path, target)
|
||||
self.assertTrue(
|
||||
os.path.isfile(os.path.join(target, "hello")),
|
||||
msg="clone should succeed with short --snapshop arg.",
|
||||
@ -202,7 +177,7 @@ class CloneTest(testcase.EdenRepoTest):
|
||||
f.write("I am not empty.\n")
|
||||
|
||||
with self.assertRaises(subprocess.CalledProcessError) as context:
|
||||
self.eden.run_cmd("clone", repo_name, non_empty_dir)
|
||||
self.eden.run_cmd("clone", self.repo.path, non_empty_dir)
|
||||
stderr = context.exception.stderr.decode("utf-8")
|
||||
self.assertRegex(
|
||||
stderr,
|
||||
@ -216,7 +191,7 @@ class CloneTest(testcase.EdenRepoTest):
|
||||
os.makedirs(empty_dir)
|
||||
|
||||
with self.assertRaises(subprocess.CalledProcessError) as context:
|
||||
self.eden.run_cmd("clone", repo_name, empty_dir, "--rev", "X")
|
||||
self.eden.run_cmd("clone", self.repo.path, empty_dir, "--rev", "X")
|
||||
stderr = context.exception.stderr.decode("utf-8")
|
||||
self.assertIn(
|
||||
"unable to find hash for commit 'X': ",
|
||||
@ -233,7 +208,7 @@ class CloneTest(testcase.EdenRepoTest):
|
||||
f.write("I am not empty.\n")
|
||||
|
||||
with self.assertRaises(subprocess.CalledProcessError) as context:
|
||||
self.eden.run_cmd("clone", repo_name, file_in_directory)
|
||||
self.eden.run_cmd("clone", self.repo.path, file_in_directory)
|
||||
stderr = context.exception.stderr.decode("utf-8")
|
||||
self.assertIn(
|
||||
f"error: destination path {file_in_directory} is not a directory\n", stderr
|
||||
@ -246,7 +221,7 @@ class CloneTest(testcase.EdenRepoTest):
|
||||
f.write("I am not empty.\n")
|
||||
|
||||
with self.assertRaises(subprocess.CalledProcessError) as context:
|
||||
self.eden.run_cmd("clone", repo_name, non_existent_dir)
|
||||
self.eden.run_cmd("clone", self.repo.path, non_existent_dir)
|
||||
stderr = context.exception.stderr.decode("utf-8")
|
||||
self.assertIn(
|
||||
f"error: destination path {non_existent_dir} is not a directory\n", stderr
|
||||
|
@ -17,7 +17,7 @@ class EdenClientTest(testcase.EdenRepoTest):
|
||||
|
||||
def test_client_dir_for_mount(self) -> None:
|
||||
clone_path = pathlib.Path(self.tmp_dir, "test_checkout")
|
||||
self.eden.run_cmd("clone", self.repo_name, str(clone_path))
|
||||
self.eden.run_cmd("clone", self.repo.path, str(clone_path))
|
||||
self.assertEqual(
|
||||
self.eden.client_dir_for_mount(clone_path),
|
||||
pathlib.Path(self.eden_dir, "clients", "test_checkout"),
|
||||
|
@ -123,9 +123,9 @@ class FsckTest(testcase.EdenRepoTest):
|
||||
mount3 = Path(self.mounts_dir) / "third_mount"
|
||||
mount4 = Path(self.mounts_dir) / "fourth_mount"
|
||||
|
||||
self.eden.clone(self.repo_name, mount2)
|
||||
self.eden.clone(self.repo_name, mount3)
|
||||
self.eden.clone(self.repo_name, mount4)
|
||||
self.eden.clone(self.repo.path, mount2)
|
||||
self.eden.clone(self.repo.path, mount3)
|
||||
self.eden.clone(self.repo.path, mount4)
|
||||
|
||||
# Unmount all but mount3
|
||||
self.eden.unmount(Path(self.mount))
|
||||
|
@ -77,7 +77,6 @@ class EdenHgTestCase(testcase.EdenTestCase, metaclass=abc.ABCMeta):
|
||||
|
||||
repo: hgrepo.HgRepository
|
||||
backing_repo: hgrepo.HgRepository
|
||||
backing_repo_name: str
|
||||
config_variant_name: str # set by the @hg_test decorator
|
||||
|
||||
def setup_eden_test(self) -> None:
|
||||
@ -86,11 +85,9 @@ class EdenHgTestCase(testcase.EdenTestCase, metaclass=abc.ABCMeta):
|
||||
# Create the backing repository
|
||||
self.backing_repo = self.create_backing_repo()
|
||||
|
||||
self.backing_repo_name = "backing_repo"
|
||||
self.eden.add_repository(self.backing_repo_name, self.backing_repo.path)
|
||||
# Edit the edenrc file to set up post-clone hooks that will correctly
|
||||
# populate the .hg directory inside the eden client.
|
||||
self.eden.clone(self.backing_repo_name, self.mount, allow_empty=True)
|
||||
self.eden.clone(self.backing_repo.path, self.mount, allow_empty=True)
|
||||
|
||||
# Now create the repository object that refers to the eden client
|
||||
self.repo = hgrepo.HgRepository(self.mount, system_hgrc=self.system_hgrc)
|
||||
|
@ -439,19 +439,6 @@ class EdenFS(object):
|
||||
# We expect the new process to fail starting.
|
||||
pass
|
||||
|
||||
def add_repository(self, name: str, repo_path: str) -> None:
|
||||
"""
|
||||
Run "eden repository" to define a repository configuration
|
||||
"""
|
||||
self.run_cmd("repository", name, repo_path)
|
||||
|
||||
def repository_cmd(self) -> str:
|
||||
"""
|
||||
Executes "eden repository" to list the repositories,
|
||||
and returns the output as a string.
|
||||
"""
|
||||
return self.run_cmd("repository")
|
||||
|
||||
def list_cmd(self) -> Dict[str, Dict[str, Any]]:
|
||||
"""
|
||||
Executes "eden list --json" to list the Eden checkouts and returns the result as
|
||||
|
@ -292,8 +292,7 @@ class EdenRepoTest(EdenTestCase):
|
||||
self.populate_repo()
|
||||
self.report_time("repository setup done")
|
||||
|
||||
self.eden.add_repository(self.repo_name, self.repo.path)
|
||||
self.eden.clone(self.repo_name, self.mount)
|
||||
self.eden.clone(self.repo.path, self.mount)
|
||||
self.report_time("eden clone done")
|
||||
|
||||
def populate_repo(self) -> None:
|
||||
|
@ -47,7 +47,7 @@ class MountTest(testcase.EdenRepoTest):
|
||||
def test_remove_unmounted_checkout(self) -> None:
|
||||
# Clone a second checkout mount point
|
||||
mount2 = os.path.join(self.mounts_dir, "mount2")
|
||||
self.eden.clone(self.repo_name, mount2)
|
||||
self.eden.clone(self.repo.path, mount2)
|
||||
self.assertEqual(
|
||||
{self.mount: "RUNNING", mount2: "RUNNING"}, self.eden.list_cmd_simple()
|
||||
)
|
||||
@ -317,9 +317,9 @@ class MountTest(testcase.EdenRepoTest):
|
||||
def test_start_with_mount_failures(self) -> None:
|
||||
# Clone a few other checkouts
|
||||
mount2 = os.path.join(self.mounts_dir, "extra_mount_1")
|
||||
self.eden.clone(self.repo_name, mount2)
|
||||
self.eden.clone(self.repo.path, mount2)
|
||||
mount3 = os.path.join(self.mounts_dir, "extra_mount_2")
|
||||
self.eden.clone(self.repo_name, mount3)
|
||||
self.eden.clone(self.repo.path, mount3)
|
||||
self.assertEqual(
|
||||
{self.mount: "RUNNING", mount2: "RUNNING", mount3: "RUNNING"},
|
||||
self.eden.list_cmd_simple(),
|
||||
|
@ -28,7 +28,7 @@ class RCTest(testcase.EdenRepoTest):
|
||||
mounts = self.eden.run_cmd("list")
|
||||
self.assertEqual("", mounts, msg="There should be 0 mount paths after remove")
|
||||
|
||||
self.eden.clone(self.repo_name, self.mount)
|
||||
self.eden.clone(self.repo.path, self.mount)
|
||||
mounts = self.eden.run_cmd("list")
|
||||
self.assertEqual(f"{self.mount}\n", mounts)
|
||||
|
||||
@ -49,7 +49,7 @@ class RCTest(testcase.EdenRepoTest):
|
||||
mounts = self.eden.list_cmd_simple()
|
||||
self.assertEqual({}, mounts, msg="There should be 0 paths in the directory map")
|
||||
|
||||
self.eden.clone(self.repo_name, self.mount)
|
||||
self.eden.clone(self.repo.path, self.mount)
|
||||
self.assertTrue(
|
||||
os.path.isdir(test_client_dir),
|
||||
msg="Client name should be restored verbatim because \
|
||||
@ -61,71 +61,3 @@ class RCTest(testcase.EdenRepoTest):
|
||||
mounts,
|
||||
msg="The client directory should have been restored",
|
||||
)
|
||||
|
||||
def test_override_system_config(self) -> None:
|
||||
system_repo = self.create_repo("system_repo")
|
||||
|
||||
system_repo.write_file("hello.txt", "hola\n")
|
||||
system_repo.commit("Initial commit.")
|
||||
|
||||
repo_info = util.get_repo(system_repo.path)
|
||||
assert repo_info is not None
|
||||
|
||||
# Create temporary system config
|
||||
system_config_dir = self.eden.etc_eden_dir / "config.d"
|
||||
system_config_dir.mkdir(parents=True, exist_ok=True)
|
||||
f, path = tempfile.mkstemp(dir=str(system_config_dir), suffix=".toml")
|
||||
|
||||
# Add system_repo to system config file
|
||||
config = textwrap.dedent(
|
||||
f"""\
|
||||
["repository {self.repo_name}"]
|
||||
path = "{repo_info.source}"
|
||||
type = "{repo_info.type}"
|
||||
"""
|
||||
)
|
||||
os.write(f, config.encode("utf-8"))
|
||||
os.close(f)
|
||||
|
||||
# Clone repository
|
||||
mount_path = os.path.join(self.mounts_dir, self.repo_name + "-1")
|
||||
self.eden.clone(self.repo_name, mount_path)
|
||||
|
||||
# Verify that clone used repository data from user config
|
||||
readme = os.path.join(mount_path, "hello.txt")
|
||||
self.assertFalse(os.path.exists(readme))
|
||||
|
||||
hello = os.path.join(mount_path, "readme.txt")
|
||||
st = os.lstat(hello)
|
||||
self.assertTrue(stat.S_ISREG(st.st_mode))
|
||||
|
||||
with open(hello, "r") as hello_file:
|
||||
self.assertEqual("test\n", hello_file.read())
|
||||
|
||||
# Add system_repo to system config file with new name
|
||||
repo_name = "repo"
|
||||
f = os.open(path, os.O_WRONLY)
|
||||
config = textwrap.dedent(
|
||||
f"""\
|
||||
["repository {repo_name}"]
|
||||
path = "{repo_info.source}"
|
||||
type = "{repo_info.type}"
|
||||
"""
|
||||
)
|
||||
os.write(f, config.encode("utf-8"))
|
||||
os.close(f)
|
||||
|
||||
# Clone repository
|
||||
mount_path = os.path.join(self.mounts_dir, repo_name + "-1")
|
||||
self.eden.clone(repo_name, mount_path)
|
||||
|
||||
# Verify that clone used repository data from system config
|
||||
readme = os.path.join(mount_path, "readme.txt")
|
||||
self.assertFalse(os.path.exists(readme))
|
||||
|
||||
hello = os.path.join(mount_path, "hello.txt")
|
||||
st = os.lstat(hello)
|
||||
self.assertTrue(stat.S_ISREG(st.st_mode))
|
||||
|
||||
with open(hello, "r") as hello_file:
|
||||
self.assertEqual("hola\n", hello_file.read())
|
||||
|
@ -48,6 +48,7 @@ class RemountTest(testcase.EdenRepoTest):
|
||||
repo_names = {"git": "git_repo", "hg": "hg_repo"}
|
||||
git_repo = self.create_git_repo(repo_names["git"])
|
||||
hg_repo = self.create_hg_repo(repo_names["hg"])
|
||||
repos = {"git_repo": git_repo, "hg_repo": hg_repo}
|
||||
|
||||
git_repo.write_file("hello", "hola\n")
|
||||
git_repo.commit("Initial commit.")
|
||||
@ -55,21 +56,17 @@ class RemountTest(testcase.EdenRepoTest):
|
||||
hg_repo.write_file("hello", "hola\n")
|
||||
hg_repo.commit("Initial commit.")
|
||||
|
||||
self.eden.add_repository(repo_names["git"], git_repo.path)
|
||||
self.eden.add_repository(repo_names["hg"], hg_repo.path)
|
||||
|
||||
# Mount git and hg clients
|
||||
for name in repo_names.values():
|
||||
for name, repo in repos.items():
|
||||
for i in range(3):
|
||||
self.eden.clone(
|
||||
name, os.path.join(self.mounts_dir, name + "-" + str(i))
|
||||
)
|
||||
self.eden.clone(repo.path, os.path.join(self.mounts_dir, f"{name}-{i}"))
|
||||
|
||||
self.eden.shutdown()
|
||||
self.eden.start()
|
||||
|
||||
# Verify that clients are remounted on startup
|
||||
for scm_type, name in repo_names.items():
|
||||
for name, repo in repos.items():
|
||||
scm_type = repo.get_type()
|
||||
for i in range(3):
|
||||
mount_path = os.path.join(self.mounts_dir, f"{name}-{i}")
|
||||
self.assert_checkout_root_entries(
|
||||
@ -130,7 +127,7 @@ class RemountTest(testcase.EdenRepoTest):
|
||||
def test_try_remount_existing_mount(self) -> None:
|
||||
"""Verify trying to mount an existing mount prints a sensible error."""
|
||||
mount_destination = self.mount + "-0"
|
||||
self.eden.clone(self.repo_name, mount_destination)
|
||||
self.eden.clone(self.repo.path, mount_destination)
|
||||
with self.assertRaises(edenclient.EdenCommandError) as context:
|
||||
self.eden.run_cmd("mount", mount_destination)
|
||||
self.assertIn(
|
||||
@ -199,7 +196,7 @@ class RemountTest(testcase.EdenRepoTest):
|
||||
|
||||
def _clone_checkouts(self, num_mounts):
|
||||
for i in range(num_mounts):
|
||||
self.eden.clone(self.repo_name, self.mount + "-" + str(i))
|
||||
self.eden.clone(self.repo.path, self.mount + "-" + str(i))
|
||||
|
||||
def _verify_not_mounted(self, num_mounts, main_mounted=False):
|
||||
# Verify that no clients are remounted. No errors should be thrown here
|
||||
|
@ -1,63 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||
#
|
||||
# This software may be used and distributed according to the terms of the
|
||||
# GNU General Public License version 2.
|
||||
|
||||
import os
|
||||
from typing import List
|
||||
|
||||
from .lib import testcase
|
||||
|
||||
|
||||
class RepoTest(testcase.EdenTestCase):
|
||||
"""
|
||||
Tests for the "eden repository" command.
|
||||
|
||||
Note that these tests do not use @testcase.eden_repo_test, since we don't
|
||||
actually need to run separately with git and mercurial repositories. These
|
||||
tests don't actually mount anything in eden at all.
|
||||
"""
|
||||
|
||||
def test_list_repository(self) -> None:
|
||||
self.assertEqual([], self._list_repos())
|
||||
|
||||
config = """\
|
||||
["repository fbsource"]
|
||||
path = "/data/users/carenthomas/fbsource"
|
||||
type = "git"
|
||||
|
||||
["bindmounts fbsource"]
|
||||
fbcode-buck-out = "fbcode/buck-out"
|
||||
fbandroid-buck-out = "fbandroid/buck-out"
|
||||
fbobjc-buck-out = "fbobjc/buck-out"
|
||||
buck-out = "buck-out"
|
||||
|
||||
["repository git"]
|
||||
path = "/home/carenthomas/src/git"
|
||||
type = "git"
|
||||
|
||||
["repository hg-crew"]
|
||||
url = "/data/users/carenthomas/facebook-hg-rpms/hg-crew"
|
||||
type = "hg"
|
||||
"""
|
||||
home_config_file = os.path.join(self.home_dir, ".edenrc")
|
||||
with open(home_config_file, "w") as f:
|
||||
f.write(config)
|
||||
|
||||
expected = ["fbsource", "git", "hg-crew"]
|
||||
self.assertEqual(expected, self._list_repos())
|
||||
|
||||
def test_add_multiple(self) -> None:
|
||||
hg_repo = self.create_hg_repo("hg_repo")
|
||||
git_repo = self.create_git_repo("git_repo")
|
||||
|
||||
self.eden.add_repository("hg1", hg_repo.path)
|
||||
self.assertEqual(["hg1"], self._list_repos())
|
||||
self.eden.add_repository("hg2", hg_repo.path)
|
||||
self.assertEqual(["hg1", "hg2"], self._list_repos())
|
||||
self.eden.add_repository("git1", git_repo.path)
|
||||
self.assertEqual(["git1", "hg1", "hg2"], self._list_repos())
|
||||
|
||||
def _list_repos(self) -> List[str]:
|
||||
return self.eden.repository_cmd().splitlines()
|
@ -230,7 +230,7 @@ class CountersTest(testcase.EdenRepoTest):
|
||||
self.eden.unmount(self.mount_path)
|
||||
counters = self.get_nonthrift_set(self.get_counters().keys())
|
||||
mount2 = os.path.join(self.mounts_dir, "mount2")
|
||||
self.eden.clone(self.repo_name, mount2)
|
||||
self.eden.clone(self.repo.path, mount2)
|
||||
self.eden.unmount(Path(mount2))
|
||||
counters2 = self.get_nonthrift_set(self.get_counters().keys())
|
||||
self.assertEqual(counters, counters2)
|
||||
|
Loading…
Reference in New Issue
Block a user