Skip to content

Add part of Safe clean #45

Merged
mors119 merged 2 commits into
FrilLab:mainfrom
mors119:feature/epic3-clean
Jun 2, 2026
Merged

Add part of Safe clean #45
mors119 merged 2 commits into
FrilLab:mainfrom
mors119:feature/epic3-clean

Conversation

@mors119
Copy link
Copy Markdown
Collaborator

@mors119 mors119 commented Jun 2, 2026

What

Safe cleaning and additional cleaning commands

Create cleanup plan and result
Add clean command
Add dry run support
Add confirmation prompt
Add cleanup summary and tests

Closes #22
Closes #23
Closes #24
Closes #25

Checklist

Required

  • cargo check passes
  • cargo fmt --check passes
  • cargo clippy --workspace --all-targets -- -D warnings passes
  • cargo test passes

Functional Validation

  • I verified the behavior locally
  • I added or updated tests when necessary

Documentation

  • README or docs were updated if needed
  • New configuration or behavior is documented

Safety

  • Cleanup behavior was reviewed for safety
  • No destructive behavior was introduced without confirmation

Summary by CodeRabbit

  • New Features

    • Implemented a functional clean command with cleanup preview, user confirmation prompt, and detailed result reporting (deleted/failed counts and freed size)
    • Added a --dry-run flag to preview cleanup operations without deleting files
    • Improved cleanup planning and accurate reclaimable-size reporting
  • Tests

    • Added comprehensive end-to-end tests covering planning and execution of cleanup workflows

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 68d06bd0-23c1-4d0c-aed4-577798cb1e27

📥 Commits

Reviewing files that changed from the base of the PR and between 75d0844 and 14ded46.

📒 Files selected for processing (5)
  • apps/dustfril-cli/src/cli.rs
  • apps/dustfril-cli/src/commands/clean.rs
  • crates/dustfril-core/src/cleaner/plan.rs
  • crates/dustfril-core/src/cleaner/tests.rs
  • crates/dustfril-core/src/models/cleanup_plan.rs
💤 Files with no reviewable changes (1)
  • crates/dustfril-core/src/cleaner/plan.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/dustfril-cli/src/cli.rs
  • crates/dustfril-core/src/cleaner/tests.rs

📝 Walkthrough

Walkthrough

Adds a fully implemented dfr clean command: structured CLI args with --dry-run, cleanup models (candidate/plan/result), create-plan and execute-delete logic, interactive confirmation, CLI dispatch branching, and comprehensive tests for planning and execution.

Changes

Clean Command Implementation

