Add Browse Files button to snapshots screen
Select a snapshot and click Browse Files to see all files in that snapshot on the remote. Also adds 'gniza snapshots browse' CLI command. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
13
bin/gniza
13
bin/gniza
@@ -305,8 +305,19 @@ run_cli() {
|
||||
fi
|
||||
_restore_remote_globals
|
||||
;;
|
||||
browse)
|
||||
[[ -z "$target" ]] && die "browse requires --target=NAME"
|
||||
local snapshot=""
|
||||
snapshot=$(_parse_flag "--snapshot" "${SUBCMD_ARGS[@]+"${SUBCMD_ARGS[@]}"}") || true
|
||||
[[ -z "$snapshot" ]] && die "browse requires --snapshot=TS"
|
||||
if [[ -z "$remote" ]]; then
|
||||
remote=$(list_remotes | head -1)
|
||||
[[ -z "$remote" ]] && die "No remotes configured"
|
||||
fi
|
||||
list_snapshot_contents "$target" "$snapshot" "$remote"
|
||||
;;
|
||||
*)
|
||||
die "Unknown snapshots action: $action (expected list)"
|
||||
die "Unknown snapshots action: $action (expected list|browse)"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
@@ -111,6 +111,7 @@ SelectionList {
|
||||
#targets-buttons,
|
||||
#remotes-buttons,
|
||||
#logs-buttons,
|
||||
#snapshots-buttons,
|
||||
#sched-buttons,
|
||||
#sched-edit-buttons,
|
||||
#te-buttons,
|
||||
@@ -126,6 +127,7 @@ SelectionList {
|
||||
#targets-buttons Button,
|
||||
#remotes-buttons Button,
|
||||
#logs-buttons Button,
|
||||
#snapshots-buttons Button,
|
||||
#sched-buttons Button,
|
||||
#sched-edit-buttons Button,
|
||||
#te-buttons Button,
|
||||
|
||||
@@ -6,6 +6,7 @@ from textual import work
|
||||
|
||||
from tui.config import list_conf_dir
|
||||
from tui.backend import run_cli
|
||||
from tui.widgets import OperationLog
|
||||
|
||||
|
||||
class SnapshotsScreen(Screen):
|
||||
@@ -27,6 +28,8 @@ class SnapshotsScreen(Screen):
|
||||
yield Select([(r, r) for r in remotes], id="snap-remote", prompt="Select remote")
|
||||
yield Button("Load Snapshots", id="btn-load", variant="primary")
|
||||
yield DataTable(id="snap-table")
|
||||
with Horizontal(id="snapshots-buttons"):
|
||||
yield Button("Browse Files", id="btn-browse")
|
||||
yield Button("Back", id="btn-back")
|
||||
yield Footer()
|
||||
|
||||
@@ -42,6 +45,19 @@ class SnapshotsScreen(Screen):
|
||||
self.app.pop_screen()
|
||||
elif event.button.id == "btn-load":
|
||||
self._load_snapshots()
|
||||
elif event.button.id == "btn-browse":
|
||||
self._browse_snapshot()
|
||||
|
||||
def _selected_snapshot(self) -> str | None:
|
||||
try:
|
||||
table = self.query_one("#snap-table", DataTable)
|
||||
if table.cursor_row is not None and table.row_count > 0:
|
||||
row_key = table.coordinate_to_cell_key((table.cursor_row, 0)).row_key.value
|
||||
# The snapshot name is in the first (only) column
|
||||
return str(table.get_cell(row_key, "Snapshot"))
|
||||
return None
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
@work
|
||||
async def _load_snapshots(self) -> None:
|
||||
@@ -58,11 +74,36 @@ class SnapshotsScreen(Screen):
|
||||
lines = [l.strip() for l in stdout.splitlines() if l.strip() and not l.startswith("===")]
|
||||
if lines:
|
||||
for s in lines:
|
||||
table.add_row(s)
|
||||
table.add_row(s, key=s)
|
||||
else:
|
||||
self.notify("No snapshots found", severity="warning")
|
||||
if stderr:
|
||||
self.notify(stderr.strip(), severity="error")
|
||||
|
||||
@work
|
||||
async def _browse_snapshot(self) -> None:
|
||||
target_sel = self.query_one("#snap-target", Select)
|
||||
remote_sel = self.query_one("#snap-remote", Select)
|
||||
if not isinstance(target_sel.value, str) or not isinstance(remote_sel.value, str):
|
||||
self.notify("Select target and remote first", severity="error")
|
||||
return
|
||||
snapshot = self._selected_snapshot()
|
||||
if not snapshot:
|
||||
self.notify("Select a snapshot first", severity="warning")
|
||||
return
|
||||
target = str(target_sel.value)
|
||||
remote = str(remote_sel.value)
|
||||
log_screen = OperationLog(f"Files: {target}/{snapshot}", show_spinner=False)
|
||||
self.app.push_screen(log_screen)
|
||||
rc, stdout, stderr = await run_cli(
|
||||
"snapshots", "browse", f"--target={target}", f"--remote={remote}", f"--snapshot={snapshot}"
|
||||
)
|
||||
if stdout:
|
||||
log_screen.write(stdout)
|
||||
if stderr:
|
||||
log_screen.write(stderr)
|
||||
if not stdout and not stderr:
|
||||
log_screen.write("No files found.")
|
||||
|
||||
def action_go_back(self) -> None:
|
||||
self.app.pop_screen()
|
||||
|
||||
Reference in New Issue
Block a user