office: open a lazygit session on the machine that owns the folder, and stop overwriting a working wrapper
This commit is contained in:
71
bin/office
71
bin/office
@@ -47,14 +47,16 @@ def parse(argv):
|
||||
opts = {"folder": ".", "folder_given": False, "project": "", "session": "",
|
||||
"dry": False, "host": "", "no_switch": False, "new": "", "remote": "",
|
||||
"git_init": "--git-init" in argv, "anywhere": "--anywhere" in argv,
|
||||
"commit_all": "--commit-all" in argv, "git_init_commits": False}
|
||||
"commit_all": "--commit-all" in argv, "git_init_commits": False,
|
||||
"client_host": ""}
|
||||
positional = []
|
||||
i = 0
|
||||
while i < len(argv):
|
||||
a = argv[i]
|
||||
if a in ("--project", "--session", "--host", "--new", "--remote"):
|
||||
if a in ("--project", "--session", "--host", "--new", "--remote", "--client-host"):
|
||||
if i + 1 < len(argv):
|
||||
opts[a[2:]] = argv[i + 1]
|
||||
# Keys are Python names, so a flag with a hyphen becomes an underscore.
|
||||
opts[a[2:].replace("-", "_")] = argv[i + 1]
|
||||
i += 2
|
||||
continue
|
||||
i += 1
|
||||
@@ -146,6 +148,45 @@ def ensure_session(session, folder):
|
||||
h.say("session: %s (created; switch to it with TUIOS's session switcher)" % session)
|
||||
|
||||
|
||||
def open_git_session(folder, session, opts):
|
||||
"""A session with lazygit already open in the folder, on the machine that has it.
|
||||
|
||||
The commit has to happen where the files are, and that machine is often not
|
||||
the one being typed at. A session on that machine is how the person gets
|
||||
there from TUIOS, which is the whole point of this program: one attach, no
|
||||
ssh, no cd.
|
||||
"""
|
||||
helper = session + "-git"
|
||||
created = ensure_session_quiet(helper, folder)
|
||||
# The pane a tool needs a PATH of its own: a pane started this way does not
|
||||
# inherit an interactive shell's.
|
||||
prelude = ('export PATH="$HOME/.local/bin:$HOME/.nix-profile/bin:'
|
||||
'/run/current-system/sw/bin:/etc/profiles/per-user/$USER/bin:$PATH"; ')
|
||||
tuios.open_pane("git", "Git", folder, prelude + "exec lazygit", helper)
|
||||
h.say("")
|
||||
h.say(" A session called %r now holds lazygit in that folder%s." % (helper, "" if created else " (it was already there)"))
|
||||
h.say(" Attach to it, stage and commit, then come back and repeat the command:")
|
||||
h.say("")
|
||||
client = opts.get("client_host") or ""
|
||||
h.say(" tuios attach%s %s" % (" --host " + client if client else "", helper))
|
||||
h.say("")
|
||||
h.say(" When you are done with it: tuios kill-session %s" % helper)
|
||||
return helper
|
||||
|
||||
|
||||
def ensure_session_quiet(session, folder):
|
||||
"""ensure_session, without the line about switching: the caller explains."""
|
||||
if session in tuios.sessions():
|
||||
return False
|
||||
params = {"name": session, "cwd": folder, "window": False}
|
||||
out = subprocess.run(["tuios", "call", "new-session", json.dumps(params)],
|
||||
capture_output=True, text=True, timeout=60)
|
||||
if out.returncode != 0 and "session_exists" not in (out.stderr or out.stdout):
|
||||
raise h.Refused(3, "could not create session %r: %s"
|
||||
% (session, (out.stderr or out.stdout).strip()[:300]))
|
||||
return True
|
||||
|
||||
|
||||
def scaffold(folder, name):
|
||||
"""Write the files this project keeps, and only the ones that are missing.
|
||||
|
||||
@@ -237,6 +278,15 @@ def install_wrapper(addr, remote_bin):
|
||||
capture_output=True, text=True, timeout=60).stdout.strip()
|
||||
if not home:
|
||||
return
|
||||
# Never replace a wrapper that already works. Pushing from another machine
|
||||
# would otherwise rewrite the owner's own `office` command to point at the
|
||||
# copy that machine sent, which is how the canonical machine ended up
|
||||
# running someone else's older copy.
|
||||
existing = subprocess.run(
|
||||
["ssh", "-o", "BatchMode=yes", addr, 'cat "$HOME/.local/bin/office" 2>/dev/null'],
|
||||
capture_output=True, text=True, timeout=60).stdout
|
||||
if "paperclip-harness/bin/office" in existing:
|
||||
return
|
||||
script = ("#!/bin/sh\n"
|
||||
"# Written by office on another machine. Runs the copy it keeps here.\n"
|
||||
"#\n"
|
||||
@@ -291,6 +341,9 @@ def run_on_remote(host, folder, opts):
|
||||
for flag in ("--git-init", "--commit-all", "--anywhere"):
|
||||
if opts.get(flag[2:].replace("-", "_")):
|
||||
inner.append(flag)
|
||||
# So the instructions printed on the other machine say how to reach it from
|
||||
# where the person is sitting.
|
||||
inner += ["--client-host", host]
|
||||
if opts["dry"]:
|
||||
inner.append("--dry")
|
||||
# "$HOME" must stay unquoted so the other machine's shell expands it; every
|
||||
@@ -410,6 +463,12 @@ ON ANOTHER MACHINE
|
||||
is not on PATH yet, so there you call it by its full path:
|
||||
~/.local/share/paperclip-harness/bin/office <folder>
|
||||
|
||||
WHEN THE FILES ARE ON ANOTHER MACHINE
|
||||
The git work has to happen where the files are, because that is where the
|
||||
commit, the worktree and the agent are. So when a folder cannot hold a
|
||||
worktree yet, office makes a session on THAT machine with lazygit already
|
||||
open in the folder, and tells you how to attach to it. No ssh, no cd.
|
||||
|
||||
AFTER A REBOOT
|
||||
TUIOS restores a session with a fresh shell in every pane and keeps the pane
|
||||
names. Run board once for that project: it checks what each pane is actually
|
||||
@@ -482,7 +541,7 @@ def repeat_command(folder, opts):
|
||||
return " ".join(parts)
|
||||
|
||||
|
||||
def prepare_git(folder, opts):
|
||||
def prepare_git(folder, opts, session):
|
||||
"""Get the folder as far as it can go toward a worktree per task.
|
||||
|
||||
A worktree needs a repository and at least one commit. Neither is made
|
||||
@@ -568,6 +627,8 @@ def prepare_git(folder, opts):
|
||||
h.say(" space stage or unstage e edit a file, .gitignore included")
|
||||
h.say(" c commit ? every key")
|
||||
h.say("")
|
||||
open_git_session(folder, session, opts)
|
||||
h.say("")
|
||||
h.say(" Then repeat this command to create the project with worktrees:")
|
||||
h.say("")
|
||||
h.say(" %s" % repeat_command(folder, opts))
|
||||
@@ -643,7 +704,7 @@ def main():
|
||||
# Only now: a folder on another machine has already been handed over, and
|
||||
# the machine that owns it does these two checks itself.
|
||||
guard_machine(folder, opts)
|
||||
ready = prepare_git(folder, opts)
|
||||
ready = prepare_git(folder, opts, session)
|
||||
|
||||
if opts["dry"]:
|
||||
if opts["new"]:
|
||||
|
||||
Reference in New Issue
Block a user