Milestones 4 and 5: project layer, review gate and serial merge, all measured
This commit is contained in:
111
bin/office
Executable file
111
bin/office
Executable file
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Open a folder as a project: adopt it, remember it, build its pages.
|
||||
|
||||
bin/office <folder> [--project <id|urlKey|name>] [--session NAME] [--dry]
|
||||
bin/office . # the folder you are in
|
||||
|
||||
Adopting writes one file, <folder>/.harness/harness.toml, and nothing else. An
|
||||
existing folder is never overwritten: what is already there stays, and only the
|
||||
missing file is written. Paperclip's project record is read, never created —
|
||||
bin/office adopts a project that exists, it does not invent one.
|
||||
|
||||
The machine is remembered, so the flag is stated once. Running the same command
|
||||
on a machine that is not the recorded one is refused rather than silently
|
||||
producing a second copy of the same project.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.insert(0, os.path.join(HERE, "lib"))
|
||||
import harness as h # noqa: E402
|
||||
import project as pj # noqa: E402
|
||||
import tuios # noqa: E402
|
||||
|
||||
|
||||
def parse(argv):
|
||||
opts = {"folder": ".", "project": "", "session": "", "dry": "--dry" in argv, "host": ""}
|
||||
args = [a for a in argv if not a.startswith("--")]
|
||||
if args:
|
||||
opts["folder"] = args[0]
|
||||
for i, a in enumerate(argv):
|
||||
if a == "--project" and i + 1 < len(argv):
|
||||
opts["project"] = argv[i + 1]
|
||||
if a == "--session" and i + 1 < len(argv):
|
||||
opts["session"] = argv[i + 1]
|
||||
if a == "--host" and i + 1 < len(argv):
|
||||
opts["host"] = argv[i + 1]
|
||||
return opts
|
||||
|
||||
|
||||
def main():
|
||||
opts = parse(sys.argv[1:])
|
||||
folder = os.path.abspath(os.path.expanduser(opts["folder"]))
|
||||
if not os.path.isdir(folder):
|
||||
raise h.Refused(2, "no folder at %s" % folder)
|
||||
|
||||
host = opts["host"] or pj.this_machine()
|
||||
|
||||
# An adopted project already knows its session. Only a new one needs a
|
||||
# default, and a default that names a session nobody made is worse than an
|
||||
# error, so the session is checked before anything is written.
|
||||
existing = {}
|
||||
if pj.exists(folder):
|
||||
existing = pj.load(folder)
|
||||
session = (
|
||||
opts["session"]
|
||||
or existing.get("session")
|
||||
or os.path.basename(folder)
|
||||
)
|
||||
tuios.require_session(session)
|
||||
|
||||
if opts["host"] and opts["host"] not in (pj.this_machine(), pj.this_machine().split(".")[0]):
|
||||
# Only a note, because the panes are built by the machine that owns them.
|
||||
h.say("host: %s (build the pages there)" % host)
|
||||
|
||||
ref = opts["project"]
|
||||
if not ref and pj.exists(folder):
|
||||
ref = pj.load(folder)["paperclip"]["project"]
|
||||
if not ref:
|
||||
raise h.Refused(
|
||||
2,
|
||||
"which Paperclip project is %s? pass --project <id|urlKey|name>" % folder,
|
||||
)
|
||||
|
||||
proj = pj.resolve_project(ref)
|
||||
h.say("project: %s (%s)" % (proj["name"], proj["id"]))
|
||||
h.say("folder: %s" % folder)
|
||||
h.say("session: %s" % session)
|
||||
h.say("machine: %s" % host)
|
||||
|
||||
tasks = pj.active_tasks(proj["id"])
|
||||
watching = next((t["identifier"] for t in tasks if t["status"] not in ("done", "cancelled")),
|
||||
tasks[0]["identifier"] if tasks else "")
|
||||
|
||||
cfg = {
|
||||
"session": session,
|
||||
"paperclip": {"company": h.COMPANY, "project": proj["id"]},
|
||||
"machine": {"host": host, "folder": folder},
|
||||
"watching": watching,
|
||||
}
|
||||
|
||||
if opts["dry"]:
|
||||
h.say("would write %s" % pj.path(folder))
|
||||
h.say("would build pages: shell, tree, reply, log, new")
|
||||
return 0
|
||||
|
||||
pj.save(folder, cfg)
|
||||
h.say("wrote %s" % pj.path(folder))
|
||||
|
||||
# The pages are built by this machine, from this folder, in this session.
|
||||
code = os.spawnv(
|
||||
os.P_WAIT,
|
||||
sys.executable,
|
||||
[sys.executable, os.path.join(HERE, "board"), "--folder", folder],
|
||||
)
|
||||
return code
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
h.main_guard(main)
|
||||
Reference in New Issue
Block a user