Skip to content

chore(ops): debt cleanup — file_ops, batch, search, archive - #113

Merged
leszek3737 merged 1 commit into
mainfrom
audit/16-debt-ops-file-batch
Jul 31, 2026
Merged

chore(ops): debt cleanup — file_ops, batch, search, archive#113
leszek3737 merged 1 commit into
mainfrom
audit/16-debt-ops-file-batch

Conversation

@leszek3737

@leszek3737 leszek3737 commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Debt cleanup: file_ops, batch, search, archive (PR-16)

Non-semantic cleanup of ops modules — style, dead code, dedup, doc accuracy. No behavior changes.

CI gate (all pass, worktree)

Gate Result
cargo fmt ✅ clean
cargo clippy --locked --all-targets -- -D warnings ✅ 0 warnings
cargo test --locked ✅ 981 lib + 302 integration, 0 failed
cargo build --release --locked

Fixed (16)

# File Finding
sevenz #9 archive/sevenz.rs use std::fs::{self};use std::fs;
sevenz #8 archive/sevenz.rs Documented SevenzExtractError duplication as forced by sevenz_rust callback API
tar #9 archive/tar.rs Documented MAX_CREATE_ENTRIES = MAX_LIST_ENTRIES lockstep relationship
zip #10 archive/zip.rs Documented compression_method_name _ => Unknown as forced by #[non_exhaustive] zip crate API
zip #12 archive/zip.rs std::fs::FileFile (already imported)
batch/tests #4 batch/tests.rs Removed dead _sizes = helpers::path_sizes(...) binding
chunk_copy #11 chunk_copy.rs Fully-qualified std::sync::mpsc::Sender / std::path::PathBuf → imports
common #8 file_ops/common.rs Deduplicated check_canceled — now delegates to check_optional_canceled (single impl)
common #9 file_ops/common.rs is_symlink() && is_dir_meta() branch now #[cfg(windows)] — unreachable on Unix
content #10 search/content.rs Merged split AtomicBool / Ordering imports into one use
name #8 search/name.rs Removed redundant !file_type.is_symlink()is_dir() already excludes symlinks
name #10 search/name.rs Merged split AtomicBool / Ordering imports into one use
pattern #10 search/pattern.rs .then(|| ...).flatten() → idiomatic if/else
search #10 search.rs Dropped redundant #[path = "search/..."] attrs on module declarations
move_ops #10 file_ops/move_ops.rs Documented #[cfg(test)] pub fn move_entry as test-only convenience wrapper
temp #10/#11 file_ops/temp.rs Added #[must_use] + Debug derive on TempDirGuard

Rejected (with justification)

