mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
Auto merge of #13960 - tweag:issue-13695, r=weihanglo
Include vcs_info even if workspace is dirty ### What does this PR try to resolve? Related to #13695. Generates and packages the `.cargo_vcs_info.json` file even if the worktree is dirty, as long as `--allow-dirty` is passed. Also added a `dirty` field to the file to record if the Git repository status is dirty. Tests are included.
This commit is contained in:
commit
95d16bed8c
@ -81,6 +81,9 @@ struct VcsInfo {
|
|||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct GitVcsInfo {
|
struct GitVcsInfo {
|
||||||
sha1: String,
|
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.
|
/// Packages a single package in a workspace, returning the resulting tar file.
|
||||||
@ -235,14 +238,8 @@ fn prepare_archive(
|
|||||||
}
|
}
|
||||||
let src_files = src.list_files(pkg)?;
|
let src_files = src.list_files(pkg)?;
|
||||||
|
|
||||||
// Check (git) repository state, getting the current commit hash if not
|
// Check (git) repository state, getting the current commit hash.
|
||||||
// dirty.
|
let vcs_info = check_repo_state(pkg, &src_files, gctx, &opts)?;
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
build_ar_list(ws, pkg, src_files, vcs_info)
|
build_ar_list(ws, pkg, src_files, vcs_info)
|
||||||
}
|
}
|
||||||
@ -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
|
/// 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
|
/// the source is *dirty* (e.g., has uncommitted changes), and `--allow-dirty`
|
||||||
/// informative message. Otherwise return the sha1 hash of the current *HEAD*
|
/// has not been passed, then `bail!` with an informative message. Otherwise
|
||||||
/// commit, or `None` if no repo is found.
|
/// return the sha1 hash of the current *HEAD* commit, or `None` if no repo is
|
||||||
|
/// found.
|
||||||
fn check_repo_state(
|
fn check_repo_state(
|
||||||
p: &Package,
|
p: &Package,
|
||||||
src_files: &[PathBuf],
|
src_files: &[PathBuf],
|
||||||
gctx: &GlobalContext,
|
gctx: &GlobalContext,
|
||||||
|
opts: &PackageOpts<'_>,
|
||||||
) -> CargoResult<Option<VcsInfo>> {
|
) -> CargoResult<Option<VcsInfo>> {
|
||||||
if let Ok(repo) = git2::Repository::discover(p.root()) {
|
if let Ok(repo) = git2::Repository::discover(p.root()) {
|
||||||
if let Some(workdir) = repo.workdir() {
|
if let Some(workdir) = repo.workdir() {
|
||||||
@ -585,7 +584,7 @@ fn check_repo_state(
|
|||||||
.unwrap_or("")
|
.unwrap_or("")
|
||||||
.replace("\\", "/");
|
.replace("\\", "/");
|
||||||
return Ok(Some(VcsInfo {
|
return Ok(Some(VcsInfo {
|
||||||
git: git(p, src_files, &repo)?,
|
git: git(p, src_files, &repo, &opts)?,
|
||||||
path_in_vcs,
|
path_in_vcs,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -608,7 +607,12 @@ fn check_repo_state(
|
|||||||
// directory is dirty or not, thus we have to assume that it's clean.
|
// directory is dirty or not, thus we have to assume that it's clean.
|
||||||
return Ok(None);
|
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:
|
// This is a collection of any dirty or untracked files. This covers:
|
||||||
// - new/modified/deleted/renamed/type change (index or worktree)
|
// - new/modified/deleted/renamed/type change (index or worktree)
|
||||||
// - untracked files (which are "new" worktree files)
|
// - untracked files (which are "new" worktree files)
|
||||||
@ -633,10 +637,12 @@ fn check_repo_state(
|
|||||||
.to_string()
|
.to_string()
|
||||||
})
|
})
|
||||||
.collect();
|
.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")?;
|
let rev_obj = repo.revparse_single("HEAD")?;
|
||||||
Ok(GitVcsInfo {
|
Ok(GitVcsInfo {
|
||||||
sha1: rev_obj.id().to_string(),
|
sha1: rev_obj.id().to_string(),
|
||||||
|
dirty,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
|
@ -31,8 +31,8 @@ steps:
|
|||||||
executable binary or example target. {{man "cargo-install" 1}} will use the
|
executable binary or example target. {{man "cargo-install" 1}} will use the
|
||||||
packaged lock file if the `--locked` flag is used.
|
packaged lock file if the `--locked` flag is used.
|
||||||
- A `.cargo_vcs_info.json` file is included that contains information
|
- A `.cargo_vcs_info.json` file is included that contains information
|
||||||
about the current VCS checkout hash if available (not included with
|
about the current VCS checkout hash if available, as well as a flag if the
|
||||||
`--allow-dirty`).
|
worktree is dirty.
|
||||||
3. Extract the `.crate` file and build it to verify it can build.
|
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
|
- 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
|
built from a pristine state. The `--no-verify` flag can be used to skip
|
||||||
@ -52,12 +52,16 @@ Will generate a `.cargo_vcs_info.json` in the following format
|
|||||||
```javascript
|
```javascript
|
||||||
{
|
{
|
||||||
"git": {
|
"git": {
|
||||||
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302"
|
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302",
|
||||||
|
"dirty": true
|
||||||
},
|
},
|
||||||
"path_in_vcs": ""
|
"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
|
`path_in_vcs` will be set to a repo-relative path for packages
|
||||||
in subdirectories of the version control repository.
|
in subdirectories of the version control repository.
|
||||||
|
|
||||||
|
@ -29,8 +29,8 @@ DESCRIPTION
|
|||||||
packaged lock file if the --locked flag is used.
|
packaged lock file if the --locked flag is used.
|
||||||
|
|
||||||
o A .cargo_vcs_info.json file is included that contains information
|
o A .cargo_vcs_info.json file is included that contains information
|
||||||
about the current VCS checkout hash if available (not included
|
about the current VCS checkout hash if available, as well as a
|
||||||
with --allow-dirty).
|
flag if the worktree is dirty.
|
||||||
|
|
||||||
3. Extract the .crate file and build it to verify it can build.
|
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
|
o This will rebuild your package from scratch to ensure that it can
|
||||||
@ -51,11 +51,15 @@ DESCRIPTION
|
|||||||
|
|
||||||
{
|
{
|
||||||
"git": {
|
"git": {
|
||||||
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302"
|
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302",
|
||||||
|
"dirty": true
|
||||||
},
|
},
|
||||||
"path_in_vcs": ""
|
"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
|
path_in_vcs will be set to a repo-relative path for packages in
|
||||||
subdirectories of the version control repository.
|
subdirectories of the version control repository.
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ steps:
|
|||||||
executable binary or example target. [cargo-install(1)](cargo-install.html) will use the
|
executable binary or example target. [cargo-install(1)](cargo-install.html) will use the
|
||||||
packaged lock file if the `--locked` flag is used.
|
packaged lock file if the `--locked` flag is used.
|
||||||
- A `.cargo_vcs_info.json` file is included that contains information
|
- A `.cargo_vcs_info.json` file is included that contains information
|
||||||
about the current VCS checkout hash if available (not included with
|
about the current VCS checkout hash if available, as well as a flag if the
|
||||||
`--allow-dirty`).
|
worktree is dirty.
|
||||||
3. Extract the `.crate` file and build it to verify it can build.
|
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
|
- 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
|
built from a pristine state. The `--no-verify` flag can be used to skip
|
||||||
@ -47,12 +47,16 @@ Will generate a `.cargo_vcs_info.json` in the following format
|
|||||||
```javascript
|
```javascript
|
||||||
{
|
{
|
||||||
"git": {
|
"git": {
|
||||||
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302"
|
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302",
|
||||||
|
"dirty": true
|
||||||
},
|
},
|
||||||
"path_in_vcs": ""
|
"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
|
`path_in_vcs` will be set to a repo-relative path for packages
|
||||||
in subdirectories of the version control repository.
|
in subdirectories of the version control repository.
|
||||||
|
|
||||||
|
@ -43,8 +43,8 @@ packaged lock file if the \fB\-\-locked\fR flag is used.
|
|||||||
.sp
|
.sp
|
||||||
.RS 4
|
.RS 4
|
||||||
\h'-04'\(bu\h'+02'A \fB\&.cargo_vcs_info.json\fR file is included that contains information
|
\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
|
about the current VCS checkout hash if available, as well as a flag if the
|
||||||
\fB\-\-allow\-dirty\fR).
|
worktree is dirty.
|
||||||
.RE
|
.RE
|
||||||
.RE
|
.RE
|
||||||
.sp
|
.sp
|
||||||
@ -74,13 +74,17 @@ Will generate a \fB\&.cargo_vcs_info.json\fR in the following format
|
|||||||
.nf
|
.nf
|
||||||
{
|
{
|
||||||
"git": {
|
"git": {
|
||||||
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302"
|
"sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302",
|
||||||
|
"dirty": true
|
||||||
},
|
},
|
||||||
"path_in_vcs": ""
|
"path_in_vcs": ""
|
||||||
}
|
}
|
||||||
.fi
|
.fi
|
||||||
.RE
|
.RE
|
||||||
.sp
|
.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
|
\fBpath_in_vcs\fR will be set to a repo\-relative path for packages
|
||||||
in subdirectories of the version control repository.
|
in subdirectories of the version control repository.
|
||||||
.sp
|
.sp
|
||||||
|
@ -2610,6 +2610,7 @@ fn include_overrides_gitignore() {
|
|||||||
p.cargo("package --list --allow-dirty")
|
p.cargo("package --list --allow-dirty")
|
||||||
.with_stdout(
|
.with_stdout(
|
||||||
"\
|
"\
|
||||||
|
.cargo_vcs_info.json
|
||||||
Cargo.toml
|
Cargo.toml
|
||||||
Cargo.toml.orig
|
Cargo.toml.orig
|
||||||
ignored.txt
|
ignored.txt
|
||||||
|
@ -703,6 +703,7 @@ fn no_duplicates_from_modified_tracked_files() {
|
|||||||
p.cargo("package --list --allow-dirty")
|
p.cargo("package --list --allow-dirty")
|
||||||
.with_stdout(
|
.with_stdout(
|
||||||
"\
|
"\
|
||||||
|
.cargo_vcs_info.json
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
Cargo.toml
|
Cargo.toml
|
||||||
Cargo.toml.orig
|
Cargo.toml.orig
|
||||||
@ -1011,6 +1012,7 @@ src/main.rs
|
|||||||
.with_stderr("")
|
.with_stderr("")
|
||||||
.with_stdout(
|
.with_stdout(
|
||||||
"\
|
"\
|
||||||
|
.cargo_vcs_info.json
|
||||||
.gitignore
|
.gitignore
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
Cargo.toml
|
Cargo.toml
|
||||||
@ -1171,6 +1173,111 @@ src/lib.rs
|
|||||||
.run();
|
.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]
|
#[cargo_test]
|
||||||
fn generated_manifest() {
|
fn generated_manifest() {
|
||||||
let registry = registry::alt_init();
|
let registry = registry::alt_init();
|
||||||
@ -2333,6 +2440,7 @@ fn finds_git_in_parent() {
|
|||||||
p.cargo("package --list --allow-dirty")
|
p.cargo("package --list --allow-dirty")
|
||||||
.with_stdout(
|
.with_stdout(
|
||||||
"\
|
"\
|
||||||
|
.cargo_vcs_info.json
|
||||||
Cargo.toml
|
Cargo.toml
|
||||||
Cargo.toml.orig
|
Cargo.toml.orig
|
||||||
ignoreme
|
ignoreme
|
||||||
@ -2346,6 +2454,7 @@ src/lib.rs
|
|||||||
p.cargo("package --list --allow-dirty")
|
p.cargo("package --list --allow-dirty")
|
||||||
.with_stdout(
|
.with_stdout(
|
||||||
"\
|
"\
|
||||||
|
.cargo_vcs_info.json
|
||||||
.gitignore
|
.gitignore
|
||||||
Cargo.toml
|
Cargo.toml
|
||||||
Cargo.toml.orig
|
Cargo.toml.orig
|
||||||
@ -2359,6 +2468,7 @@ src/lib.rs
|
|||||||
p.cargo("package --list --allow-dirty")
|
p.cargo("package --list --allow-dirty")
|
||||||
.with_stdout(
|
.with_stdout(
|
||||||
"\
|
"\
|
||||||
|
.cargo_vcs_info.json
|
||||||
.gitignore
|
.gitignore
|
||||||
Cargo.toml
|
Cargo.toml
|
||||||
Cargo.toml.orig
|
Cargo.toml.orig
|
||||||
@ -2621,6 +2731,7 @@ fn deleted_git_working_tree() {
|
|||||||
p.cargo("package --allow-dirty --list")
|
p.cargo("package --allow-dirty --list")
|
||||||
.with_stdout(
|
.with_stdout(
|
||||||
"\
|
"\
|
||||||
|
.cargo_vcs_info.json
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
Cargo.toml
|
Cargo.toml
|
||||||
Cargo.toml.orig
|
Cargo.toml.orig
|
||||||
@ -2635,6 +2746,7 @@ src/main.rs
|
|||||||
p.cargo("package --allow-dirty --list")
|
p.cargo("package --allow-dirty --list")
|
||||||
.with_stdout(
|
.with_stdout(
|
||||||
"\
|
"\
|
||||||
|
.cargo_vcs_info.json
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
Cargo.toml
|
Cargo.toml
|
||||||
Cargo.toml.orig
|
Cargo.toml.orig
|
||||||
|
@ -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 `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`
|
[NOTE] package `patched v1.0.0` added to the packaged Cargo.lock file, was originally sourced from `[..]/foo/patched`
|
||||||
[PACKAGED] [..] files, [..] ([..] compressed)
|
[PACKAGED] [..] files, [..] ([..] compressed)
|
||||||
|
[WARNING] no (git) Cargo.toml found at `target/tmp/[..]/foo/Cargo.toml` in workdir `[..]`
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
.run();
|
.run();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user