From a6ad3a3ed5163c58dfd546f6064bc2b2aa4a99eb Mon Sep 17 00:00:00 2001
From: Tor Hovland <55164+torhovland@users.noreply.github.com>
Date: Mon, 27 May 2024 10:14:35 +0200
Subject: [PATCH 1/5] test: Verify that the vcs_info file is not included in
 package when allowing dirty.

---
 tests/testsuite/package.rs | 62 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs
index 5e7e410b3a8..c3777a04811 100644
--- a/tests/testsuite/package.rs
+++ b/tests/testsuite/package.rs
@@ -1171,6 +1171,68 @@ src/lib.rs
         .run();
 }
 
+#[cargo_test]
+fn issue_13695_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);
+
+    // Fail because worktree is dirty.
+    p.cargo("package")
+        .with_status(101)
+        .with_stderr_contains(
+            "[ERROR] 2 files in the working directory contain changes that were not yet committed into git:",
+        )
+        .run();
+
+    // Listing fails too.
+    p.cargo("package --list")
+        .with_status(101)
+        .with_stderr_contains(
+            "[ERROR] 2 files in the working directory contain changes that were not yet committed into git:",
+        )
+        .run();
+
+    // Allowing a dirty worktree results in the vcs file not 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.toml", "Cargo.toml.orig", "src/lib.rs"],
+        &[],
+    );
+
+    // Listing provides a consistent result.
+    p.cargo("package --list --allow-dirty")
+        .with_stderr("")
+        .with_stdout(
+            "\
+Cargo.toml
+Cargo.toml.orig
+src/lib.rs
+",
+        )
+        .run();
+}
+
 #[cargo_test]
 fn generated_manifest() {
     let registry = registry::alt_init();

From 2a1299a8780f488eb77fc836b1f2abe32d6d754e Mon Sep 17 00:00:00 2001
From: Tor Hovland <55164+torhovland@users.noreply.github.com>
Date: Mon, 27 May 2024 10:18:44 +0200
Subject: [PATCH 2/5] fix: Include vcs_info even if workspace is dirty.

---
 src/cargo/ops/cargo_package.rs      | 29 +++++++++++++++--------------
 tests/testsuite/git.rs              |  1 +
 tests/testsuite/package.rs          | 17 +++++++++++++++--
 tests/testsuite/publish_lockfile.rs |  1 +
 4 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs
index 30731de20aa..0128473bc5a 100644
--- a/src/cargo/ops/cargo_package.rs
+++ b/src/cargo/ops/cargo_package.rs
@@ -235,14 +235,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)
 }
@@ -559,13 +553,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() {
@@ -585,7 +581,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,
                     }));
                 }
@@ -608,7 +604,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)
@@ -633,7 +634,7 @@ fn check_repo_state(
                     .to_string()
             })
             .collect();