# Reason
content #12 (truncation idiom inconsistency) Already resolved: all truncation sites already route through SearchOutcome::record_truncation(), which implements the get_or_insert-style dedup. No if truncated.is_none() sites exist in the current code — the finding describes code that was already standardized.
batch/tests #13 (f64 == on byte_percent() == 100.0) Not fragile in practice: byte_percent() returns the literal 100.0 (exactly representable in IEEE 754) when bytes_done >= bytes_total. The test asserts on a hardcoded constant return, not a computed float.
pattern #6 (greedy_wildcard_match O(n·m)) Design/perf, not debt. Search patterns are short user input (rarely pathological *a*a*a*b shapes); the DP matcher is correct and the worst case is academic for filenames. A linear-time rewrite would be a perf PR, not a debt PR.
pattern #7 (pub fn matches allocates MatchScratch) Design, not debt. The one-shot matches() is a convenience API; the hot loop already uses matches_with() with a reused scratch. Restructuring the public API shape is out of scope for a debt PR.
pattern #8 / search #11 (l <= f dead guard in try_simple_wildcard) Reviewed: star_positions[1] > star_positions[0] is the guard (line 320). The old l <= f check no longer exists in the current code — the finding references code already removed during the single-pass refactor.
search #12 (search_content_recursive foldable) Design, not debt. The wrapper allocates the Finder + visited set and seeds the context struct once per recursive scan. Folding it inline into search_content would duplicate the single-file vs directory branch and the setup — net more code, not less. The current split is the single-responsibility boundary.
model #5/#6/#7/#8/#9 (SearchError/Outcome API design) Design debates, not debt. Adding Display for SearchErrorKind, #[non_exhaustive], doc comments, and helper methods (is_empty/has_errors/merge) are API-shaping decisions that belong in a dedicated refactor, not a debt cleanup. Each would change the public API contract.
sevenz #7 (error_slot helper for 9 repeated sites) The error_slot.set(...) + return Error::Other(...) pattern is intrinsic to sevenz_rust's callback API: each call site sets a different SevenzExtractError variant before returning a sevenz_rust::Error. A helper would need to take the enum variant as a parameter, adding indirection without removing the per-site classification logic. The repetition is in the error classification, not boilerplate.
batch #12 (&Option<T>Option<&T> params) CZĘŚCIOWO: the batch functions receive cancel: &Option<Arc<AtomicBool>> from callers that hold the Option by value. Changing to Option<&T> would ripple through execute_batch_with_byte_progress and all its callers in ops::batch. API-shape change, not debt.
tar #10/#11 (TempFileReader inline / Box) Design. TempFileReader is a one-off adapter for the xz→temp-file path; extracting it to a named struct adds a file for a single match arm. Box<dyn Read> is forced by the multiple decompressor types (gz/bz2/zst/xz) returned from wrap_decompress.
delete #8/#9 (CRITICAL_DIRS duplication / /private prefix) CZĘŚCIOWO: the macOS and non-macos lists differ intentionally (macOS has /private, /Applications but not /tmp, /flatpak, etc.). Deriving one from the other would add build-script complexity for ~90% overlap that is already self-documenting. The /private without bare entry is intentional: /private itself is a real dir users may manage; /private/etc, /private/tmp, /private/var are system symlinks.
delete #11 (progress callback for delete_recursive) Feature gap, not debt. Adding a progress callback changes the function signature and all callers.
entry_ops #7/#9/#10 (missing tests / mode & 0o7777 mask / doc ratio) #7 is a test-coverage gap (not debt), #9 (mode & 0o7777) is correct behavior — set_permissions only applies the permission bits, and the mask is defensive; #10 (doc:code ratio) is subjective and the doc explains why (non-interactive caller, ancestor creation).
file_ops/mod #2/#3/#4/#11 (test dedup / test extraction / re-export visibility) Test refactors (#2/#3/#4) and visibility-level comments (#11) are test-maintainability debt that risks churn on the ~989-line inline test module for marginal benefit. Per AGENTS.md the tests should move to tests.rs but that's a large mechanical extraction, not a debt-cleanup fix.
move_ops #9 (too_many_arguments suppress) The 8-param copy_then_remove_src takes three injected closures (for testability) plus the data they report on. A MoveContext struct would group the closures but add a type whose only purpose is grouping — the params are intrinsic to the test-injection design.
content #8/#9/#11/#13 (test boilerplate / error-push inconsistency / temp_dir / ContentMatch alias) #8 (test boilerplate) and #11 (temp_dir vs TempDir) are test-maintenance gaps; #9 (inline error push vs push_read_error) — the inline pushes construct different SearchErrorKind variants per site, not boilerplate; #13 (ContentMatch alias private) is cosmetic.
walk #7/#8/#9 (context struct field dup / truncation order / re-export placement) #7: FileSearchContext/ContentSearchContext share visited/cancel/outcome but differ in their match-type and pattern/finder fields — a shared base struct would need generics or trait objects, adding complexity for 3 fields. #8 (truncation check order) is a semantic nuance, not debt. #9 (re-export placement) is cosmetic.

Summary by Sourcery

Clean up technical debt across ops modules with non-semantic refactors and documentation improvements in file operations, batch tests, search, and archive handling.

Enhancements:

  • Deduplicate and centralize cancellation checking logic in file operations, making required and optional cancel flows share a single implementation.
  • Clarify platform-specific directory handling in file removal utilities, explicitly gating Windows-only symlink/junction logic and documenting Unix behavior.
  • Streamline type usage and imports in chunked copy operations and archive handlers to avoid fully qualified paths and improve readability.
  • Document constraints and relationships in archive modules, including compression method naming and create-vs-list entry limits for tar and zip.
  • Consolidate atomic import usage in search modules and simplify pattern matching helpers for case-insensitive wildcard handling.
  • Mark temporary directory guards as debuggable and must-use to make lifecycle and cleanup behavior more explicit.

