Skip to content

Borrow build path when emitting manifest#90

Merged
leynos merged 3 commits intomainfrom
codex/refactor-handle_build-to-use-cowpath
Aug 11, 2025
Merged

Borrow build path when emitting manifest#90
leynos merged 3 commits intomainfrom
codex/refactor-handle_build-to-use-cowpath

Conversation

@leynos
Copy link
Owner

@leynos leynos commented Aug 8, 2025

Summary

  • avoid allocating when --emit is used by borrowing the emitted path
  • pass borrowed build path to run_ninja

Testing

  • make fmt
  • make check-fmt
  • make lint
  • make test

closes #84


https://chatgpt.com/codex/tasks/task_e_6896813806388322b8a8b5ffd8794566

Summary by Sourcery

Use Cow in handle_build to borrow emitted build paths and avoid unnecessary allocations when using the --emit option, and update the run_ninja invocation accordingly.

Enhancements:

  • Borrow the emitted build path with Cow instead of cloning when --emit is provided
  • Use Cow to represent temporary or emitted build paths and pass them to run_ninja via as_ref()

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Aug 8, 2025

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

This PR refactors handle_build to use a Cow for the build path, avoiding a clone when an emitted path is provided and passing the borrowed path directly to run_ninja.

File-Level Changes

Change Details Files
Use Cow for build_path instead of PathBuf to avoid allocations
  • Change build_path type to Cow
  • On emit branch, use Cow::Borrowed(path.as_path())
  • On temp branch, use Cow::Owned(tmp.path().to_path_buf())
src/runner.rs
Adjust run_ninja call to accept borrowed path
  • Pass build_path.as_ref() instead of &build_path
src/runner.rs
Update comment to reflect borrowing behavior
  • Modify comment before build_path binding to mention borrowing emitted path
src/runner.rs

Assessment against linked issues

Issue Objective Addressed Explanation
#84 Change handle_build to bind build_path as Cow.
#84 Borrow the path in the Some(args.emit) branch; own the temp-file path in the None branch.
#84 Update the run_ninja call site to pass build_path.as_ref().

Possibly linked issues


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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 8, 2025

Summary by CodeRabbit

  • New Features
    • No user-facing changes.
  • Refactor
    • Optimised the build workflow to reduce allocations and improve handling of temporary files, ensuring they persist for the duration of the build.
    • Minor inline documentation updates to clarify behaviour.
  • Stability
    • Improved reliability of the build invocation by tightening file lifecycle management.
  • Compatibility
    • No changes to public interfaces or configuration.

Walkthrough

Refactor handle_build in src/runner.rs to use std::borrow::Cow<Path> for build_path, borrow the emitted path when present and own the temporary-file path otherwise; pass build_path.as_ref() to run_ninja and ensure the temporary file lives until after run_ninja returns. No public API changes.

Changes

Cohort / File(s) Change Summary
Path ownership refactor in build handling
src/runner.rs
Import std::borrow::Cow. Replace tuple-based (PathBuf, Option<NamedTempFile>) handling with Cow<Path> + Option<NamedTempFile>; write Ninja to emitted path when provided (borrowed), otherwise create temp file (owned); pass build_path.as_ref() to run_ninja; explicitly drop temp file after run_ninja.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant handle_build
    participant run_ninja

    Caller->>handle_build: invoke handle_build(args)
    alt args.emit is Some(path)
        handle_build->>handle_build: build_path = Cow::Borrowed(path)
        handle_build->>handle_build: write Ninja content to emitted path
    else args.emit is None
        handle_build->>handle_build: tmp_file = create NamedTempFile
        handle_build->>handle_build: build_path = Cow::Borrowed(tmp_file.path())
        handle_build->>tmp_file: keep ownership to extend lifetime
    end
    handle_build->>run_ninja: run_ninja(build_path.as_ref(), ...)
    run_ninja->>handle_build: return result
    handle_build->>handle_build: drop(tmp_file) // ensure temp file removed after run
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Assessment against linked issues

