コード例 #1
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))
コード例 #2
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))