Documentation:

  • Augment inline docs explaining Windows vs Unix metadata semantics in file_ops, cancellation behavior, and test-only wrappers for move operations.
  • Improve documentation for archive modules, including sevenz error handling constraints, tar entry caps, and zip compression method naming tied to non-exhaustive enums.

Tests:

  • Remove dead code from batch move cancellation tests and document test-only conveniences in move operations used by integration tests.

@sourcery-ai

sourcery-ai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Reviewer's Guide

Non-semantic ops cleanup across file operations, batch tests, search, and archive modules: minor refactors, dead-code removal/annotation, import deduplication, and documentation clarifications with no behavior changes.

File-Level Changes

Change Details Files
File operations common helpers refactored for deduplication and clearer platform-specific behavior.
  • Made check_canceled delegate to check_optional_canceled to centralize cancel error handling.
  • Annotated is_dir_meta behavior and added #[allow(dead_code)] for Unix-only implementation.
  • Gated the is_symlink() && is_dir_meta() branch in remove_any behind #[cfg(windows)] and expanded comments on Windows vs Unix symlink handling.
src/ops/file_ops/common.rs
Chunked copy implementation cleaned up by using imported types instead of fully-qualified paths.
  • Imported Sender and PathBuf and used them instead of fully-qualified std paths.
  • Updated copy_with_progress and copy_to_temp to accept &Sender instead of &std::sync::mpsc::Sender.
  • Changed temp path helpers to return PathBuf instead of std::path::PathBuf.
src/ops/chunk_copy.rs
Archive modules received documentation fixes and minor import cleanup for clarity about limits and external APIs.
  • Documented CompressionMethod string mapping and the non-exhaustive nature of the zip crate enum, and used File alias instead of std::fs::File in extract_zip.
  • Documented the lockstep relationship between MAX_CREATE_ENTRIES and MAX_LIST_ENTRIES in tar archives.
  • Simplified sevenz fs import from use std::fs::{self} to use std::fs.
