diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index cdf6dfe8136..a6eba3dbe86 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -290,7 +290,16 @@ fn check_repo_state( .filter(|file| { let relative = file.strip_prefix(workdir).unwrap(); if let Ok(status) = repo.status_file(relative) { - status != git2::Status::CURRENT + if status == git2::Status::CURRENT { + false + } else { + if relative.to_str().unwrap_or("") == "Cargo.lock" { + // It is OK to include this file even if it is ignored. + status != git2::Status::IGNORED + } else { + true + } + } } else { submodule_dirty(file) } diff --git a/tests/testsuite/publish_lockfile.rs b/tests/testsuite/publish_lockfile.rs index 3daef142b27..2e49f4e0c76 100644 --- a/tests/testsuite/publish_lockfile.rs +++ b/tests/testsuite/publish_lockfile.rs @@ -396,3 +396,58 @@ dependencies = [ ) .run(); } + +#[cargo_test] +fn ignore_lockfile() { + // With an explicit `include` list, but Cargo.lock in .gitignore, don't + // complain about `Cargo.lock` being ignored. Note that it is still + // included in the packaged regardless. + let (p, _r) = git::new_repo("foo", |p| { + p.file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + + include = [ + "src/main.rs" + ] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file(".gitignore", "Cargo.lock") + }); + p.cargo("package -l") + .with_stdout( + "\ +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +src/main.rs +", + ) + .run(); + p.cargo("generate-lockfile").run(); + p.cargo("package -v") + .with_stderr( + "\ +[PACKAGING] foo v0.0.1 ([..]) +[ARCHIVING] Cargo.toml +[ARCHIVING] src/main.rs +[ARCHIVING] .cargo_vcs_info.json +[ARCHIVING] Cargo.lock +[VERIFYING] foo v0.0.1 ([..]) +[COMPILING] foo v0.0.1 ([..]) +[RUNNING] `rustc --crate-name foo src/main.rs [..] +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +", + ) + .run(); +}