Skip to content

fix: false-positive uncommitted changes for gitignored directories#16864

Closed
unclepomedev wants to merge 2 commits intorust-lang:masterfrom
unclepomedev:feat/#16547
Closed

fix: false-positive uncommitted changes for gitignored directories#16864
unclepomedev wants to merge 2 commits intorust-lang:masterfrom
unclepomedev:feat/#16547

Conversation

@unclepomedev
Copy link
Copy Markdown

@unclepomedev unclepomedev commented Apr 9, 2026

Fixes #16547
(as patch before gix-dir)

What does this PR try to resolve?

Fixes false-positive 'uncommitted changes' errors during cargo publish caused by .gitignored directories (e.g., .venv) in workspace setups.

How to test and review this PR?

  • Copy of the test described in the issue, with the TODO and a typo corrected.
    • (edited) also added the include = ... line that triggers this bug.
  • A false positive test for LICENSE files under .venv that are gitignored (I encountered and typical in Python+Rust env)

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 9, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 9, 2026

r? @epage

rustbot has assigned @epage.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: @ehuss, @epage, @weihanglo
  • @ehuss, @epage, @weihanglo expanded to ehuss, epage, weihanglo
  • Random selection from ehuss, epage, weihanglo

@epage
Copy link
Copy Markdown
Contributor

epage commented Apr 9, 2026

FYI our contrib process encourages having tests in a commit before the fix, with every commit passing tests, see https://doc.crates.io/contrib/process/working-on-cargo.html#submitting-a-pull-request. I've written up more on this at https://epage.github.io/dev/pr-style/#c-test

@epage
Copy link
Copy Markdown
Contributor

epage commented Apr 9, 2026

Note that #16547 was never labeled S-accepted which our contrib guide says is a pre-req for opening issues.

@unclepomedev
Copy link
Copy Markdown
Author

unclepomedev commented Apr 9, 2026

@epage
My apologies for missing the S-accepted requirement.
I submitted this PR because it seemed like there hadn't been discussion for a while. However, if sufficient design discussion is needed, I may need to close this PR. Please let me know how you'd like to proceed.

@unclepomedev
Copy link
Copy Markdown
Author

Also, apologies for overlooking your earlier comment about the contribution process.

This adds tests to reproduce the issue where `cargo publish` falsely
flags `.gitignored` directories (like `.venv` or nested repositories)
as uncommitted changes when the `include` option is used.

The tests currently expect the erroneous behavior to establish a
baseline before applying the actual fix.
When the `include` field is specified in `Cargo.toml`, Cargo's file listing logic previously ignored `.gitignore` rules for directories and traversed into nested git repositories. This caused `cargo package` to report uncommitted changes for files that were not intended to be part of the package.

This change ensures that:
- `.gitignore` is respected for directory traversal even when the `include` option is used.
- Nested git repositories are explicitly skipped during file discovery.

Fixes rust-lang#16547
documentation = "foo"
homepage = "foo"
repository = "foo"
include = ["src/**/*", "tests/**/*"]
Copy link
Copy Markdown
Author

@unclepomedev unclepomedev Apr 9, 2026

Choose a reason for hiding this comment

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

View changes since the review

Simply copying the test from the issue would result in false-negative (the test would pass even without modifying the code), so added an include statement, which is the trigger for the error.
(Without include, Cargo uses the standard ignore logic and the bug doesn't trigger.)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Doesn't the reproduction is still unclear? Should we discuss in the issue first to be aligned with the issue reporter? The two tests here might be two different issues.

@unclepomedev
Copy link
Copy Markdown
Author

Updated the PR to follow the C-TEST guidelines. The changes are split into:

  1. Adding tests that reproduce errors.
  2. The fix and updating the tests to pass.

As commented, I found a flaw in the original reproduction.
Also, since the error output includes Git hashes, I ran:
SNAPSHOTS=overwrite cargo test -p cargo --test testsuite -- package::gitignored_nested_repo_not_treated_as_uncommitted --exact

Copy link
Copy Markdown
Member

@weihanglo weihanglo left a comment

Choose a reason for hiding this comment

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

The two reproducible test seem different than each others. And the fix include also ignoring .git and all files under a gitignore'd directory when package.include is specified.

These cases and behavior changes seem to be slightly different and should be discussed and clarified separately in the original issue or a new issue for new bug report.

View changes since this review

// Create a nested git repository in tests/fixtures/ that is gitignored
// This simulates test fixtures that are git repositories (like gix-dir test fixtures)
let repo_base = main_repo.root().join(
"tests/fixtures/generated-do-not-edit/many/613585535-unix/slash-in-root-and-negated/",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We probably want toavoid creating such a long path. It might exceed path length limit in some operating systems.

documentation = "foo"
homepage = "foo"
repository = "foo"
include = ["src/**/*", "tests/**/*"]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Doesn't the reproduction is still unclear? Should we discuss in the issue first to be aligned with the issue reporter? The two tests here might be two different issues.

Comment thread src/cargo/sources/path.rs
return false;
}

// Skip nested git repositories (see rust-lang/cargo#16547).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is also different than ust-lang/cargo#16547 that unclear to me why we want to ignore when not using include (I knew you added an include).

Comment thread src/cargo/sources/path.rs
Comment on lines +628 to +638
if let Some(ref gitignore) = gitignore_for_include {
if gitignore
.matched_path_or_any_parents(relative_path, is_dir)
.is_ignore()
&& !ignore_include
.matched_path_or_any_parents(relative_path, is_dir)
.is_ignore()
{
return false;
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This a wrong fix, or at least a significant behavior-breaking change that we should consider more cases. For example, if a directory is gitignore'd but user request to package.include a specific file inside it, after this change the file won't be included.

@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 10, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 10, 2026

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@rustbot rustbot added the S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. label Apr 10, 2026
@unclepomedev
Copy link
Copy Markdown
Author

Thank you for the thorough review.
I'd like to take the following steps before marking this ready again:

  1. Check with the original issue reporter to clarify whether my reproduction covers the same case or a separate one.
  2. If they turn out to be different issues, I'll open a new issue for the bug I encountered, with a proper reproduction.
  3. I'll also re-examine the fix to make sure it doesn't break the case where include is intended to override .gitignore.

@unclepomedev
Copy link
Copy Markdown
Author

@weihanglo

I've confirmed with the issue reporter that we're facing the same issue: a false-positive uncommitted error occurs during cargo publish when package.include is specified and the project contains a nested git repository.
I'd like to open a single reproduction issue covering both cases:

  • False positives for files inside a .git directory
  • False positives for .gitignored files

Would that be okay, or would you prefer them as separate issues?

@weihanglo
Copy link
Copy Markdown
Member

Thanks for the investigation!

They may have different compatibility guarantee, so separate issues sounds better to manage the discussion.

@unclepomedev
Copy link
Copy Markdown
Author

unclepomedev commented Apr 11, 2026

Thanks!

Closing in favor of #16872 and #16873 to split the issues as suggested.

@unclepomedev unclepomedev deleted the feat/#16547 branch April 11, 2026 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cargo publish produces "X files in the working directory contain changes that were not yet committed into git" for .gitignored files

4 participants