예제 #1
0
def check_loaded_content(
    tracker: ProblemTracker,
    instance: EdenInstance,
    checkout: EdenCheckout,
    query_prjfs_file: Callable[[Path], PRJ_FILE_STATE],
) -> None:
    with instance.get_thrift_client_legacy() as client:
        loaded = client.debugInodeStatus(
            bytes(checkout.path),
            b"",
            flags=DIS_REQUIRE_LOADED,
            sync=SyncBehavior(),
        )

        errors = []
        for loaded_dir in loaded:
            path = Path(os.fsdecode(loaded_dir.path))

            for dirent in loaded_dir.entries:
                if not stat.S_ISREG(dirent.mode) or dirent.materialized:
                    continue

                dirent_path = path / Path(os.fsdecode(dirent.name))
                filestate = query_prjfs_file(checkout.path / dirent_path)
                if (filestate & PRJ_FILE_STATE.HydratedPlaceholder !=
                        PRJ_FILE_STATE.HydratedPlaceholder):
                    # We should only compute the sha1 of files that have been read.
                    continue

                def compute_file_sha1(file: Path) -> bytes:
                    hasher = hashlib.sha1()
                    with open(checkout.path / dirent_path, "rb") as f:
                        while True:
                            buf = f.read(1024 * 1024)
                            if buf == b"":
                                break
                            hasher.update(buf)
                    return hasher.digest()

                sha1 = client.getSHA1(bytes(checkout.path),
                                      [bytes(dirent_path)],
                                      sync=SyncBehavior())[0].get_sha1()
                on_disk_sha1 = compute_file_sha1(checkout.path / dirent_path)
                if sha1 != on_disk_sha1:
                    errors += [(dirent_path, sha1, on_disk_sha1)]

        if errors != []:
            tracker.add_problem(LoadedFileHasDifferentContentOnDisk(errors))
예제 #2
0
파일: mount_test.py 프로젝트: simpkins/eden
    def _assert_thrift_calls_fail_during_mount_init(
            self, client: EdenClient) -> None:
        error_regex = "mount point .* is still initializing"
        mount_path = Path(self.mount)
        null_commit = b"\00" * 20

        with self.assertRaisesRegex(EdenError, error_regex) as ctx:
            client.getFileInformation(mountPoint=bytes(mount_path),
                                      paths=[b""],
                                      sync=SyncBehavior())
        self.assertEqual(EdenErrorType.POSIX_ERROR, ctx.exception.errorType)

        with self.assertRaisesRegex(EdenError, error_regex) as ctx:
            client.getScmStatus(mountPoint=bytes(mount_path),
                                listIgnored=False,
                                commit=null_commit)
        self.assertEqual(EdenErrorType.POSIX_ERROR, ctx.exception.errorType)

        parents = WorkingDirectoryParents(parent1=null_commit)
        params = ResetParentCommitsParams()
        with self.assertRaisesRegex(EdenError, error_regex) as ctx:
            client.resetParentCommits(mountPoint=bytes(mount_path),
                                      parents=parents,
                                      params=params)
        self.assertEqual(EdenErrorType.POSIX_ERROR, ctx.exception.errorType)
예제 #3
0
 def test_get_sha1_throws_for_non_existent_file(self) -> None:
     with self.get_thrift_client_legacy() as client:
         results = client.getSHA1(self.mount_path_bytes,
                                  [b"i_do_not_exist"],
                                  sync=SyncBehavior())
     self.assertEqual(1, len(results))
     self.assert_sha1_error(results[0],
                            "i_do_not_exist: No such file or directory")
예제 #4
0
 def test_get_sha1_throws_for_symlink(self) -> None:
     """Fails because caller should resolve the symlink themselves."""
     with self.get_thrift_client_legacy() as client:
         results = client.getSHA1(self.mount_path_bytes, [b"slink"],
                                  sync=SyncBehavior())
     self.assertEqual(1, len(results))
     self.assert_sha1_error(results[0],
                            "slink: file is a symlink: Invalid argument")
예제 #5
0
 def test_get_sha1_throws_for_path_with_dot_components(self) -> None:
     with self.get_thrift_client_legacy() as client:
         results = client.getSHA1(self.mount_path_bytes, [b"./hello"],
                                  sync=SyncBehavior())
     self.assertEqual(1, len(results))
     self.assert_sha1_error(
         results[0],
         re.compile(
             r".*PathComponentValidationError.*: PathComponent must not be \."
         ),
     )
예제 #6
0
 def get_loaded_inodes_count(self, path: str) -> int:
     with self.get_thrift_client_legacy() as client:
         result = client.debugInodeStatus(self.mount_path_bytes,
                                          os.fsencode(path),
                                          flags=0,
                                          sync=SyncBehavior())
     inode_count = 0
     for item in result:
         assert item.entries is not None
         for inode in item.entries:
             if inode.loaded:
                 inode_count += 1
     return inode_count