Objective Addressed Explanation
Avoid clone of emitted path in Some(args.emit) branch (#84)
Use Cow<Path> for build_path in handle_build (#84)
Borrow emitted path, own temp path, update run_ninja call, add necessary import (#84)
Do not change run_ninja’s signature or behaviour (#84)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes found.

Possibly related PRs

Poem

A borrowed path, a tiny file kept near,
Cow stands ready — no needless copy here.
Ninja runs tidy, lifetimes aligned,
Temp file dropped once the job's defined.
Rust smiles softly, allocation spared.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/refactor-handle_build-to-use-cowpath

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @leynos - I've reviewed your changes and found some issues that need to be addressed.


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.

Copy link
Contributor

@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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fb6c684 and 57c62d2.

📒 Files selected for processing (1)
  • src/runner.rs (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.rs: Clippy warnings MUST be disallowed.
Fix any warnings emitted during tests in the code itself rather than silencing them.
Where a function is too long, extract meaningfully named helper functions adhering to separation of concerns and CQRS.
Where a function has too many parameters, group related parameters in meaningfully named structs.
Where a function is returning a large error consider using Arc to reduce the amount of data returned.
Write unit and behavioural tests for new functionality. Run both before and after making any change.
Every module must begin with a module level (//!) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Avoid unsafe code unless absolutely necessary and document any usage clearly.
Place function attributes after doc comments.
Do not use return in single-line functions.
Use predicate functions for conditional criteria with more than two branches.
Lints must not be silenced except as a last resort.
Lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow.
Prefer .expect() over .unwrap().
Use concat!() to combine long string literals rather than escaping newlines with a backslash.
Prefer semantic error enums: Derive std::error::Error (via the thiserror crate) for any condition the caller might inspect, retry, or map to an HTTP status.
Use an opaque error only at the app boundary: Use eyre::Report for human-readable logs; these should not be exposed in public APIs.
Never export the opaque type from a library: Convert to domain enums at API boundaries, and to eyre only in the main main() entrypoint or top-level async task.

Files:

  • src/runner.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • src/runner.rs
🔍 MCP Research (1 server)

Deepwiki:

  • The run_ninja function in src/runner.rs is updated to accept a &Path reference for the build path instead of a &PathBuf, reflecting the change to use Cow<Path> in handle_build. This aligns with the ownership semantics and avoids unnecessary cloning. (Related PR #46)

  • The netsuke project enforces strict code quality standards, including no cloning of paths when unnecessary, and uses comprehensive testing including unit tests, linting, formatting checks, and behavioral tests to validate changes like the one in handle_build. (Code Quality Standards, Testing Framework)

  • There are no reported bugs or incidents specifically related to the handle_build function or the use of Cow<Path> in src/runner.rs. The change is a micro-optimization flagged during code review and is intended to improve efficiency without altering behavior. (Issue #84 discussion)

⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-test

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Greptile Summary

This PR refactors the handle_build function in src/runner.rs to use Cow<Path> (Copy on Write) for more efficient memory management when handling build file paths. The change eliminates unnecessary heap allocations by borrowing the emitted path when the --emit option is provided, instead of cloning it.

The refactoring addresses a micro-optimization opportunity identified in issue #84. When users specify an output path via --emit, the original code was unnecessarily cloning the PathBuf, even though the path already exists in the args structure and could be borrowed instead. The new implementation uses Cow<Path> to express mixed ownership semantics - borrowing when the path is provided externally (emit case) and borrowing from owned temporary files when needed.

The change maintains the same external behavior while improving memory efficiency. The code now separates the variable declarations to manage lifetimes explicitly, ensuring the temporary file remains alive for the duration of the Ninja invocation. This fits well with the codebase's focus on performance and efficient resource management, as evidenced by the comprehensive testing infrastructure and build optimization goals of the Netsuke build system.

Important Files Changed

Files Modified
Filename Score Overview
src/runner.rs 4/5 Refactored handle_build function to use Cow for borrowing build paths instead of cloning

Confidence score: 4/5

  • This PR is safe to merge with minimal risk as it's a focused optimization that maintains existing behavior
  • Score reflects a well-executed micro-optimization with proper lifetime management and no behavioral changes
  • No files require special attention as the change is isolated and straightforward

1 file reviewed, no comments

Edit Code Review Bot Settings | Greptile

Copy link
Contributor

@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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 57c62d2 and cef1c15.

📒 Files selected for processing (1)
  • src/runner.rs (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.rs: Clippy warnings MUST be disallowed.
Fix any warnings emitted during tests in the code itself rather than silencing them.
Where a function is too long, extract meaningfully named helper functions adhering to separation of concerns and CQRS.
Where a function has too many parameters, group related parameters in meaningfully named structs.
Where a function is returning a large error consider using Arc to reduce the amount of data returned.
Write unit and behavioural tests for new functionality. Run both before and after making any change.
Every module must begin with a module level (//!) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Avoid unsafe code unless absolutely necessary and document any usage clearly.
Place function attributes after doc comments.
Do not use return in single-line functions.
Use predicate functions for conditional criteria with more than two branches.
Lints must not be silenced except as a last resort.
Lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow.
Prefer .expect() over .unwrap().
Use concat!() to combine long string literals rather than escaping newlines with a backslash.
Prefer semantic error enums: Derive std::error::Error (via the thiserror crate) for any condition the caller might inspect, retry, or map to an HTTP status.
Use an opaque error only at the app boundary: Use eyre::Report for human-readable logs; these should not be exposed in public APIs.
Never export the opaque type from a library: Convert to domain enums at API boundaries, and to eyre only in the main main() entrypoint or top-level async task.

Files:

  • src/runner.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • src/runner.rs
🔍 MCP Research (1 server)

Deepwiki:

  • The handle_build function manages temporary Ninja files using NamedTempFile and ensures proper lifetime management by explicit drop after Ninja invocation, preventing premature deletion. (PR summary)

  • The handle_build function's update to use Cow<Path> and borrow the emitted path avoids cloning, which reduces allocations and improves ownership clarity in the build execution logic. (PR summary, Issue #84)

  • The run_ninja function is called with a &Path reference obtained from build_path.as_ref(), reflecting the change to use Cow<Path> for the build path. The temporary file is explicitly dropped after Ninja invocation to ensure its lifetime covers the build process. (PR summary)

⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-test
🔇 Additional comments (4)
src/runner.rs (4)

11-11: Add Cow import for mixed ownership semantics — LGTM

Import Cow to support borrowed/owned path semantics. Matches the PR objective and keeps the API surface unchanged.


118-135: Borrow emitted path and keep temp alive — correct, allocation-free, borrow-checker-safe

Borrow the emitted path (Cow::Borrowed) and keep NamedTempFile alive while borrowing its path. This removes the to_path_buf() clone and aligns with the optimisation and Deepwiki notes.


138-139: Pass borrowed path to run_ninja and drop temp after invocation — LGTM

Pass build_path.as_ref() to run_ninja and explicitly drop the temp file after the build. This satisfies the lifetime requirement noted in Deepwiki.


118-135: Resolve build-path clone concerns

No stray to_path_buf() calls remain in the handle_build flow – build_path is always a Cow::Borrowed. All run_ninja invocations receive a &Path. The only remaining to_path_buf() is at src/runner.rs:333 as a fallback for canonicalize(), which is required to supply a PathBuf on error. No action required.

@leynos leynos merged commit 5f81c1c into main Aug 11, 2025
3 of 4 checks passed
@leynos leynos deleted the codex/refactor-handle_build-to-use-cowpath branch August 11, 2025 11:31
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

1 file reviewed, no comments

Edit Code Review Bot Settings | Greptile

Copy link
Contributor

@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: 5

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cef1c15 and 05f97ca.

📒 Files selected for processing (1)
  • src/runner.rs (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.rs: Comment why, not what. Explain assumptions, edge cases, trade-offs, or complexity. Don't echo the obvious.
Use functions and composition. Avoid repetition by extracting reusable logic. Prefer generators or comprehensions, and declarative code to imperative repetition when readable.
Small, meaningful functions. Functions must be small, clear in purpose, single responsibility, and obey command/query segregation.
Name things precisely. Use clear, descriptive variable and function names. For booleans, prefer names with is, has, or should.
Every module must begin with a module level (//! ) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Place function attributes after doc comments.
Do not use return in single-line functions.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Prefer .expect() over .unwrap().
Use concat!() to combine long string literals rather than escaping newlines with a backslash.
Prefer single line versions of functions where appropriate.
Clippy warnings MUST be disallowed.
Lints must not be silenced except as a last resort.
Lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow.
Keep file size manageable. No single code file may be longer than 400 lines. Long switch statements or dispatch tables should be broken up by feature and constituents colocated with targets. Large blocks of test data should be moved to external data files.
Illustrate with clear examples. Function documentation must include clear examples demonstrating the usage and outcome of the function. Test documentation should omit examples where the example serves only to reiterate the test logic.
Prefer semantic error enums. Derive std::error::Error (via the thiserror crate) for any condition the caller might inspect, retry, or map to an HTTP status.
...

Files:

  • src/runner.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Where code is only used by specific features, it must be conditionally compiled or a conditional expectation for unused_code applied.

  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • src/runner.rs
🔍 MCP Research (1 server)

Deepwiki:

⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-test

use crate::{ir::BuildGraph, manifest, ninja_gen};
use anyhow::{Context, Result};
use serde_json;
use std::borrow::Cow;
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Cow import no longer needed if you simplify to &Path

Drop this import once you replace Cow<Path> with &Path as suggested below.

- use std::borrow::Cow;

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/runner.rs around line 11, the use std::borrow::Cow import is unnecessary
once you replace Cow<Path> with &Path; update function signatures and local
variables that currently use Cow<Path> to accept &Path instead, adjust any call
sites to pass a reference (and replace Cow-specific methods with &Path
equivalents like as_ref()/to_path_buf() or direct &), then remove the `use
std::borrow::Cow;` line; ensure lifetimes and mutable/ownership expectations are
satisfied by borrowing or cloning where required.

Comment on lines +118 to +120
// Normalize the build file path and keep the temporary file alive for the
// duration of the Ninja invocation. Borrow the emitted path when provided
// to avoid unnecessary allocation.
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Correct the comment: path canonicalization happens in run_ninja, not here

Avoid misleading readers about where normalisation occurs; keep the focus on lifetimes and borrowing.

-    // Normalize the build file path and keep the temporary file alive for the
-    // duration of the Ninja invocation. Borrow the emitted path when provided
-    // to avoid unnecessary allocation.
+    // Keep the temporary build file alive for the duration of the Ninja
+    // invocation. Borrow the emitted path when provided to avoid unnecessary
+    // allocation; run_ninja canonicalizes the path.
📝 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
// Normalize the build file path and keep the temporary file alive for the
// duration of the Ninja invocation. Borrow the emitted path when provided
// to avoid unnecessary allocation.
// Keep the temporary build file alive for the duration of the Ninja
// invocation. Borrow the emitted path when provided to avoid unnecessary
// allocation; run_ninja canonicalizes the path.
🤖 Prompt for AI Agents
In src/runner.rs around lines 118 to 120, the comment incorrectly states that
path canonicalization/normalization happens here; update the comment to remove
that claim and instead describe only keeping the temporary file alive for the
duration of the Ninja invocation and borrowing the emitted path to avoid
allocation, focusing on lifetimes/borrowing rather than normalization location.

Comment on lines +121 to +135
let build_path: Cow<Path>;
let mut tmp_file: Option<NamedTempFile> = None;
if let Some(path) = &args.emit {
write_ninja_file(path, &ninja)?;
(path.clone(), None)
build_path = Cow::Borrowed(path.as_path());
} else {
let tmp = create_temp_ninja_file(&ninja)?;
(tmp.path().to_path_buf(), Some(tmp))
};
tmp_file = Some(tmp);
build_path = Cow::Borrowed(
tmp_file
.as_ref()
.expect("temporary Ninja file should exist")
.path(),
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Simplify: replace Cow<Path> with &Path; the owned variant is never used

Both branches produce borrowed paths. Remove Cow to reduce indirection and imports while preserving lifetimes.

-    let build_path: Cow<Path>;
+    let build_path: &Path;
     let mut tmp_file: Option<NamedTempFile> = None;
     if let Some(path) = &args.emit {
         write_ninja_file(path, &ninja)?;
-        build_path = Cow::Borrowed(path.as_path());
+        build_path = path.as_path();
     } else {
         let tmp = create_temp_ninja_file(&ninja)?;
         tmp_file = Some(tmp);
-        build_path = Cow::Borrowed(
-            tmp_file
-                .as_ref()
-                .expect("temporary Ninja file should exist")
-                .path(),
-        );
+        build_path = tmp_file
+            .as_ref()
+            .expect("temporary Ninja file should exist")
+            .path();
     }
📝 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
let build_path: Cow<Path>;
let mut tmp_file: Option<NamedTempFile> = None;
if let Some(path) = &args.emit {
write_ninja_file(path, &ninja)?;
(path.clone(), None)
build_path = Cow::Borrowed(path.as_path());
} else {
let tmp = create_temp_ninja_file(&ninja)?;
(tmp.path().to_path_buf(), Some(tmp))
};
tmp_file = Some(tmp);
build_path = Cow::Borrowed(
tmp_file
.as_ref()
.expect("temporary Ninja file should exist")
.path(),
);
}
let build_path: &Path;
let mut tmp_file: Option<NamedTempFile> = None;
if let Some(path) = &args.emit {
write_ninja_file(path, &ninja)?;
build_path = path.as_path();
} else {
let tmp = create_temp_ninja_file(&ninja)?;
tmp_file = Some(tmp);
build_path = tmp_file
.as_ref()
.expect("temporary Ninja file should exist")
.path();
}
🤖 Prompt for AI Agents
In src/runner.rs around lines 121 to 135, replace the Cow<Path> usage with a
borrowed &Path since neither branch ever produces an owned Path: change the
declaration to let build_path: &Path; keep tmp_file: Option<NamedTempFile>
declared before so its lifetime spans the borrow; in the if branch assign
build_path = path.as_path(); in the else branch assign build_path =
tmp_file.as_ref().expect("temporary Ninja file should exist").path(); and remove
the now-unused Cow import.


let program = resolve_ninja_program();
run_ninja(program.as_path(), cli, &build_path, &targets)?;
run_ninja(program.as_path(), cli, build_path.as_ref(), &targets)?;
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Pass build_path directly after the simplification

If you adopt the &Path refactor above, remove the .as_ref() call here.

-    run_ninja(program.as_path(), cli, build_path.as_ref(), &targets)?;
+    run_ninja(program.as_path(), cli, build_path, &targets)?;
📝 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
run_ninja(program.as_path(), cli, build_path.as_ref(), &targets)?;
run_ninja(program.as_path(), cli, build_path, &targets)?;
🤖 Prompt for AI Agents
In src/runner.rs around line 138, the call currently uses build_path.as_ref();
remove the unnecessary .as_ref() and pass build_path directly (or as a borrowed
reference if needed, e.g. &build_path) so the argument matches the simplified
&Path type expected by run_ninja.

let program = resolve_ninja_program();
run_ninja(program.as_path(), cli, &build_path, &targets)?;
run_ninja(program.as_path(), cli, build_path.as_ref(), &targets)?;
drop(tmp_file);
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Remove redundant explicit drop

tmp_file drops at end-of-scope immediately after this line anyway. Avoid noise.

-    drop(tmp_file);
📝 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
drop(tmp_file);
🤖 Prompt for AI Agents
In src/runner.rs around line 139, the explicit call drop(tmp_file); is redundant
because tmp_file will be dropped automatically at the end of the scope; remove
that line to avoid noise and rely on Rust's RAII for cleanup (ensure no code
depends on immediate drop timing before deleting).

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.

runner: avoid clone in handle_build by using Cow<Path> for emitted path

1 participant