-        if dirty_src_files.is_empty() {
+        if dirty_src_files.is_empty() || opts.allow_dirty {
             let rev_obj = repo.revparse_single("HEAD")?;
             Ok(GitVcsInfo {
                 sha1: rev_obj.id().to_string(),
diff --git a/tests/testsuite/git.rs b/tests/testsuite/git.rs
index 6b9cbd308c6..624fc4260fa 100644
--- a/tests/testsuite/git.rs
+++ b/tests/testsuite/git.rs
@@ -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
diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs
index c3777a04811..79d84c14112 100644
--- a/tests/testsuite/package.rs
+++ b/tests/testsuite/package.rs
@@ -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
@@ -1011,6 +1012,7 @@ src/main.rs
         .with_stderr("")
         .with_stdout(
             "\
+.cargo_vcs_info.json
 .gitignore
 Cargo.lock
 Cargo.toml
@@ -1209,14 +1211,19 @@ fn issue_13695_dirty_vcs_info() {
         )
         .run();
 
-    // Allowing a dirty worktree results in the vcs file not being included.
+    // Allowing a dirty worktree results in the vcs file 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.toml", "Cargo.toml.orig", "src/lib.rs"],
+        &[
+            ".cargo_vcs_info.json",
+            "Cargo.toml",
+            "Cargo.toml.orig",
+            "src/lib.rs",
+        ],
         &[],
     );
 
@@ -1225,6 +1232,7 @@ fn issue_13695_dirty_vcs_info() {
         .with_stderr("")
         .with_stdout(
             "\
+.cargo_vcs_info.json
 Cargo.toml
 Cargo.toml.orig
 src/lib.rs
@@ -2395,6 +2403,7 @@ fn finds_git_in_parent() {
     p.cargo("package --list --allow-dirty")
         .with_stdout(
             "\
+.cargo_vcs_info.json
 Cargo.toml
 Cargo.toml.orig
 ignoreme
@@ -2408,6 +2417,7 @@ src/lib.rs
     p.cargo("package --list --allow-dirty")
         .with_stdout(
             "\
+.cargo_vcs_info.json
 .gitignore
 Cargo.toml
 Cargo.toml.orig
@@ -2421,6 +2431,7 @@ src/lib.rs
     p.cargo("package --list --allow-dirty")
         .with_stdout(
             "\
+.cargo_vcs_info.json
 .gitignore
 Cargo.toml
 Cargo.toml.orig
@@ -2683,6 +2694,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
@@ -2697,6 +2709,7 @@ src/main.rs
     p.cargo("package --allow-dirty --list")
         .with_stdout(
             "\
+.cargo_vcs_info.json
 Cargo.lock
 Cargo.toml
 Cargo.toml.orig
diff --git a/tests/testsuite/publish_lockfile.rs b/tests/testsuite/publish_lockfile.rs
index d8a29d45c47..7e7aedbc0e7 100644
--- a/tests/testsuite/publish_lockfile.rs
+++ b/tests/testsuite/publish_lockfile.rs
@@ -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();

From 1b636855a9405b7745cea608df8eace0cd4139fd Mon Sep 17 00:00:00 2001
From: Tor Hovland <55164+torhovland@users.noreply.github.com>
Date: Wed, 29 May 2024 09:13:26 +0200
Subject: [PATCH 3/5] Add a dirty flag to the vcs_info file.

---
 src/cargo/ops/cargo_package.rs |  6 ++-
 tests/testsuite/package.rs     | 82 +++++++++++++++++++++++++---------
 2 files changed, 66 insertions(+), 22 deletions(-)

diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs
index 0128473bc5a..26934de509f 100644
--- a/src/cargo/ops/cargo_package.rs
+++ b/src/cargo/ops/cargo_package.rs
@@ -81,6 +81,8 @@ struct VcsInfo {
 #[derive(Serialize)]
 struct GitVcsInfo {
     sha1: String,
+    /// Indicate whether or not the Git worktree is dirty.
+    dirty: bool,
 }
 
 /// Packages a single package in a workspace, returning the resulting tar file.
@@ -634,10 +636,12 @@ fn check_repo_state(
                     .to_string()
             })
             .collect();
-        if dirty_src_files.is_empty() || opts.allow_dirty {
+        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!(
diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs
index 79d84c14112..163ce018885 100644
--- a/tests/testsuite/package.rs
+++ b/tests/testsuite/package.rs
@@ -189,7 +189,8 @@ See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for
     let vcs_contents = format!(
         r#"{{
   "git": {{
-    "sha1": "{}"
+    "sha1": "{}",
+    "dirty": false
   }},
   "path_in_vcs": ""
 }}
@@ -230,7 +231,8 @@ See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for
     let vcs_contents = format!(
         r#"{{
   "git": {{
-    "sha1": "{}"
+    "sha1": "{}",
+    "dirty": false
   }},
   "path_in_vcs": "a/a"
 }}
@@ -1174,7 +1176,7 @@ src/lib.rs
 }
 
 #[cargo_test]
-fn issue_13695_dirty_vcs_info() {
+fn issue_13695_allow_dirty_vcs_info() {
     let p = project()
         .file(
             "Cargo.toml",
@@ -1195,23 +1197,7 @@ fn issue_13695_dirty_vcs_info() {
     // Initial commit, with no files added.
     git::commit(&repo);
 
-    // Fail because worktree is dirty.
-    p.cargo("package")
-        .with_status(101)
-        .with_stderr_contains(
-            "[ERROR] 2 files in the working directory contain changes that were not yet committed into git:",
-        )
-        .run();
-
-    // Listing fails too.
-    p.cargo("package --list")
-        .with_status(101)
-        .with_stderr_contains(
-            "[ERROR] 2 files in the working directory contain changes that were not yet committed into git:",
-        )
-        .run();
-
-    // Allowing a dirty worktree results in the vcs file being included.
+    // 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();
@@ -1224,7 +1210,16 @@ fn issue_13695_dirty_vcs_info() {
             "Cargo.toml.orig",
             "src/lib.rs",
         ],
-        &[],
+        &[(
+            ".cargo_vcs_info.json",
+            r#"{
+  "git": {
+    "sha1": "[..]",
+    "dirty": true
+  },
+  "path_in_vcs": ""
+}"#,
+        )],
     );
 
     // Listing provides a consistent result.
@@ -1241,6 +1236,51 @@ 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": "[..]",
+    "dirty": false
+  },
+  "path_in_vcs": ""
+}"#,
+        )],
+    );
+}
+
 #[cargo_test]
 fn generated_manifest() {
     let registry = registry::alt_init();

From a00232d857a06db9b24824c2d33dfa05e3f327eb Mon Sep 17 00:00:00 2001
From: Tor Hovland <55164+torhovland@users.noreply.github.com>
Date: Fri, 31 May 2024 08:55:04 +0200
Subject: [PATCH 4/5] Adjusted documentation about the dirty flag.

---
 src/doc/man/cargo-package.md                | 10 +++++++---
 src/doc/man/generated_txt/cargo-package.txt | 10 +++++++---
 src/doc/src/commands/cargo-package.md       | 10 +++++++---
 src/etc/man/cargo-package.1                 | 10 +++++++---
 4 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/src/doc/man/cargo-package.md b/src/doc/man/cargo-package.md
index 05d0925971f..20bbda9396f 100644
--- a/src/doc/man/cargo-package.md
+++ b/src/doc/man/cargo-package.md
@@ -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, and whether or not 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
@@ -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 whether or not 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.
 
diff --git a/src/doc/man/generated_txt/cargo-package.txt b/src/doc/man/generated_txt/cargo-package.txt
index 1cbee480709..174bf1e5b05 100644
--- a/src/doc/man/generated_txt/cargo-package.txt
+++ b/src/doc/man/generated_txt/cargo-package.txt
@@ -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, and whether or
+             not 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
@@ -51,11 +51,15 @@ DESCRIPTION
 
            {
             "git": {
-              "sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302"
+              "sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302",
+              "dirty": true
             },
             "path_in_vcs": ""
            }
 
+       dirty indicates whether or not 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.
 
diff --git a/src/doc/src/commands/cargo-package.md b/src/doc/src/commands/cargo-package.md
index 87f56f98809..cebb550dc26 100644
--- a/src/doc/src/commands/cargo-package.md
+++ b/src/doc/src/commands/cargo-package.md
@@ -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, and whether or not 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
@@ -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 whether or not 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.
 
diff --git a/src/etc/man/cargo-package.1 b/src/etc/man/cargo-package.1
index f515beaad5a..f715c1e9de1 100644
--- a/src/etc/man/cargo-package.1
+++ b/src/etc/man/cargo-package.1
@@ -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, and whether or not the
+worktree is dirty.
 .RE
 .RE
 .sp
@@ -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 whether or not 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

From e7bfed103cdb31f2b65b2f8ba576405e268e9b98 Mon Sep 17 00:00:00 2001
From: Tor Hovland <55164+torhovland@users.noreply.github.com>
Date: Mon, 3 Jun 2024 10:09:33 +0200
Subject: [PATCH 5/5] Skip serializing the dirty flag if false.

---
 src/cargo/ops/cargo_package.rs              | 1 +
 src/doc/man/cargo-package.md                | 4 ++--
 src/doc/man/generated_txt/cargo-package.txt | 8 ++++----
 src/doc/src/commands/cargo-package.md       | 4 ++--
 src/etc/man/cargo-package.1                 | 4 ++--
 tests/testsuite/package.rs                  | 9 +++------
 6 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs
index 26934de509f..e5821867f8a 100644
--- a/src/cargo/ops/cargo_package.rs
+++ b/src/cargo/ops/cargo_package.rs
@@ -82,6 +82,7 @@ struct VcsInfo {
 struct GitVcsInfo {
     sha1: String,
     /// Indicate whether or not the Git worktree is dirty.
+    #[serde(skip_serializing_if = "std::ops::Not::not")]
     dirty: bool,
 }
 
diff --git a/src/doc/man/cargo-package.md b/src/doc/man/cargo-package.md
index 20bbda9396f..42fa2366b83 100644
--- a/src/doc/man/cargo-package.md
+++ b/src/doc/man/cargo-package.md
@@ -31,7 +31,7 @@ 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, and whether or not the
+      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
@@ -59,7 +59,7 @@ Will generate a `.cargo_vcs_info.json` in the following format
 }
 ```
 
-`dirty` indicates whether or not the Git worktree was dirty when the package
+`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
diff --git a/src/doc/man/generated_txt/cargo-package.txt b/src/doc/man/generated_txt/cargo-package.txt
index 174bf1e5b05..0e474d17ff8 100644
--- a/src/doc/man/generated_txt/cargo-package.txt
+++ b/src/doc/man/generated_txt/cargo-package.txt
@@ -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, and whether or
-             not the worktree is 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
@@ -57,8 +57,8 @@ DESCRIPTION
             "path_in_vcs": ""
            }
 
-       dirty indicates whether or not the Git worktree was dirty when the
-       package was built.
+       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.
diff --git a/src/doc/src/commands/cargo-package.md b/src/doc/src/commands/cargo-package.md
index cebb550dc26..bb3324fdb74 100644
--- a/src/doc/src/commands/cargo-package.md
+++ b/src/doc/src/commands/cargo-package.md
@@ -26,7 +26,7 @@ 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, and whether or not the
+      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
@@ -54,7 +54,7 @@ Will generate a `.cargo_vcs_info.json` in the following format
 }
 ```
 
-`dirty` indicates whether or not the Git worktree was dirty when the package
+`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
diff --git a/src/etc/man/cargo-package.1 b/src/etc/man/cargo-package.1
index f715c1e9de1..9a7986014a4 100644
--- a/src/etc/man/cargo-package.1
+++ b/src/etc/man/cargo-package.1
@@ -43,7 +43,7 @@ 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, and whether or not the
+about the current VCS checkout hash if available, as well as a flag if the
 worktree is dirty.
 .RE
 .RE
@@ -82,7 +82,7 @@ Will generate a \fB\&.cargo_vcs_info.json\fR in the following format
 .fi
 .RE
 .sp
-\fBdirty\fR indicates whether or not the Git worktree was dirty when the package
+\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
diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs
index 163ce018885..91179535acb 100644
--- a/tests/testsuite/package.rs
+++ b/tests/testsuite/package.rs
@@ -189,8 +189,7 @@ See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for
     let vcs_contents = format!(
         r#"{{
   "git": {{
-    "sha1": "{}",
-    "dirty": false
+    "sha1": "{}"
   }},
   "path_in_vcs": ""
 }}
@@ -231,8 +230,7 @@ See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for
     let vcs_contents = format!(
         r#"{{
   "git": {{
-    "sha1": "{}",
-    "dirty": false
+    "sha1": "{}"
   }},
   "path_in_vcs": "a/a"
 }}
@@ -1272,8 +1270,7 @@ fn issue_13695_allowing_dirty_vcs_info_but_clean() {
             ".cargo_vcs_info.json",
             r#"{
   "git": {
-    "sha1": "[..]",
-    "dirty": false
+    "sha1": "[..]"
   },
   "path_in_vcs": ""
 }"#,