Add URLs to add, and a migrate command that deletes originals

add now downloads http(s) URLs (with a Chrome user agent) through a
private temporary file, and treats ".", ".." and "/" as "this folder's
contents" so the destination folder is no longer dropped for "..".

migrate is add followed by deleting each original and any directories
left empty. It asks on the terminal before overwriting anything already
in the vault, refusing when there is no terminal, unless --yes is given.

Adding or migrating a directory skips the vault and key file if they
live inside it, so migrate can never ingest or delete them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andy Dixon
2026-09-28 15:59:09 +01:00
co-authored by Claude Opus 5.5
parent 8b7a7f1415
commit eb138b5524
5 changed files with 287 additions and 20 deletions
+19
View File
@@ -1,9 +1,11 @@
package term
import (
"bufio"
"fmt"
"os"
"runtime"
"strings"
"golang.org/x/term"
)
@@ -72,6 +74,23 @@ func ReadSecret(prompt string) (s []byte, err error) {
return
}
// Confirm asks a yes/no question on the terminal. Only "y" or "yes" is yes.
func Confirm(prompt string) (yes bool, err error) {
err = WithTerminal(func(in, out *os.File) error {
fmt.Fprintf(out, "%s ", prompt)
line, err := bufio.NewReader(in).ReadString('\n')
if err != nil && line == "" {
return err
}
switch strings.ToLower(strings.TrimSpace(line)) {
case "y", "yes":
yes = true
}
return nil
})
return
}
// ReadPassphrase returns the passphrase from the environment variable env if
// it is set, otherwise prompts on the terminal.
func ReadPassphrase(prompt, env string) (string, error) {