dak.generate_md5sums

Generate a md5sums index of an archive tree

Walk an archive tree, print a md5sum(1)-compatible index of all regular files to stdout, and keep a cache keyed on path, mtime and size to avoid re-hashing unchanged files.

All paths are handled as bytes: the index must list filenames exactly as they appear on disk.

Functions

generate(root, old_cache, out, cache_out[, ...])

write a md5sums index of all regular files below root to out

hash_file(path)

load_cache(cache_file)

read the cache from cache_file; a missing file is an empty cache

main([argv])

read_cache(fh)

parse cache records as written by generate

run(root, cache_file, out[, exclude])

generate the index for root, updating cache_file atomically

usage()

walk_tree(root)

yield (path relative to root, lstat result) for all regular files

Classes

CacheEntry(mtime_ns, size, md5)

class dak.generate_md5sums.CacheEntry(mtime_ns: int, size: int, md5: bytes)[source]
md5: bytes
mtime_ns: int
size: int
dak.generate_md5sums.generate(root: bytes, old_cache: Cache, out: BinaryIO, cache_out: BinaryIO, exclude: Collection[bytes] = frozenset({})) tuple[int, int][source]

write a md5sums index of all regular files below root to out

Files whose relative path is listed in exclude are skipped. MD5 sums are taken from old_cache for files whose mtime and size are unchanged and computed otherwise; the new cache is written to cache_out. Returns the number of files (hashed, reused).

dak.generate_md5sums.hash_file(path: bytes) bytes[source]
dak.generate_md5sums.load_cache(cache_file: bytes) Cache[source]

read the cache from cache_file; a missing file is an empty cache

dak.generate_md5sums.main(argv: list[str] | None = None) None[source]
dak.generate_md5sums.read_cache(fh: BinaryIO) Cache[source]

parse cache records as written by generate

Returns a mapping of path to CacheEntry. Unparsable lines are ignored: the cache is only an optimization, and dropping a record just means the file gets hashed again.

dak.generate_md5sums.run(root: bytes, cache_file: bytes, out: BinaryIO, exclude: Collection[bytes] = frozenset({})) None[source]

generate the index for root, updating cache_file atomically

dak.generate_md5sums.usage() None[source]
dak.generate_md5sums.walk_tree(root: bytes) Iterator[tuple[bytes, stat_result]][source]

yield (path relative to root, lstat result) for all regular files

Directory entries are visited in sorted order. Symbolic links are neither followed nor listed; other non-regular files are skipped.