protonfs.localscan module

Walks the local filesystem to produce the “local” side of a three-way diff.

scan() rglobs a repo (or subpath), skipping ignored files and the .protonfs control directory, hashing each remaining file into a ScanEntry. Its output feeds classify() as the local argument.

Added in version 1.0.0.

class protonfs.localscan.ScanEntry(rel_path, size, mtime, sha256, sha1, is_lfs_pointer=False)[source]

Bases: object

One file’s state as observed by a local filesystem scan.

Variables:
  • rel_path – Repo-relative path.

  • size – File size in bytes, from stat().

  • mtime – Modification time (seconds since epoch), from stat().

  • sha256 – protonfs’s own content checksum.

  • sha1 – Matches proton’s plaintext claimedDigests.sha1, for comparison against a RemoteEntry without needing a second hash pass.

  • is_lfs_pointer – True if this is an un-smudged git-LFS pointer stub rather than real content (#32); classify() short-circuits on this flag.

is_lfs_pointer: bool = False
mtime: float
rel_path: str
sha1: str
sha256: str
size: int
protonfs.localscan.hash_file(path)[source]

Compute the sha256 hex digest of path’s contents.

Parameters:

path (Path) – File to hash.

Return type:

str

Returns:

Hex-encoded sha256 digest.

Note

Reads in 1 MiB chunks to bound memory use on large files. When both sha256 and sha1 are needed (as in scan()), prefer hash_file_digests(), which computes both in a single read pass.

protonfs.localscan.hash_file_digests(path)[source]

Return (sha256, sha1) for path, computed in a single pass over the file so a scan pays one read, not two, for the two digests it needs.

Return type:

tuple[str, str]

protonfs.localscan.scan(root, subpath, ignore, index, low_io=False, reporter=None, hash_cache=None)[source]

Walk root / subpath and build a ScanEntry for every synced file.

Parameters:
  • root (Path) – Repo root.

  • subpath (Path) – Subdirectory to scan, relative to root (Path(".") for the whole repo).

  • ignore (IgnoreMatcher) – Matcher used to exclude files (see IgnoreMatcher).

  • index (IndexStore) – The repo’s IndexStore, consulted for cached hashes when low_io is set.

  • low_io (bool) – If True, reuse a file’s previously indexed sha256/sha1 instead of rehashing it, whenever the index has an entry with matching size and mtime. Trades a small risk of missing a same-size/same-mtime content change for avoiding a full read of every file on each scan.

  • reporter – optional Reporter; when given, per-file hashing progress is narrated so a long scan (the pre-upload hash of a large tree, which is otherwise silent for minutes) shows movement at -v.

Return type:

dict[str, ScanEntry]

Returns:

Dict of ScanEntry keyed by repo-relative path. The .protonfs control directory and any path matched by ignore are excluded.

See also

classify(), which consumes this as its local arg.

Changed in version 1.5.2: subpath may now name a single file, not just a directory or .; a file subpath scans exactly that file. A nonexistent subpath still returns {}.

Parameters:

hash_cache – optional HashCache; when set and low_io is on, a file whose (size, mtime) matches a cached hash is not re-hashed even if it is not in the index (so a re-run/resumed scan skips work the index-based reuse misses). Freshly-computed hashes are written back to the cache (regardless of low_io) and the cache is persisted periodically + at the end.

Changed in version 1.8.0: Added the optional reporter for per-file hashing progress, and the optional hash_cache for persistent, index-independent hash reuse.