예제 #7
0
def check_materialized_are_accessible(
    tracker: ProblemTracker,
    instance: EdenInstance,
    checkout: EdenCheckout,
) -> None:
    mismatched_mode = []
    inaccessible_inodes = []

    with instance.get_thrift_client_legacy() as client:
        materialized = client.debugInodeStatus(
            bytes(checkout.path),
            b"",
            flags=DIS_REQUIRE_MATERIALIZED,
            sync=SyncBehavior(),
        )

    for materialized_dir in materialized:
        path = Path(os.fsdecode(materialized_dir.path))
        try:
            st = os.lstat(checkout.path / path)
        except OSError:
            inaccessible_inodes += [path]
            continue

        if not stat.S_ISDIR(st.st_mode):
            mismatched_mode += [(path, stat.S_IFDIR, st.st_mode)]

        for dirent in materialized_dir.entries:
            if dirent.materialized:
                dirent_path = path / Path(os.fsdecode(dirent.name))
                try:
                    dirent_stat = os.lstat(checkout.path / dirent_path)
                except OSError:
                    inaccessible_inodes += [dirent_path]
                    continue

                # TODO(xavierd): Symlinks are for now recognized as files.
                dirent_mode = (stat.S_IFREG if stat.S_ISLNK(
                    dirent_stat.st_mode) else stat.S_IFMT(dirent_stat.st_mode))
                if dirent_mode != stat.S_IFMT(dirent.mode):
                    mismatched_mode += [(dirent_path, dirent_stat.st_mode,
                                         dirent.mode)]

    if inaccessible_inodes != []:
        tracker.add_problem(
            MaterializedInodesAreInaccessible(inaccessible_inodes))

    if mismatched_mode != []:
        tracker.add_problem(
            MaterializedInodesHaveDifferentModeOnDisk(mismatched_mode))
예제 #8
0
 def get_paths_for_inodes(self, path: str = "") -> Iterable[str]:
     """path: relative path to a directory under the mount."""
     with self.create_thrift_client() as client:
         debug_info = client.debugInodeStatus(
             os.fsencode(self._mount_point),
             os.fsencode(path),
             flags=0,
             sync=SyncBehavior(),
         )
     for tree_inode_debug_info in debug_info:
         parent_dir = tree_inode_debug_info.path.decode("utf-8")
         for entry in tree_inode_debug_info.entries:
             if entry.loaded:
                 yield f'{parent_dir}/{entry.name.decode("utf-8")}'
예제 #9
0
    def test_get_sha1(self) -> None:
        expected_sha1_for_hello = hashlib.sha1(b"hola\n").digest()
        result_for_hello = SHA1Result(expected_sha1_for_hello)

        expected_sha1_for_adir_file = hashlib.sha1(b"foo!\n").digest()
        result_for_adir_file = SHA1Result(expected_sha1_for_adir_file)

        with self.get_thrift_client_legacy() as client:
            self.assertEqual(
                [result_for_hello, result_for_adir_file],
                client.getSHA1(
                    self.mount_path_bytes,
                    [b"hello", b"adir/file"],
                    sync=SyncBehavior(),
                ),
            )
예제 #10
0
    def get_inode_count(self, path: str = "") -> int:
        """path: relative path to a directory under the mount.

        Use '' for the root. Note that this will include the inode count for
        the root .hg and .eden entries.
        """
        with self.create_thrift_client() as client:
            debug_info = client.debugInodeStatus(
                os.fsencode(self._mount_point),
                os.fsencode(path),
                flags=0,
                sync=SyncBehavior(),
            )
        count = 0
        for tree_inode_debug_info in debug_info:
            count += sum(1 for entry in tree_inode_debug_info.entries if entry.loaded)
        return count
예제 #11
0
    def xtest_debug_blob_prints_binary_data(self) -> None:
        with self.eden.get_thrift_client_legacy() as client:
            debugInfo = client.debugInodeStatus(os.fsencode(self.mount),
                                                b".",
                                                flags=0,
                                                sync=SyncBehavior())

        [root] = [entry for entry in debugInfo if entry.path == b""]
        self.assertEqual(1, root.inodeNumber)

        [file] = [entry for entry in root.entries if entry.name == b"binary"]
        self.assertEqual(False, file.materialized)
        blob_id = binascii.hexlify(file.hash).decode()
        print(blob_id)

        output = self.eden.run_cmd("debug",
                                   "blob",
                                   ".",
                                   blob_id,
                                   cwd=self.mount)
        self.assertEqual(b"\xff\xfe\xfd\xfc", output)
예제 #12
0
 def test_get_sha1_throws_for_directory(self) -> None:
     with self.get_thrift_client_legacy() as client:
         results = client.getSHA1(self.mount_path_bytes, [b"adir"],
                                  sync=SyncBehavior(60))
     self.assertEqual(1, len(results))
     self.assert_sha1_error(results[0], "adir: Is a directory")
예제 #13
0
 def test_get_sha1_throws_for_empty_string(self) -> None:
     with self.get_thrift_client_legacy() as client:
         results = client.getSHA1(self.mount_path_bytes, [b""],
                                  sync=SyncBehavior())
     self.assertEqual(1, len(results))
     self.assert_sha1_error(results[0], "path cannot be the empty string")