Skip to content

Split srch flat collector into interactive builder and reusable mover#16

Open
ib-bsb-br wants to merge 1 commit into
mainfrom
codex/refactor-script-to-use-srch-tool
Open

Split srch flat collector into interactive builder and reusable mover#16
ib-bsb-br wants to merge 1 commit into
mainfrom
codex/refactor-script-to-use-srch-tool

Conversation

@ib-bsb-br

@ib-bsb-br ib-bsb-br commented Mar 22, 2026

Copy link
Copy Markdown
Owner

Motivation

  • Reduce complexity and heredoc usage by separating the interactive srch command builder from the per-match mover so the mover can be versioned, unit-tested, and reused across runs.
  • Preserve the original goals: collect regular files into a single-level destination under /home/linaro, provide deterministic collision handling, maintain an auditable centralized log, and support safe cross-filesystem moves.
  • Make concurrency-safe name allocation explicit (prefer flock with a mkdir-lock fallback), provide a DRYRUN mode, and enforce destination ownership/permissions for operational consistency.

Description

  • Added /usr/local/bin/srch_flat_collect, an interactive builder that collects srch start points and options, rotates and initializes operation_log.txt, exports DESTDIR/LOGFILE/LOCKFILE/LOCKDIR/DRYRUN, and invokes srch ... -r /usr/local/libexec/srch_move_one with all output wrapped via fold to avoid long unbroken lines.
  • Added /usr/local/libexec/srch_move_one, a standalone per-file mover that normalizes incoming paths, reserves a destination name under lock, applies deterministic numeric suffixes (_NNN) before extensions for collisions, performs copy+delete semantics to support cross-filesystem moves, and writes folded audit lines to the centralized log.
  • Implemented concurrency-safe locking using flock when available with a mkdir-based lockdir fallback, and implemented a DRYRUN path that logs intended actions without creating files.
  • Enforced post-run ownership and permissions with chown -R linaro:linaro and chmod -R a+rwX on the destination and ensured both scripts check for required tooling (srch, fold) and run as root.

Testing

  • No automated tests were executed for these script and documentation changes.

Codex Task

Summary by Sourcery

Document the design and intended behavior of a two-script refactor that separates an interactive srch-based collector from a reusable per-file mover for flat file collection into /home/linaro with deterministic naming and audit logging.

New Features:

  • Introduce the srch_flat_collect interactive builder script path at /usr/local/bin and the srch_move_one reusable mover helper at /usr/local/libexec as separate, versionable entry points for the collection workflow.

Documentation:

  • Add a comprehensive specification in README describing the srch_flat_collect builder and srch_move_one mover, their environment, constraints, behaviors, and usage, including collision handling, logging, permissions, and locking semantics.

Summary by cubic

Split the srch flat collector into an interactive builder and a reusable per-file mover to simplify the workflow and make moves safer and testable. Preserves flat collection under /home/linaro with deterministic collision handling and centralized logging.

  • Refactors

    • Introduced /usr/local/bin/srch_flat_collect to build srch options interactively, rotate/init the log, export DESTDIR/LOGFILE/LOCKFILE/LOCKDIR/DRYRUN, and invoke srch -r /usr/local/libexec/srch_move_one.
    • Output is wrapped with fold, regular-file matching is enforced (-f), and root/tool checks are performed.
    • README expanded with the two-script spec, examples, usage, and limitations.
  • New Features

    • Added /usr/local/libexec/srch_move_one: a standalone per-file mover that normalizes paths and writes auditable log lines.
    • Concurrency-safe name reservation using flock with a mkdir-based fallback; collision suffixes _NNN are applied before extensions.
    • Cross-filesystem support via copy+delete semantics, plus DRYRUN mode that logs intended actions only.
    • Post-run ownership and permissions enforced on the destination (linaro:linaro, a+rwX).

Written for commit 02ef961. Summary will update on new commits.

@sourcery-ai

sourcery-ai Bot commented Mar 22, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refactors the srch-based flat file collector into an interactive builder script and a reusable per-file mover, with explicit logging, deterministic collision handling, concurrency-safe locking, and enforced destination ownership/permissions, and documents the design in README.md.

Flow diagram for srch_move_one per-file move logic

