예제 #1
0
    def clone(
        self, checkout_config: CheckoutConfig, path: str, snapshot_id: str
    ) -> None:
        if path in self._get_directory_map():
            raise Exception(
                """\
mount path %s is already configured (see `eden list`). \
Do you want to run `eden mount %s` instead?"""
                % (path, path)
            )

        # Create the mount point directory
        self._create_mount_point_dir(path)

        # Create client directory
        clients_dir = self._get_clients_dir()
        clients_dir.mkdir(parents=True, exist_ok=True)
        client_dir = self._create_client_dir_for_path(clients_dir, path)

        # Store snapshot ID
        checkout = EdenCheckout(self, Path(path), Path(client_dir))
        if snapshot_id:
            checkout.save_snapshot(snapshot_id)
        else:
            raise Exception("snapshot id not provided")

        checkout.save_config(checkout_config)

        # Prepare to mount
        mount_info = eden_ttypes.MountArgument(
            mountPoint=os.fsencode(path),
            edenClientPath=os.fsencode(client_dir),
            readOnly=False,
        )
        with self.get_thrift_client_legacy() as client:
            client.mount(mount_info)

        self._post_clone_checkout_setup(checkout, snapshot_id)

        # Add mapping of mount path to client directory in config.json
        self._add_path_to_directory_map(Path(path), os.path.basename(client_dir))
예제 #2
0
파일: config.py 프로젝트: leszfb/eden
    def mount(self, path: Union[Path, str], read_only: bool) -> int:
        # Load the config info for this client, to make sure we
        # know about the client.
        path = Path(path).resolve(strict=False)
        client_dir = self._get_client_dir_for_mount_point(path)
        checkout = EdenCheckout(self, path, client_dir)

        # Call checkout.get_config() for the side-effect of it raising an
        # Exception if the config is in an invalid state.
        checkout.get_config()

        # Make sure the mount path exists
        path.mkdir(parents=True, exist_ok=True)

        # Check if it is already mounted.
        try:
            root = path / ".eden" / "root"
            target = readlink_retry_estale(root)
            if Path(target) == path:
                print_stderr(
                    f"ERROR: Mount point in use! {path} is already mounted by Eden."
                )
                return 1
            else:
                # If we are here, MOUNT/.eden/root is a symlink, but it does not
                # point to MOUNT. This suggests `path` is a subdirectory of an
                # existing mount, though we should never reach this point
                # because _get_client_dir_for_mount_point() above should have
                # already thrown an exception. We return non-zero here just in
                # case.
                print_stderr(
                    f"ERROR: Mount point in use! "
                    f"{path} is already mounted by Eden as part of {root}.")
                return 1
        except OSError as ex:
            # - ENOENT is expected if the mount is not mounted.
            # - We'll get ENOTCONN if the directory was not properly unmounted from a
            #   previous EdenFS instance.  Remounting over this directory is okay (even
            #   though ideally we would unmount the old stale mount point to clean it
            #   up).
            # - EINVAL can happen if .eden/root isn't a symlink.  This isn't expected
            #   in most circumstances, but it does mean that the directory isn't
            #   currently an EdenFS checkout.
            err = ex.errno
            if err not in (errno.ENOENT, errno.ENOTCONN, errno.EINVAL):
                raise

        # Ask eden to mount the path
        mount_info = eden_ttypes.MountArgument(
            mountPoint=bytes(path),
            edenClientPath=bytes(client_dir),
            readOnly=read_only)

        try:
            with self.get_thrift_client_legacy() as client:
                client.mount(mount_info)
        except eden_ttypes.EdenError as ex:
            if "already mounted" in str(ex):
                print_stderr(
                    f"ERROR: Mount point in use! {path} is already mounted by Eden."
                )
                return 1

        return 0