Files
exo/scripts/hashdir.py
Gelu Vrabie 345fafd80d Forwarder versioning
Co-authored-by: Gelu Vrabie <gelu@exolabs.net>
2025-08-18 15:08:50 +01:00

81 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import hashlib
import os
import sys
EXCLUDE_DIRS = {".git", "build", "vendor", ".idea", ".vscode", "__pycache__"}
def norm_rel(path: str, base: str) -> str:
"""Forwarder-rootrelative path with '/' separators."""
abs_path = os.path.abspath(path)
abs_base = os.path.abspath(base)
rel = os.path.relpath(abs_path, abs_base)
return rel.replace(os.sep, "/")
def collect_files(arg_path: str) -> tuple[str, list[str]]:
# Resolve forwarder_root and src_root from the provided path
p = os.path.abspath(arg_path)
if not os.path.isdir(p):
sys.stderr.write(f"error: path must be a directory: {arg_path}\n")
sys.exit(2)
if os.path.basename(p) == "src":
forwarder_root = os.path.dirname(p)
src_root = p
else:
forwarder_root = p
src_root = os.path.join(forwarder_root, "src")
files = []
# 1) Include .go files under src, excluding *_test.go
if os.path.isdir(src_root):
for root, dirs, filenames in os.walk(src_root):
# prune excluded dirs
dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS]
for name in filenames:
# strict .go, exclude *_test.go
if not name.lower().endswith(".go"):
continue
if name.lower().endswith("_test.go"):
continue
files.append(os.path.join(root, name))
# 2) Add go.mod, go.sum, main.go from the forwarder root
for name in ("go.mod", "go.sum", "main.go"):
pth = os.path.join(forwarder_root, name)
if os.path.isfile(pth):
# defensive: exclude *_test.go at root too
if name.lower().endswith("_test.go"):
continue
files.append(pth)
# Deduplicate and sort deterministically by forwarder-rootrelative path
files: list[str] = sorted(set(files), key=lambda f: norm_rel(f, forwarder_root))
return forwarder_root, files
def hash_files(forwarder_root: str, files: list[str]) -> str:
h = hashlib.sha256()
for fp in files:
rel = norm_rel(fp, forwarder_root)
h.update(b"F\x00")
h.update(rel.encode("utf-8"))
h.update(b"\x00")
with open(fp, "rb") as f:
for chunk in iter(lambda: f.read(256 * 1024), b""):
h.update(chunk)
h.update(b"\n")
return h.hexdigest()
def main():
if len(sys.argv) > 1:
arg = sys.argv[1]
else:
arg = os.path.join("networking", "forwarder", "src")
forwarder_root, files = collect_files(arg)
digest = hash_files(forwarder_root, files)
# print without trailing newline (easier to capture in shell)
sys.stdout.write(digest)
if __name__ == "__main__":
main()