Add snapshot files to list a snapshot's files without restoring it (closes #435)
check / check (push) In progress
check / check (push) In progress
`vaultik snapshot files <snapshot-id> [path] [--json]` downloads and decrypts the snapshot database, as restore does, and prints mode, size, modification time and path for every file at or under the path. A path that matches nothing is an error. It needs the private key. The mode is in Go's file-mode notation, which the README spells out. The table quotes a path that holds a non-printable character. Named `files` because `ls` is already the alias of `snapshot list`. The missing-key error no longer says "for restore", since this command and deep verify return it too. The README opening now states the private-key rule first. Model: opus-5-5
This commit is contained in:
1 parent
5ca0d46932
commit
88f2ea6f06
14 files changed
+552
-82
No files matched your search
+10
-6
@@ -17,6 +17,9 @@
|
||||
// Count, Percent) return ANSI-colored strings the caller composes into
|
||||
// the message body. When color is disabled (non-TTY output or NO_COLOR
|
||||
// set) all formatters return plain text.
|
||||
//
|
||||
// QuoteUnprintable is the same escaping without colour, for plain tables
|
||||
// that print paths from the snapshot database.
|
||||
package ui
|
||||
|
||||
import (
|
||||
@@ -227,17 +230,17 @@ func (w *Writer) Hex(s string) string {
|
||||
short = s[:hexAbbrevLen] + "..."
|
||||
}
|
||||
|
||||
return w.paint(ansiCyan, sanitize(short))
|
||||
return w.paint(ansiCyan, QuoteUnprintable(short))
|
||||
}
|
||||
|
||||
// Snapshot colorizes a snapshot ID (full, no abbreviation).
|
||||
func (w *Writer) Snapshot(id string) string {
|
||||
return w.paint(ansiCyan+ansiBold, sanitize(id))
|
||||
return w.paint(ansiCyan+ansiBold, QuoteUnprintable(id))
|
||||
}
|
||||
|
||||
// Path colorizes a filesystem path.
|
||||
func (w *Writer) Path(p string) string {
|
||||
return w.paint(ansiBlue, sanitize(p))
|
||||
return w.paint(ansiBlue, QuoteUnprintable(p))
|
||||
}
|
||||
|
||||
// Size colorizes a byte count using humanize.Bytes.
|
||||
@@ -312,14 +315,15 @@ func (w *Writer) paint(color, s string) string {
|
||||
return color + s + ansiReset
|
||||
}
|
||||
|
||||
// sanitize returns s unchanged when every rune in it is printable, and a
|
||||
// double-quoted, backslash-escaped form (\n, \x1b, …) otherwise. The
|
||||
// QuoteUnprintable returns s unchanged when every rune in it is printable,
|
||||
// and a double-quoted, backslash-escaped form (\n, \x1b, …) otherwise. The
|
||||
// string value formatters escape their argument through this before
|
||||
// painting: identifiers, paths and symlink targets they render come from
|
||||
// the snapshot database, which is not trusted, and escaping must happen
|
||||
// before colour is applied — the painted result already contains the
|
||||
// escape codes the raw text would otherwise be indistinguishable from.
|
||||
func sanitize(s string) string {
|
||||
// Plain tables call it directly.
|
||||
func QuoteUnprintable(s string) string {
|
||||
for _, r := range s {
|
||||
if !unicode.IsPrint(r) {
|
||||
return strconv.Quote(s)
|
||||
|
||||
Reference in new issue
Block a user