54 lines
2.3 KiB
Python
54 lines
2.3 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""Plan all captured spaces newest first, offline; private output, no import."""
|
||
|
|
|
||
|
|
import argparse
|
||
|
|
import hashlib
|
||
|
|
import json
|
||
|
|
import os
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
||
|
|
|
||
|
|
from coulomb_social.apps.spaces.bubble_transfer import transfer_plan # noqa: E402
|
||
|
|
|
||
|
|
|
||
|
|
def main():
|
||
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
||
|
|
parser.add_argument("capture", type=Path, help="Private spaces.json/articles.json directory")
|
||
|
|
parser.add_argument("--output", type=Path, required=True, help="New private JSON file")
|
||
|
|
parser.add_argument("--inventory-spaces", type=Path,
|
||
|
|
help="Retained spaces.json; keep absent spaces queued as not refreshed")
|
||
|
|
args = parser.parse_args()
|
||
|
|
try:
|
||
|
|
sources = {name: (args.capture / (name + ".json")).read_bytes()
|
||
|
|
for name in ("spaces", "articles")}
|
||
|
|
inventory = None
|
||
|
|
if args.inventory_spaces:
|
||
|
|
sources["retained_spaces"] = args.inventory_spaces.read_bytes()
|
||
|
|
inventory = json.loads(sources["retained_spaces"])
|
||
|
|
plan = transfer_plan(json.loads(sources["spaces"]), json.loads(sources["articles"]),
|
||
|
|
inventory_spaces=inventory)
|
||
|
|
plan["source_sha256"] = {name: hashlib.sha256(data).hexdigest()
|
||
|
|
for name, data in sources.items()}
|
||
|
|
# Never print private IDs, names, notes or source errors to the terminal.
|
||
|
|
fd = os.open(args.output, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
|
||
|
|
with os.fdopen(fd, "w") as stream:
|
||
|
|
json.dump(plan, stream, indent=2)
|
||
|
|
stream.write("\n")
|
||
|
|
print(json.dumps({
|
||
|
|
"spaces": len(plan["spaces"]),
|
||
|
|
"captured_graph_complete": sum(s["captured_graph_complete"] for s in plan["spaces"]),
|
||
|
|
"unassigned_articles": len(plan["unassigned_article_ids"]),
|
||
|
|
"inventory_only_spaces": len(plan["inventory_only_space_ids"]),
|
||
|
|
"live_source_completeness_verified": False, "production_imported": False,
|
||
|
|
}))
|
||
|
|
except (ValueError, OSError, TypeError):
|
||
|
|
print("Transfer plan refused; inspect the private capture/output locally", file=sys.stderr)
|
||
|
|
return 1
|
||
|
|
return 0
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
raise SystemExit(main())
|