src/ops/archive/zip.rs
src/ops/archive/tar.rs
src/ops/archive/sevenz.rs
Search modules cleaned up imports and simplified pattern logic while removing redundant conditions.
  • Merged separate AtomicBool and Ordering imports into a single use in content and name search modules.
  • Removed redundant !is_symlink() check when determining plain_dir in name search recursion, with comments explaining FileType behavior.
  • Rewrote then(
Move and temp file ops gained clearer documentation and attributes for test-only APIs and RAII guards.
  • Documented #[cfg(test)] move_entry as a test-only convenience wrapper that synthesizes progress and cancel tokens and clarified its public visibility rationale.
  • Added #[must_use] and Debug derive to TempDirGuard to make its RAII semantics explicit and aid debugging.
src/ops/file_ops/move_ops.rs
src/ops/file_ops/temp.rs
Batch tests were slightly simplified by removing unused code.
  • Removed dead _sizes binding that computed path sizes but was never used in batch_move_cancel_reports_canceled.
src/ops/batch/tests.rs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@greptile-apps

greptile-apps Bot commented Jul 31, 2026

Copy link
Copy Markdown

Greptile Summary

This PR performs behavior-preserving cleanup across archive, file-operation, batch, and search modules.

  • Simplifies imports, module declarations, and wildcard-affix construction.
  • Deduplicates cancellation handling and gates a Windows-specific removal branch.
  • Removes an unused test binding and adds documentation for intentional implementation constraints.
  • Adds Debug and must_use annotations to TempDirGuard.

Confidence Score: 5/5

The PR appears safe to merge, with no actionable behavioral, build, or security regressions identified.

The functional-looking edits preserve existing cancellation, removal, directory traversal, wildcard construction, and module-resolution behavior; the remaining changes affect imports, tests, documentation, or annotations only.

Important Files Changed

Filename Overview
src/ops/file_ops/common.rs Delegates mandatory cancellation checks to the equivalent optional helper and compiles the directory-symlink removal branch only on Windows without changing supported platform behavior.
src/ops/search/name.rs Removes a redundant symlink predicate because DirEntry::file_type().is_dir() already excludes symlinks, while the separate symlink traversal path remains intact.
src/ops/search/pattern.rs Replaces an Option flattening expression with an equivalent conditional while preserving all sensitivity and affix states.
src/ops/search.rs Removes redundant module path attributes whose paths exactly match Rust's default module layout.
src/ops/file_ops/temp.rs Adds diagnostic and compiler-use annotations to the temporary-directory guard without changing its lifecycle behavior.
src/ops/archive/tar.rs Documents the intended lockstep relationship between archive creation and listing entry limits.
src/ops/archive/zip.rs Documents non-exhaustive compression-method handling and uses the existing File import.
src/ops/chunk_copy.rs Replaces fully qualified standard-library types with equivalent imports.

Reviews (1): Last reviewed commit: "chore(ops): debt — file_ops, batch, sear..." | Re-trigger Greptile

@opencode-agent

Copy link
Copy Markdown

PR Review: chore(ops): debt cleanup

Verdict: Approve. I verified every change against the source and ran the full CI gate — all green:

Gate Result
cargo fmt --check clean
cargo clippy --locked --all-targets 0 warnings
cargo test --locked 980 lib + 302 integration, 0 failed
cargo build --release --locked ok

Bugs / correctness

None found. The two semantically meaningful changes are verified behavior-preserving:

  • check_canceled delegation (common.rs:43): check_optional_canceled(Some(cancel)) produces identical behavior — same ErrorKind::Interrupted, same message, same Ordering::Relaxed.
  • #[cfg(windows)] gate on the remove_any symlink branch (common.rs:263): correct. I confirmed is_dir_meta has no remaining Unix callersdelete.rs:6 gates its own use to #[cfg(windows)], so after this gate the Unix is_dir_meta stub is genuinely dead, justifying the new #[allow(dead_code)]. The claim "unreachable on Unix" holds: symlink_metadata lstat of a symlink is never is_dir().

The smaller refactor claims all check out: name.rs !is_symlink() removal is valid (FileType::is_dir() excludes symlinks); pattern.rs .then(||...).flatten()if/else is exactly equivalent; no remaining FQN sites or newly-orphaned imports; the tar/zip/MAX_LIST_ENTRIES (all 100_000) lockstep doc is factually accurate.

Issues to flag (all minor)

  1. PR body test count is off. Claims 981 lib tests; actual is 980. No tests were added/removed, so it's just a miscount — worth correcting for traceability, not a code problem.

  2. #[allow(dead_code)] could be avoided (common.rs:30). Since the Unix is_dir_meta stub now has zero callers, making is_dir_meta Windows-only (#[cfg(windows)] only, dropping the #[cfg(not(windows))] stub + the allow) would remove a lint suppression. Keeping the stub for doc symmetry is a defensible alternative, but it does trade a #[allow] for intent. AGENTS.md discourages #[allow(...)] outside tests.

  3. move_ops.rs doc placement (move_ops.rs:120-123). The new "Test-only convenience wrapper" paragraph is appended to a doc block (lines 110-118) that actually describes move_entry_impl's case-rename semantics, not the wrapper. The placement is pre-existing, but the addition deepens the incongruity — consider moving the impl-specific prose onto move_entry_impl.

  4. No Windows CI coverage. The PR modifies #[cfg(windows)] removal/symlink logic that the ubuntu+macOS matrix never compiles. Pre-existing gap, not introduced here, but the Windows path-removal correctness now rests entirely on the doc comments rather than any build.

The rejection table is thorough and shows sound judgment (especially pattern #6 perf-not-debt, delete #8 intentional /private distinction, and model #5-9 API-shaping-not-debt). No requested changes blocking merge.

New%20session%20-%202026-07-31T13%3A28%3A06.483Z
opencode session  |  github run

@leszek3737
leszek3737 merged commit 5ed42d7 into main Jul 31, 2026
7 checks passed
@leszek3737
leszek3737 deleted the audit/16-debt-ops-file-batch branch July 31, 2026 14:19
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.

1 participant