Re-shoot the guide's screenshots and add one for migrate
shots.py gains a pseudo-terminal runner so it can answer migrate's overwrite question, and the guide shows the resulting screenshot. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Before Width: | Height: | Size: 165 KiB After Width: | Height: | Size: 165 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 266 KiB After Width: | Height: | Size: 311 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 129 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 142 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
@@ -16,6 +16,7 @@ import glob
|
||||
import grp
|
||||
import html
|
||||
import os
|
||||
import pty
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -94,6 +95,28 @@ class Sandbox:
|
||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
||||
return self.tidy(p.stdout)
|
||||
|
||||
def run_tty(self, command, passphrase, answer):
|
||||
"""Run on a pseudo-terminal, typing answer at vault's [y/N] question."""
|
||||
env = self.env({"VAULT_PASSPHRASE": passphrase})
|
||||
pid, fd = pty.fork()
|
||||
if pid == 0:
|
||||
os.chdir(self.home)
|
||||
os.execve("/bin/bash", ["bash", "-c", command], env)
|
||||
out = b""
|
||||
while b"[y/N]" not in out:
|
||||
out += os.read(fd, 1024)
|
||||
os.write(fd, answer.encode() + b"\n")
|
||||
try:
|
||||
while True:
|
||||
chunk = os.read(fd, 1024)
|
||||
if not chunk:
|
||||
break
|
||||
out += chunk
|
||||
except OSError:
|
||||
pass
|
||||
os.waitpid(pid, 0)
|
||||
return self.tidy(out.decode().replace("\r\n", "\n"))
|
||||
|
||||
def tidy(self, text):
|
||||
owner = " %s %s " % (getpass.getuser(), grp.getgrgid(os.getgid()).gr_name)
|
||||
return text.replace(self.home, SHOWN_HOME).replace(owner, " sam sam ").rstrip("\n")
|
||||
@@ -278,6 +301,20 @@ def main():
|
||||
t.cmd("find ~/.vault/store/records -type f | wc -l")
|
||||
shoot("decoy-hidden", t)
|
||||
|
||||
# migrate: one file is already in the vault, so it asks first
|
||||
box.write("Scans/receipts/march.pdf", os.urandom(48_113))
|
||||
box.write("Scans/receipts/april.pdf", os.urandom(51_870))
|
||||
box.run("vault add Scans/receipts/march.pdf receipts", P)
|
||||
t = Term(box)
|
||||
t.lines.append(prompt() + '<span class="c">vault migrate Scans/receipts</span>')
|
||||
for line in box.run_tty("vault migrate Scans/receipts", P, "y").split("\n"):
|
||||
esc = html.escape(line)
|
||||
if "[y/N]" in line:
|
||||
esc = '<span class="hl">%s</span>' % esc
|
||||
t.lines.append(esc)
|
||||
t.cmd("ls Scans")
|
||||
shoot("migrate", t)
|
||||
|
||||
# errors
|
||||
t = Term(box)
|
||||
t.cmd("vault list", "hunter2", highlight=("incorrect",))
|
||||
|
||||
@@ -572,6 +572,8 @@ before touching anything. Answer anything but \texttt{y} and nothing changes.
|
||||
With no terminal to ask on, the answer is no. For scripts, \texttt{--yes}
|
||||
answers yes up front.
|
||||
|
||||
\shot{migrate}{Moving a folder in. One file was already there, so vault asked first.}
|
||||
|
||||
\subsection{What gets skipped}
|
||||
When adding a folder, anything that isn't a plain file, such as symbolic
|
||||
links, sockets or devices, is skipped with a note. So are the vault and key
|
||||
|
||||