Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include vcs_info even if workspace is dirty #13960

Merged
merged 5 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 20 additions & 14 deletions src/cargo/ops/cargo_package.rs
weihanglo marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ struct VcsInfo {
#[derive(Serialize)]
struct GitVcsInfo {
sha1: String,
/// Indicate whether or not the Git worktree is dirty.
#[serde(skip_serializing_if = "std::ops::Not::not")]
dirty: bool,
}

/// Packages a single package in a workspace, returning the resulting tar file.
Expand Down Expand Up @@ -235,14 +238,8 @@ fn prepare_archive(
}
let src_files = src.list_files(pkg)?;

// Check (git) repository state, getting the current commit hash if not
// dirty.
let vcs_info = if !opts.allow_dirty {
// This will error if a dirty repo is found.
check_repo_state(pkg, &src_files, gctx)?
} else {
None
};
// Check (git) repository state, getting the current commit hash.
let vcs_info = check_repo_state(pkg, &src_files, gctx, &opts)?;

build_ar_list(ws, pkg, src_files, vcs_info)
}
Expand Down Expand Up @@ -559,13 +556,15 @@ fn check_metadata(pkg: &Package, gctx: &GlobalContext) -> CargoResult<()> {
}

/// Checks if the package source is in a *git* DVCS repository. If *git*, and
/// the source is *dirty* (e.g., has uncommitted changes) then `bail!` with an
/// informative message. Otherwise return the sha1 hash of the current *HEAD*
/// commit, or `None` if no repo is found.
/// the source is *dirty* (e.g., has uncommitted changes), and `--allow-dirty`
/// has not been passed, then `bail!` with an informative message. Otherwise
/// return the sha1 hash of the current *HEAD* commit, or `None` if no repo is
/// found.
fn check_repo_state(
p: &Package,
src_files: &[PathBuf],
gctx: &GlobalContext,
opts: &PackageOpts<'_>,
) -> CargoResult<Option<VcsInfo>> {
if let Ok(repo) = git2::Repository::discover(p.root()) {
if let Some(workdir) = repo.workdir() {
Expand All @@ -585,7 +584,7 @@ fn check_repo_state(
.unwrap_or("")
.replace("\\", "/");
return Ok(Some(VcsInfo {
git: git(p, src_files, &repo)?,
git: git(p, src_files, &repo, &opts)?,
path_in_vcs,
}));
}
Expand All @@ -608,7 +607,12 @@ fn check_repo_state(
// directory is dirty or not, thus we have to assume that it's clean.
return Ok(None);

fn git(p: &Package, src_files: &[PathBuf], repo: &git2::Repository) -> CargoResult<GitVcsInfo> {
fn git(
p: &Package,
src_files: &[PathBuf],
repo: &git2::Repository,
opts: &PackageOpts<'_>,
) -> CargoResult<GitVcsInfo> {
// This is a collection of any dirty or untracked files. This covers:
// - new/modified/deleted/renamed/type change (index or worktree)
// - untracked files (which are "new" worktree files)
Expand All @@ -633,10 +637,12 @@ fn check_repo_state(
.to_string()
})
.collect();
if dirty_src_files.is_empty() {
let dirty = !dirty_src_files.is_empty();
if !dirty || opts.allow_dirty {
let rev_obj = repo.revparse_single("HEAD")?;
Ok(GitVcsInfo {
sha1: rev_obj.id().to_string(),
dirty,
})
} else {
anyhow::bail!(
Expand Down
10 changes: 7 additions & 3 deletions src/doc/man/cargo-package.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ steps:
executable binary or example target. {{man "cargo-install" 1}} will use the
packaged lock file if the `--locked` flag is used.
- A `.cargo_vcs_info.json` file is included that contains information
about the current VCS checkout hash if available (not included with
`--allow-dirty`).
about the current VCS checkout hash if available, as well as a flag if the
worktree is dirty.
3. Extract the `.crate` file and build it to verify it can build.
- This will rebuild your package from scratch to ensure that it can be
built from a pristine state. The `--no-verify` flag can be used to skip
Expand All @@ -52,12 +52,16 @@ Will generate a `.cargo_vcs_info.json` in the following format
```javascript
{
"git": {
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302"
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302",
"dirty": true
},
"path_in_vcs": ""
}
```

`dirty` indicates that the Git worktree was dirty when the package
was built.

`path_in_vcs` will be set to a repo-relative path for packages
in subdirectories of the version control repository.

Expand Down
10 changes: 7 additions & 3 deletions src/doc/man/generated_txt/cargo-package.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ DESCRIPTION
packaged lock file if the --locked flag is used.

o A .cargo_vcs_info.json file is included that contains information
about the current VCS checkout hash if available (not included
with --allow-dirty).
about the current VCS checkout hash if available, as well as a
flag if the worktree is dirty.

3. Extract the .crate file and build it to verify it can build.
o This will rebuild your package from scratch to ensure that it can
Expand All @@ -51,11 +51,15 @@ DESCRIPTION

{
"git": {
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302"
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302",
"dirty": true
},
"path_in_vcs": ""
}

dirty indicates that the Git worktree was dirty when the package was
built.

path_in_vcs will be set to a repo-relative path for packages in
subdirectories of the version control repository.

Expand Down
10 changes: 7 additions & 3 deletions src/doc/src/commands/cargo-package.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ steps:
executable binary or example target. [cargo-install(1)](cargo-install.html) will use the
packaged lock file if the `--locked` flag is used.
- A `.cargo_vcs_info.json` file is included that contains information
about the current VCS checkout hash if available (not included with
`--allow-dirty`).
about the current VCS checkout hash if available, as well as a flag if the
worktree is dirty.
3. Extract the `.crate` file and build it to verify it can build.
- This will rebuild your package from scratch to ensure that it can be
built from a pristine state. The `--no-verify` flag can be used to skip
Expand All @@ -47,12 +47,16 @@ Will generate a `.cargo_vcs_info.json` in the following format
```javascript
{
"git": {
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302"
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302",
"dirty": true
},
"path_in_vcs": ""
}
```

`dirty` indicates that the Git worktree was dirty when the package
was built.

`path_in_vcs` will be set to a repo-relative path for packages
in subdirectories of the version control repository.

Expand Down
10 changes: 7 additions & 3 deletions src/etc/man/cargo-package.1
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ packaged lock file if the \fB\-\-locked\fR flag is used.
.sp
.RS 4
\h'-04'\(bu\h'+02'A \fB\&.cargo_vcs_info.json\fR file is included that contains information
about the current VCS checkout hash if available (not included with
\fB\-\-allow\-dirty\fR).
about the current VCS checkout hash if available, as well as a flag if the
worktree is dirty.
.RE
.RE
.sp
Expand Down Expand Up @@ -74,13 +74,17 @@ Will generate a \fB\&.cargo_vcs_info.json\fR in the following format
.nf
{
"git": {
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302"
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302",
"dirty": true
},
"path_in_vcs": ""
}
.fi
.RE
.sp
\fBdirty\fR indicates that the Git worktree was dirty when the package
was built.
.sp
\fBpath_in_vcs\fR will be set to a repo\-relative path for packages
in subdirectories of the version control repository.
.sp
Expand Down
1 change: 1 addition & 0 deletions tests/testsuite/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2610,6 +2610,7 @@ fn include_overrides_gitignore() {
p.cargo("package --list --allow-dirty")
.with_stdout(
"\
.cargo_vcs_info.json
Cargo.toml
Cargo.toml.orig
ignored.txt
Expand Down
112 changes: 112 additions & 0 deletions tests/testsuite/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,7 @@ fn no_duplicates_from_modified_tracked_files() {
p.cargo("package --list --allow-dirty")
.with_stdout(
"\
.cargo_vcs_info.json
Cargo.lock
Cargo.toml
Cargo.toml.orig
Expand Down Expand Up @@ -1011,6 +1012,7 @@ src/main.rs
.with_stderr("")
.with_stdout(
"\
.cargo_vcs_info.json
.gitignore
Cargo.lock
Cargo.toml
Expand Down Expand Up @@ -1171,6 +1173,111 @@ src/lib.rs
.run();
}

#[cargo_test]
fn issue_13695_allow_dirty_vcs_info() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
edition = "2015"
description = "foo"
license = "foo"
documentation = "foo"
"#,
)
.file("src/lib.rs", "")
.build();

let repo = git::init(&p.root());
// Initial commit, with no files added.
git::commit(&repo);

// Allowing a dirty worktree results in the vcs file still being included.
p.cargo("package --allow-dirty").run();

let f = File::open(&p.root().join("target/package/foo-0.1.0.crate")).unwrap();
validate_crate_contents(
f,
"foo-0.1.0.crate",
&[
".cargo_vcs_info.json",
"Cargo.toml",
"Cargo.toml.orig",
"src/lib.rs",
],
&[(
".cargo_vcs_info.json",
r#"{
"git": {
"sha1": "[..]",
"dirty": true
},
"path_in_vcs": ""
}"#,
)],
);

// Listing provides a consistent result.
p.cargo("package --list --allow-dirty")
.with_stderr("")
.with_stdout(
"\
.cargo_vcs_info.json
Cargo.toml
Cargo.toml.orig
src/lib.rs
",
)
.run();
}

#[cargo_test]
fn issue_13695_allowing_dirty_vcs_info_but_clean() {
let p = project().build();
let _ = git::repo(&paths::root().join("foo"))
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
edition = "2015"
description = "foo"
license = "foo"
documentation = "foo"
"#,
)
.file("src/lib.rs", "")
.build();

// Allowing a dirty worktree despite it being clean.
p.cargo("package --allow-dirty").run();

let f = File::open(&p.root().join("target/package/foo-0.1.0.crate")).unwrap();
validate_crate_contents(
f,
"foo-0.1.0.crate",
&[
".cargo_vcs_info.json",
"Cargo.toml",
"Cargo.toml.orig",
"src/lib.rs",
],
&[(
".cargo_vcs_info.json",
r#"{
"git": {
"sha1": "[..]"
},
"path_in_vcs": ""
}"#,
)],
);
}

#[cargo_test]
fn generated_manifest() {
let registry = registry::alt_init();
Expand Down Expand Up @@ -2333,6 +2440,7 @@ fn finds_git_in_parent() {
p.cargo("package --list --allow-dirty")
.with_stdout(
"\
.cargo_vcs_info.json
Cargo.toml
Cargo.toml.orig
ignoreme
Expand All @@ -2346,6 +2454,7 @@ src/lib.rs
p.cargo("package --list --allow-dirty")
.with_stdout(
"\
.cargo_vcs_info.json
.gitignore
Cargo.toml
Cargo.toml.orig
Expand All @@ -2359,6 +2468,7 @@ src/lib.rs
p.cargo("package --list --allow-dirty")
.with_stdout(
"\
.cargo_vcs_info.json
.gitignore
Cargo.toml
Cargo.toml.orig
Expand Down Expand Up @@ -2621,6 +2731,7 @@ fn deleted_git_working_tree() {
p.cargo("package --allow-dirty --list")
.with_stdout(
"\
.cargo_vcs_info.json
Cargo.lock
Cargo.toml
Cargo.toml.orig
Expand All @@ -2635,6 +2746,7 @@ src/main.rs
p.cargo("package --allow-dirty --list")
.with_stdout(
"\
.cargo_vcs_info.json
Cargo.lock
Cargo.toml
Cargo.toml.orig
Expand Down
1 change: 1 addition & 0 deletions tests/testsuite/publish_lockfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ fn note_resolve_changes() {
[NOTE] package `multi v0.1.0` added to the packaged Cargo.lock file, was originally sourced from `[..]/foo/multi`
[NOTE] package `patched v1.0.0` added to the packaged Cargo.lock file, was originally sourced from `[..]/foo/patched`
[PACKAGED] [..] files, [..] ([..] compressed)
[WARNING] no (git) Cargo.toml found at `target/tmp/[..]/foo/Cargo.toml` in workdir `[..]`
",
)
.run();
Expand Down