flowchart TD
  A["Start srch_move_one"] --> B["Validate environment and required vars
DESTDIR, LOGFILE, LOCKFILE or LOCKDIR"]
  B --> C["Normalize source path to absolute"]
  C --> D{"Source exists and is regular file?"}
  D -->|no| E["Log error to LOGFILE"]
  E --> Z["End"]

  D -->|yes| F["Acquire lock
(flock on LOCKFILE
or mkdir LOCKDIR)"]
  F --> G["Derive base name and extension"]
  G --> H["Select collision-free name
with _NNN suffix if needed"]
  H --> I{"DRYRUN enabled?"}

  I -->|yes| J["Log planned move
source -> DESTDIR/target"]
  J --> M["Release lock"]
  M --> Z

  I -->|no| K["Copy source to
DESTDIR/target"]
  K --> L{"Copy succeeded?"}
  L -->|no| E

  L -->|yes| N["Delete original source file"]
  N --> O["Log successful move
original path, final name"]
  O --> M
Loading

File-Level Changes

Change Details Files
Document the two-script srch refactor design, behavior, and constraints in README
  • Replace placeholder README with a formal specification describing the builder and mover scripts, environment, constraints, and variables
  • Detail required behavior for interactive srch option collection, collision handling, logging, and copy+delete semantics
  • Document output format, example usage, self-check checklist, evaluation scenarios, and known limitations
README.md
Add interactive srch_flat_collect builder that prepares environment and invokes srch with reusable mover
  • Introduce /usr/local/bin/srch_flat_collect as a standalone script location for the interactive builder
  • Have the builder script collect srch roots and options, enforce regular-file selection, and construct the srch command
  • Ensure the builder sets DESTDIR, LOGFILE, LOCKFILE/LOCKDIR, and DRYRUN, rotates existing logs, and runs srch -r with the mover while wrapping output via fold
usr/local/bin/srch_flat_collect
Add srch_move_one reusable mover for deterministic, logged, flat-destination moves
  • Introduce /usr/local/libexec/srch_move_one as a standalone helper invoked via srch -r for each match
  • Normalize incoming paths, allocate unique names with numeric suffixes before extensions under lock, and perform copy+delete semantics for cross-filesystem safety
  • Implement concurrency-safe locking via flock with mkdir fallback, DRYRUN behavior for no-op runs, and centralized folded audit logging to operation_log.txt while enforcing destination ownership and permissions
usr/local/libexec/srch_move_one

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 left some high level feedback:

  • The README now reads more like an internal specification/template than user-facing documentation; consider adding a concise, task-oriented section that shows how an operator actually runs srch_flat_collect and interprets operation_log.txt without needing to parse the full spec.
  • For the locking implementation (flock with mkdir-based fallback), ensure that all early-exit and error paths reliably release the lockfile/lockdir so that interrupted runs cannot block subsequent invocations indefinitely.
  • The heavy reliance on interactive prompts in srch_flat_collect may make automation difficult; consider supporting a non-interactive mode (e.g., flags or environment variables) so the same logic can be reused in scripted workflows without TTY prompts.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The README now reads more like an internal specification/template than user-facing documentation; consider adding a concise, task-oriented section that shows how an operator actually runs `srch_flat_collect` and interprets `operation_log.txt` without needing to parse the full spec.
- For the locking implementation (`flock` with mkdir-based fallback), ensure that all early-exit and error paths reliably release the lockfile/lockdir so that interrupted runs cannot block subsequent invocations indefinitely.
- The heavy reliance on interactive prompts in `srch_flat_collect` may make automation difficult; consider supporting a non-interactive mode (e.g., flags or environment variables) so the same logic can be reused in scripted workflows without TTY prompts.

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.

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the srch flat collector script into two separate scripts: an interactive builder and a reusable mover. This separation improves code maintainability, testability, and reusability. The changes also introduce concurrency-safe locking, comprehensive logging, and a dry-run mode to enhance the reliability and safety of file operations.

Highlights

  • Refactoring: The srch flat collector script was split into an interactive builder (srch_flat_collect) and a reusable mover (srch_move_one) to reduce complexity and improve maintainability.
  • Concurrency Safety: Implemented concurrency-safe locking using flock with a mkdir-based lockdir fallback to prevent naming collisions during file moves.
  • Auditing and Logging: The changes preserve auditability by rotating existing logs and recording the full srch invocation context in a centralized log file.
  • Operational Consistency: Enforced post-run ownership and permissions with chown -R linaro:linaro and chmod -R a+rwX on the destination directory to ensure consistent file access.
  • Dry-Run Mode: Implemented a DRYRUN mode that logs intended actions without creating files, allowing for testing and verification before actual execution.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@cubic-dev-ai cubic-dev-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.

2 issues found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="README.md">

<violation number="1" location="README.md:35">
P2: The README contains unresolved template placeholders (`[[...]]`) and prompt-structure tags, which makes the documentation non-actionable for users.</violation>
</file>

<file name="usr/local/libexec/srch_move_one">

<violation number="1" location="usr/local/libexec/srch_move_one:21">
P2: `_lock_release` never releases the flock lock, so each worker holds the lock for the entire script run and unintentionally serializes concurrent moves.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread README.md
</context>

<variables>
<variable name="[[task_request]]" required="true">

@cubic-dev-ai cubic-dev-ai Bot Mar 22, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: The README contains unresolved template placeholders ([[...]]) and prompt-structure tags, which makes the documentation non-actionable for users.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At README.md, line 35:

<comment>The README contains unresolved template placeholders (`[[...]]`) and prompt-structure tags, which makes the documentation non-actionable for users.</comment>

<file context>
@@ -1 +1,137 @@
+  </context>
+
+  <variables>
+    <variable name="[[task_request]]" required="true">
+      <description>Refactor the srch-based collection workflow into a builder and a reusable mover with consistent logging and collision handling.</description>
+    </variable>
</file context>
Fix with Cubic

if command -v flock >/dev/null 2>&1; then
exec 9>>"$LOCKFILE"
flock -x 9
return 0

@cubic-dev-ai cubic-dev-ai Bot Mar 22, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: _lock_release never releases the flock lock, so each worker holds the lock for the entire script run and unintentionally serializes concurrent moves.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At usr/local/libexec/srch_move_one, line 21:

<comment>`_lock_release` never releases the flock lock, so each worker holds the lock for the entire script run and unintentionally serializes concurrent moves.</comment>

<file context>
@@ -0,0 +1,124 @@
+  if command -v flock >/dev/null 2>&1; then
+    exec 9>>"$LOCKFILE"
+    flock -x 9
+    return 0
+  fi
+  if [[ -z "$LOCKDIR" ]]; then
</file context>
Fix with Cubic

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request is a great step forward in refactoring the collection workflow into a more modular and maintainable two-script design. The separation of the interactive builder from the file mover is well-executed. However, I've identified a few high-severity issues that should be addressed. The builder script contains bugs related to parsing user input with spaces, which will cause incorrect behavior for paths or arguments containing spaces. Additionally, the mover script has an issue with its flock locking mechanism, where locks are not released promptly, leading to unnecessary serialization of file moves and reduced concurrency. I've also included a suggestion to improve the readability of the README.md file by using standard Markdown formatting.

Comment on lines +110 to +111
# shellcheck disable=SC2206
SRCH_ROOTS=( $roots_raw )

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Unquoted expansion of $roots_raw will cause issues with paths that contain spaces, even if they are quoted in the input. The shellcheck disable=SC2206 indicates awareness, but this is a bug that should be fixed. Use read -r -a with a here-string to correctly parse space-separated arguments into an array, which respects quotes.

read -r -a SRCH_ROOTS <<< "$roots_raw"

Comment on lines +217 to +218
# shellcheck disable=SC2206
extra_arr=( $extra_raw )

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Unquoted expansion of $extra_raw will cause issues with arguments that contain spaces, even if they are quoted in the input. The shellcheck disable=SC2206 indicates awareness, but this is a bug that should be fixed. Use read -r -a with a here-string to correctly parse space-separated arguments into an array.

  read -r -a extra_arr <<< "$extra_raw"


_lock_release() {
if command -v flock >/dev/null 2>&1; then
return 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The flock lock is not being released explicitly. _lock_release returns without action if flock is available, meaning the lock is held until the script exits. This serializes all file move operations, hurting performance, and is inconsistent with the mkdir fallback which releases the lock after name reservation. The lock should be released after name reservation to allow concurrent copy operations.

    flock -u 9

Comment thread README.md
Comment on lines +1 to +137
[[
<purpose>
Provide a formal, comprehensive specification for a two-script refactor that separates an interactive srch command builder from a reusable per-file mover, while preserving flat-destination moves, deterministic collision handling, and auditable logging.
</purpose>

<context>
<environment>
<execution_user>root (invoked via sudo by user linaro)</execution_user>
<script_locations>
<builder>/usr/local/bin/srch_flat_collect</builder>
<mover>/usr/local/libexec/srch_move_one</mover>
</script_locations>
<destination_root>/home/linaro/</destination_root>
<log_location>operation_log.txt inside the destination folder</log_location>
</environment>

<constraints>
<constraint>All matched files are moved into a single flat directory under /home/linaro.</constraint>
<constraint>srch -r must invoke the per-file mover script for each matched path.</constraint>
<constraint>Collision handling must use deterministic numeric suffixes before extensions.</constraint>
<constraint>Moves must use copy+delete semantics to support cross-filesystem operations.</constraint>
<constraint>Ownership must be linaro:linaro and permissions must allow read/write for owner, group, and others (a+rwX).</constraint>
<constraint>No archive or zip operation is permitted.</constraint>
<constraint>Interactive prompts must cover feasible srch flags and filters.</constraint>
</constraints>

<domain_notes>
<note>Three draft approaches were provided and must be merged into a single, reusable two-script design.</note>
<note>Reducing heredocs is required to improve versioning and reuse of the per-file mover.</note>
<note>Logging must capture original paths, normalized paths, renames, and errors.</note>
</domain_notes>
</context>

<variables>
<variable name="[[task_request]]" required="true">
<description>Refactor the srch-based collection workflow into a builder and a reusable mover with consistent logging and collision handling.</description>
</variable>
<variable name="[[builder_path]]" required="true">
<description>/usr/local/bin/srch_flat_collect</description>
</variable>
<variable name="[[mover_path]]" required="true">
<description>/usr/local/libexec/srch_move_one</description>
</variable>
<variable name="[[destination_folder]]" required="true">
<description>Single-level folder under /home/linaro used as the collection target.</description>
</variable>
</variables>

<instructions>
<instruction>1. Restate the goal: split the workflow into a builder script and a reusable mover while keeping flat moves, collision-safe naming, and audit logging.</instruction>

<instruction>2. Implement /usr/local/bin/srch_flat_collect as an interactive srch option builder that:
(a) collects srch start points;
(b) prompts for name matching (-N/-n/-i with optional negation);
(c) prompts for path matching (-a), exclusions (-e/-E/-Z), depth (-m), and filesystem boundary (-x);
(d) prompts for size and age filters (-s, -o/-O/-P, -y/-Y/-W);
(e) prompts for ownership filters (-u/-U/-g/-G);
(f) prompts for performance options (-t/-I/-q/-Q/-X) and progress/stats (-v/-S/-T/-C);
(g) always enforces -f for regular files.
</instruction>

<instruction>3. Implement /usr/local/libexec/srch_move_one as a standalone mover that:
(a) normalizes paths to absolute form;
(b) allocates collision-free names using numeric suffixes;
(c) performs copy+delete moves into the destination;
(d) logs every action to a .txt file in the destination.
</instruction>

<instruction>4. Ensure the builder exports DESTDIR, LOGFILE, LOCKFILE/LOCKDIR, and DRYRUN so the mover can operate consistently across runs.</instruction>

<instruction>5. Preserve auditability by rotating existing logs and recording the full srch invocation context.</instruction>
</instructions>

<output_format_specification>
<format>Plain text</format>
<requirements>
<requirement>Provide both scripts as versionable files rather than large heredocs embedded in one script.</requirement>
<requirement>Maintain formal, impersonal language and the structure of this template.</requirement>
<requirement>Include a complete example of each script.</requirement>
</requirements>
</output_format_specification>

<examples>
<example>
<input_data>
<task_request>Provide the builder and mover scripts as two separate files for reuse and testing.</task_request>
</input_data>
<output>
Builder: /usr/local/bin/srch_flat_collect
Mover: /usr/local/libexec/srch_move_one

The builder prompts for srch options, sets DESTDIR/LOGFILE/LOCKFILE/DRYRUN, and invokes:
srch <args> -r /usr/local/libexec/srch_move_one <roots>

The mover validates each match, resolves collisions with suffixes, copies to the destination,
deletes the source, and writes audit lines to operation_log.txt.
</output>
</example>
</examples>

<self_check>
<checklist>
<item>The builder and mover are separated into /usr/local/bin and /usr/local/libexec.</item>
<item>srch -r invokes the mover without embedding a large heredoc in the builder.</item>
<item>Collision handling uses deterministic numeric suffixes before extensions.</item>
<item>Moves use copy+delete semantics and are logged in operation_log.txt.</item>
<item>Destination ownership and permissions are set for linaro with a+rwX.</item>
</checklist>
</self_check>

<evaluation_notes>
<test_cases>
<case>Multiple identical basenames across different source paths.</case>
<case>Parallel srch -r runs with lock-guarded name allocation.</case>
<case>Files disappearing between traversal and move.</case>
<case>Paths containing spaces or special characters.</case>
</test_cases>
<success_definition>All matched files land in the flat destination with correct naming, permissions, and complete audit logs.</success_definition>
</evaluation_notes>

<documentation>
<usage>
<step>Install /usr/local/bin/srch_flat_collect and /usr/local/libexec/srch_move_one, then run the builder with sudo.</step>
<step>Follow prompts to build the srch command, confirm the operation, and review operation_log.txt.</step>
</usage>
<known_limitations>
<limitation>Large traversals can be I/O intensive; filters should be tuned before execution.</limitation>
<limitation>Locking uses flock when available and a mkdir fallback otherwise; behavior may vary on some filesystems.</limitation>
</known_limitations>
</documentation>

<observations>
<item>Drafts differed on whether to allow existing destinations; this version prompts for confirmation if the destination exists.</item>
<item>Drafts used both three- and four-digit suffixes; this version standardizes on three-digit suffixes for collisions.</item>
<item>Drafts varied between embedded mover heredocs and external helpers; this version externalizes the mover for reuse.</item>
</observations>
]]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The document uses a custom format with [[...]] and XML-like tags. This format is not standard Markdown and will not render correctly in most Markdown viewers (like on GitHub). Consider using standard Markdown syntax (e.g., headers, lists, bold text) to improve readability and maintainability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant