Hold back the Disk panel and OS drag-out from the ship branch
This is a scope reduction, not an abandonment. Both subsystems are
preserved in full on `hold/disk-and-dragout` and are intended to come
back once they have been hardened separately. Nothing here is a
judgement that the features are unwanted — three successive
audit-and-fix cycles each closed a critical defect in these two areas
and each opened a new one, so the rest of the round ships now and these
two get their own cycle rather than holding it up.
Removed: the Disk settings panel and its whole reclaim / destroy /
compaction surface — `DiskSettings`, `DiskProjectTable`, `useDiskUsage`,
`docker/disk.rs`, `disk_tests.rs`, the disk commands in
`docker_commands.rs`, and their `generate_handler!` entries. Dropping
the IPC entries is the point: a UI-only removal would have left five
commands callable by a compromised webview, one of them a verified
arbitrary-DELETE primitive. `sweep_orphaned_snapshots`'s *command* goes
with them (the panel was its only caller); the sweep itself stays.
Removed: OS drag-out from the Files tab — `stage_container_file_for_drag`
and its host staging lifecycle, the pointer gesture and `dragPreview`,
`stageForDrag` / `isStagedHostPath`, the `tauri-plugin-drag` and
`@crabnebula/tauri-plugin-drag` dependencies, and the
`drag:allow-start-drag` capability grant, which could not be scoped.
The capability test's expected list is updated; its `*:default` and
`store:*` assertions are untouched.
Kept, deliberately: drag-and-drop *into* the app (Files pane and
terminal) and "Save to host…", which is now the only route out of a
container. The prevention work is untouched — the pre-commit scrub and
`SNAPSHOT_SCRUB_PATHS`, capped container logs, the `triple-c.base` /
`triple-c.managed` labels, `sweep_orphaned_snapshots` and the startup
housekeeping, the migration pin/probe reapers, scheduler log pruning,
`formatBytes.ts`, and `project_lock.rs` in full with every acquisition
site outside `disk.rs`.
Entanglements, resolved rather than deleted blind:
* `container.rs`'s `a_compaction_runs_this_module_s_scrub_script_byte_for_byte`
pinned the compaction Dockerfile against `snapshot_scrub_script()`.
Dropped — it existed only for compaction. `snapshot_scrub_script` and
its containment tests are untouched.
* `lib.rs`'s startup reap of `:compacting` tags and `triple-c-compact-*`
containers is dropped: nothing on this branch creates them.
* `project_lock`'s `Compaction` / `CacheClear` variants and
`any_held_excluding`, `migration_commands::is_migrating`, and
`formatBytes{Delta,Ceiling}` lose their last production caller but are
kept and still tested, annotated with why.
* `projects_store::corrupt_since` and `migration_store::peek_ownerless_since`
were read only by the disk survey and are removed. The corrupt-load
marker and `.bak` are still written.
Verified: `npm run test` 611 passing, `npx tsc --noEmit` clean,
`npm run build` green; `cargo test` 419 passed / 2 ignored,
`cargo build` 0 warnings. Every test removed belongs to a removed
feature — no kept-behaviour test was weakened or deleted.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GBq2rGum6GX7xXgsas1fDc
This commit is contained in:
@@ -54,80 +54,3 @@ pub async fn list_sibling_containers() -> Result<Vec<serde_json::Value>, String>
|
||||
.collect();
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Disk
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// The disk view's IPC surface. It lives here rather than in a module of its own
|
||||
// for the same reason `check_image_exists` does: these are thin shims over
|
||||
// `crate::docker`, and the logic they call is in `docker/disk.rs` where it can
|
||||
// be unit-tested without a daemon.
|
||||
|
||||
/// Measure where the daemon's bytes have gone.
|
||||
///
|
||||
/// **Expensive on purpose.** This is `GET /system/df` plus an `image_history`
|
||||
/// per distinct image, and `df()` walks every image, container and volume on
|
||||
/// the daemon to compute shared-layer sizes. On a 100 GB store that is seconds.
|
||||
/// The frontend must keep it behind an explicit Scan button — never on panel
|
||||
/// open, never on a timer.
|
||||
#[tauri::command]
|
||||
pub async fn get_docker_disk_usage(
|
||||
state: State<'_, AppState>,
|
||||
) -> Result<docker::disk::DiskUsageReport, String> {
|
||||
let projects = state.projects_store.list();
|
||||
docker::disk::scan(&projects).await
|
||||
}
|
||||
|
||||
/// Everything that could be reclaimed, each with its measured cost.
|
||||
///
|
||||
/// Takes the report from [`get_docker_disk_usage`] rather than re-measuring, so
|
||||
/// a user who re-plans after ticking a box does not pay for a second `df()`.
|
||||
#[tauri::command]
|
||||
pub async fn list_reclaimable(
|
||||
report: docker::disk::DiskUsageReport,
|
||||
state: State<'_, AppState>,
|
||||
) -> Result<docker::disk::ReclaimPlan, String> {
|
||||
let projects = state.projects_store.list();
|
||||
docker::disk::list_reclaimable(&projects, &report).await
|
||||
}
|
||||
|
||||
/// Run the ticked targets and report what each one actually freed.
|
||||
///
|
||||
/// `ReclaimTarget` cannot express a destructive action — that is a different
|
||||
/// type, reached only through [`destroy_project_disk_object`] with a typed
|
||||
/// confirmation — so there is no selection a user can build here that deletes a
|
||||
/// live project's data.
|
||||
#[tauri::command]
|
||||
pub async fn reclaim(
|
||||
targets: Vec<docker::disk::ReclaimTarget>,
|
||||
state: State<'_, AppState>,
|
||||
) -> Result<docker::disk::ReclaimOutcome, String> {
|
||||
let projects = state.projects_store.list();
|
||||
Ok(docker::disk::reclaim(&targets, &projects).await)
|
||||
}
|
||||
|
||||
/// Delete one object that has no other copy, against a typed confirmation of
|
||||
/// the project's name.
|
||||
///
|
||||
/// Deliberately one target per call: this is never part of a bulk action.
|
||||
#[tauri::command]
|
||||
pub async fn destroy_project_disk_object(
|
||||
target: docker::disk::DestructiveTarget,
|
||||
confirmation: String,
|
||||
state: State<'_, AppState>,
|
||||
) -> Result<docker::disk::ReclaimResult, String> {
|
||||
let projects = state.projects_store.list();
|
||||
docker::disk::destroy(&target, &confirmation, &projects).await
|
||||
}
|
||||
|
||||
/// Run the orphaned-snapshot sweep on demand and return its report.
|
||||
///
|
||||
/// The sweep already runs at startup, after every recreation and after a
|
||||
/// migration settles, but every one of those callers throws the report away —
|
||||
/// so a user has never been able to see that 11.9 GB of superseded images were
|
||||
/// found and left because a stopped container still pinned them.
|
||||
#[tauri::command]
|
||||
pub async fn sweep_orphaned_snapshots() -> Result<docker::SnapshotSweepReport, String> {
|
||||
Ok(docker::sweep_orphaned_snapshots().await)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user