Layer / File(s) Summary
CLI argument definitions
apps/dustfril-cli/src/cli.rs
CleanArgs with --dry-run added; Commands::Clean changed to Clean(CleanArgs) and Clap derives/imports updated.
Cleanup data models
crates/dustfril-core/src/models/*
Added CleanupCandidate, CleanupPlan (with reclaimable_size_bytes()), and CleanupResult; models module reorganized and re-exports updated.
Cleaner planning and execution
crates/dustfril-core/src/cleaner/*
create_cleanup_plan builds a plan from AnalysisResult filtering SafeToClean; execute_cleanup deletes candidate directories for selected artifact types and returns CleanupResult; cleaner module wiring added.
CLI command implementation
apps/dustfril-cli/src/commands/clean.rs, apps/dustfril-cli/src/main.rs
dry_run() prints a preview; execute() prints preview, prompts confirmation, calls execute_cleanup, and reports results; main dispatches on --dry-run.
Cleanup workflow tests
crates/dustfril-core/src/cleaner/tests.rs
Tests for empty plan, SafeToClean filtering, Keep filtering, successful on-disk deletion, and missing-path failure behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • FrilLab/dustfril#34: Scaffolds the CLI clean subcommand; this PR implements structured args and full clean workflow building on that scaffold.

Poem

A rabbit hops through dusty code with glee,
Previewing cleanup with a gentle plea,
"--dry-run" shows targets, their sizes, their place,
Ask "Continue?" — then tidy up the space.
🐇✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Add part of Safe clean' is vague and ambiguous; it doesn't clearly convey what aspect of safe cleaning is being implemented or why 'part of' is mentioned. Revise the title to be more specific and descriptive, such as 'Implement clean command with dry-run and confirmation prompt' or 'Add safe cleanup workflow with dry-run support'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR implements all four linked objectives: clean command (#22), cleanup plan creation (#23), dry-run support (#24), and confirmation prompt (#25) with corresponding code changes.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the linked issues; no out-of-scope modifications were introduced beyond the cleanup workflow implementation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
crates/dustfril-core/src/models/cleanup_plan.rs (1)

3-7: 🏗️ Heavy lift

Avoid storing a mutable aggregate beside its source list.

candidates and reclaimable_size_bytes can drift apart because both are independently mutable. That turns into incorrect cleanup totals in previews and summaries. Prefer deriving the total from candidates or enforcing the invariant via a constructor/accessor.

One way to enforce the invariant
 use crate::models::CleanupCandidate;
 
 #[derive(Debug, Default)]
 pub struct CleanupPlan {
     pub candidates: Vec<CleanupCandidate>,
-
-    pub reclaimable_size_bytes: u64,
 }
+
+impl CleanupPlan {
+    pub fn reclaimable_size_bytes(&self) -> u64 {
+        self.candidates
+            .iter()
+            .map(|candidate| candidate.size_bytes)
+            .sum()
+    }
+}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/dustfril-core/src/models/cleanup_plan.rs` around lines 3 - 7, The
struct CleanupPlan currently stores a mutable aggregate reclaimable_size_bytes
alongside the source list candidates causing potential drift; remove the public
reclaimable_size_bytes field and instead derive the total on demand by adding a
method (e.g., CleanupPlan::reclaimable_size_bytes() or
total_reclaimable_bytes()) that iterates candidates and sums their sizes, or
alternatively make reclaimable_size_bytes private and populate/maintain it only
via a constructor and mutators that update it whenever candidates changes;
update any call sites that read reclaimable_size_bytes to call the new accessor
so the invariant is enforced by computation or controlled mutation in
CleanupPlan.
crates/dustfril-core/src/cleaner/executor.rs (1)

13-23: 🏗️ Heavy lift

Cleanup executor match is exhaustive; focus on better failure reporting instead.

  • ArtifactType has only Target, CargoRegistry, and CargoGit, so the executor’s match covers all variants (future enum additions will fail to compile rather than being silently skipped).
  • Remaining gap: remove_dir_all errors are collapsed to failed_paths without any error details, and the CLI only prints the number of failed paths (not which ones). Consider printing failed_paths and/or logging the underlying error.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/dustfril-core/src/cleaner/executor.rs` around lines 13 - 23, The
cleanup executor currently treats all fs::remove_dir_all failures the same by
only pushing candidate.path into result.failed_paths; update the failure
handling in the match arm that inspects candidate.artifact_type so you capture
and surface the underlying IO error (from fs::remove_dir_all) instead of
discarding it: on Err(e) include the error message alongside the path (e.g.,
extend result.failed_paths to carry path+error or push a structured failure
record) and ensure the CLI/logging prints these failed paths and their errors;
modify references around candidate.path, fs::remove_dir_all,
result.failed_paths, result.deleted_paths, and result.freed_size_bytes
accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/dustfril-cli/src/cli.rs`:
- Around line 24-27: Add a help string for the dry_run flag on the CleanArgs
struct so the CLI help shows why it exists; update the dry_run field
(CleanArgs::dry_run) to include either a field doc comment or an #[arg(help =
"...")] attribute that explains it performs a non-destructive dry run and does
not actually delete files (e.g., "Perform a dry run; show what would be removed
without deleting anything"), leaving the flag name #[arg(long)] unchanged.

---

Nitpick comments:
In `@crates/dustfril-core/src/cleaner/executor.rs`:
- Around line 13-23: The cleanup executor currently treats all
fs::remove_dir_all failures the same by only pushing candidate.path into
result.failed_paths; update the failure handling in the match arm that inspects
candidate.artifact_type so you capture and surface the underlying IO error (from
fs::remove_dir_all) instead of discarding it: on Err(e) include the error
message alongside the path (e.g., extend result.failed_paths to carry path+error
or push a structured failure record) and ensure the CLI/logging prints these
failed paths and their errors; modify references around candidate.path,
fs::remove_dir_all, result.failed_paths, result.deleted_paths, and
result.freed_size_bytes accordingly.

In `@crates/dustfril-core/src/models/cleanup_plan.rs`:
- Around line 3-7: The struct CleanupPlan currently stores a mutable aggregate
reclaimable_size_bytes alongside the source list candidates causing potential
drift; remove the public reclaimable_size_bytes field and instead derive the
total on demand by adding a method (e.g., CleanupPlan::reclaimable_size_bytes()
or total_reclaimable_bytes()) that iterates candidates and sums their sizes, or
alternatively make reclaimable_size_bytes private and populate/maintain it only
via a constructor and mutators that update it whenever candidates changes;
update any call sites that read reclaimable_size_bytes to call the new accessor
so the invariant is enforced by computation or controlled mutation in
CleanupPlan.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 60da3d46-3506-4f69-a1b5-da1511fa4650

📥 Commits

Reviewing files that changed from the base of the PR and between 0b7892d and 75d0844.

📒 Files selected for processing (11)
  • apps/dustfril-cli/src/cli.rs
  • apps/dustfril-cli/src/commands/clean.rs
  • apps/dustfril-cli/src/main.rs
  • crates/dustfril-core/src/cleaner/executor.rs
  • crates/dustfril-core/src/cleaner/mod.rs
  • crates/dustfril-core/src/cleaner/plan.rs
  • crates/dustfril-core/src/cleaner/tests.rs
  • crates/dustfril-core/src/models/cleanup_candidate.rs
  • crates/dustfril-core/src/models/cleanup_plan.rs
  • crates/dustfril-core/src/models/cleanup_result.rs
  • crates/dustfril-core/src/models/mod.rs

Comment on lines +24 to +27
#[derive(Args)]
pub struct CleanArgs {
#[arg(long)]
pub dry_run: bool,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add help text for --dry-run.

This flag is central to the safety story, but without a field doc comment it shows up in --help with no explanation.

Suggested fix
 #[derive(Args)]
 pub struct CleanArgs {
+    /// Preview cleanup operations without deleting files.
     #[arg(long)]
     pub dry_run: bool,
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#[derive(Args)]
pub struct CleanArgs {
#[arg(long)]
pub dry_run: bool,
#[derive(Args)]
pub struct CleanArgs {
/// Preview cleanup operations without deleting files.
#[arg(long)]
pub dry_run: bool,
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/dustfril-cli/src/cli.rs` around lines 24 - 27, Add a help string for the
dry_run flag on the CleanArgs struct so the CLI help shows why it exists; update
the dry_run field (CleanArgs::dry_run) to include either a field doc comment or
an #[arg(help = "...")] attribute that explains it performs a non-destructive
dry run and does not actually delete files (e.g., "Perform a dry run; show what
would be removed without deleting anything"), leaving the flag name #[arg(long)]
unchanged.

@mors119 mors119 merged commit c8d556b into FrilLab:main Jun 2, 2026
2 checks passed
@mors119 mors119 deleted the feature/epic3-clean branch June 2, 2026 17:53
@coderabbitai coderabbitai Bot mentioned this pull request Jun 2, 2026
10 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[TASK] Add confirmation prompt [TASK] Add dry run support [TASK] Create cleanup plan [FEATURE] Add clean command

1 participant