Repository: EmbarkStudios/cargo-deny (language: rust)

Issue:
Wildcard version warnings generated git dependencies with fixed commit
**Describe the bug**

When specifying a git dependency with a `rev` (i.e., fixed commit hash) entry, the version wildcard warning is triggered.
However, because of the commit hash, an exact version has been specified.

**To Reproduce**
Steps to reproduce the behavior:
1. Add a git dependency with a commit specified, e.g.:

    ```toml
    [dependencies]
    bevy_ecs_tilemap = { git = "https://github.com/StarArawn/bevy_ecs_tilemap", rev = "2967a394dc59c29fac14cb8cb187d601ea604a1e" }
    ```
3. Ban wildcard dependencies in `deny.toml`:

    ```toml
    [bans]
    wildcards = "deny"
    ```

4. Run `cargo deny check`. A wildcard error is triggered for the git dependency.
    In our case, it looks like this (with two git dependencies):

    ```
    error[wildcard]: found 3 wildcard dependencies for crate 'emergence_lib'
      ┌─ /home/tim/Documents/bevyengine/Emergence/emergence_lib/Cargo.toml:2:1
      │
    2 │ bevy-trait-query = '*'
      │ ^^^^^^^^^^^^^^^^^^^^^^ wildcard crate entry
    3 │ bevy_ecs_tilemap = '*'
    4 │ bevy_ecs_tilemap = '*'
      │ ^^^^^^^^^^^^^^^^^^^^^^
      │ │
      │ wildcard crate entry
      │ wildcard crate entry
      │
      = emergence_lib v0.1.0
        └── emergence_game v0.1.0

**Expected behavior**

The wildcard warning is only triggered for git dependencies if the commit hash is not fixed, i.e. when the `rev` attribute is missing.

**Device:**
 - OS: Linux (Pop!_OS)
 - Version `0.13.5`

Wildcard version warnings generated git dependencies with fixed commit
**Describe the bug**

When specifying a git dependency with a `rev` (i.e., fixed commit hash) entry, the version wildcard warning is triggered.
However, because of the commit hash, an exact version has been specified.

**To Reproduce**
Steps to reproduce the behavior:
1. Add a git dependency with a commit specified, e.g.:

    ```toml
    [dependencies]
    bevy_ecs_tilemap = { git = "https://github.com/StarArawn/bevy_ecs_tilemap", rev = "2967a394dc59c29fac14cb8cb187d601ea604a1e" }
    ```
3. Ban wildcard dependencies in `deny.toml`:

    ```toml
    [bans]
    wildcards = "deny"
    ```

4. Run `cargo deny check`. A wildcard error is triggered for the git dependency.
    In our case, it looks like this (with two git dependencies):

    ```
    error[wildcard]: found 3 wildcard dependencies for crate 'emergence_lib'
      ┌─ /home/tim/Documents/bevyengine/Emergence/emergence_lib/Cargo.toml:2:1
      │
    2 │ bevy-trait-query = '*'
      │ ^^^^^^^^^^^^^^^^^^^^^^ wildcard crate entry
    3 │ bevy_ecs_tilemap = '*'
    4 │ bevy_ecs_tilemap = '*'
      │ ^^^^^^^^^^^^^^^^^^^^^^
      │ │
      │ wildcard crate entry
      │ wildcard crate entry
      │
      = emergence_lib v0.1.0
        └── emergence_game v0.1.0

**Expected behavior**

The wildcard warning is only triggered for git dependencies if the commit hash is not fixed, i.e. when the `rev` attribute is missing.

**Device:**
 - OS: Linux (Pop!_OS)
 - Version `0.13.5`



Discussion / hints:
This was fixed in #487
I'm still getting the same error with cargo-deny `0.13.6`, is that intentional?
Sorry, thought this was fixed, I guess I need another edge case when git dependencies are direct like that instead of a patch on top of a version, which is the only way I use them.
I believe I'm seeing this error, or a related one. I have a private package that is importing some other private packages from GitLab. Even with `allow-wildcard-paths`, I get this message:

```
error[wildcard]: found 2 wildcard dependencies for crate 'behavioral-tests'. allow-wildcard-paths is enabled, but does not apply to public crates as crates.io disallows path dependencies.
```

There's no indication of why `cargo deny` thinks there's a "public crate" involved here; is it saying that the two packages I've specified as `git` dependencies are public, or that the top-level package is public?
This was fixed in #487
I'm still getting the same error with cargo-deny `0.13.6`, is that intentional?
Sorry, thought this was fixed, I guess I need another edge case when git dependencies are direct like that instead of a patch on top of a version, which is the only way I use them.
I believe I'm seeing this error, or a related one. I have a private package that is importing some other private packages from GitLab. Even with `allow-wildcard-paths`, I get this message:

```
error[wildcard]: found 2 wildcard dependencies for crate 'behavioral-tests'. allow-wildcard-paths is enabled, but does not apply to public crates as crates.io disallows path dependencies.
```

There's no indication of why `cargo deny` thinks there's a "public crate" involved here; is it saying that the two packages I've specified as `git` dependencies are public, or that the top-level package is public?

Fix patch:
diff --git a/docs/src/checks/bans/cfg.md b/docs/src/checks/bans/cfg.md
index ab6b75aac..b897c298c 100644
--- a/docs/src/checks/bans/cfg.md
+++ b/docs/src/checks/bans/cfg.md
@@ -32,11 +32,11 @@ Determines what happens when a dependency is specified with the `*` (wildcard) v
 
 If specified, alters how the `wildcard` field behaves:
 
-* [path](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-path-dependencies) `dependencies` in **private** crates will no longer emit a warning or error.
-* path `dev-dependencies` in both public and private crates will no longer emit a warning or error.
-* path `dependencies` and `build-dependencies` in **public** crates will continue to produce warnings and errors.
+* [path](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-path-dependencies) or [git](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories) `dependencies` in **private** crates will no longer emit a warning or error.
+* path or git `dev-dependencies` in both public and private crates will no longer emit a warning or error.
+* path or git `dependencies` and `build-dependencies` in **public** crates will continue to produce warnings and errors.
 
-Being limited to private crates is due to crates.io not allowing packages to be published with `path` dependencies except for `dev-dependencies`.
+Being limited to private crates is due to crates.io not allowing packages to be published with `path` or `git` dependencies except for `dev-dependencies`.
 
 ### The `highlight` field (optional)
 
diff --git a/src/bans.rs b/src/bans.rs
index 079d16e31..d4858b746 100644
--- a/src/bans.rs
+++ b/src/bans.rs
@@ -786,12 +786,13 @@ pub fn check(
                                 let is_private = krate.is_private(&[]);
 
                                 wildcards.retain(|dep| {
+                                    let is_path_or_git = is_path_or_git_dependency(dep);
                                     if is_private {
-                                        dep.path.is_none()
+                                        !is_path_or_git
                                     } else {
-                                        let is_path_dev_dependency = dep.path.is_some()
+                                        let is_path_non_dev_dependency = is_path_or_git
                                             && dep.kind != DependencyKind::Development;
-                                        is_path_dev_dependency || dep.path.is_none()
+                                        is_path_non_dev_dependency || !is_path_or_git
                                     }
                                 });
                             }
@@ -1415,3 +1416,15 @@ fn validate_file_checksum(path: &crate::Path, expected: &cfg::Checksum) -> anyho
     validate_checksum(std::io::BufReader::new(file), expected)?;
     Ok(())
 }
+
+/// Returns true if the dependency has a `path` or `git` source.
+///
+/// TODO: Possibly what we actually care about, where this is used in the wildcard check, is
+/// “is not using any registry source”.
+fn is_path_or_git_dependency(dep: &krates::cm::Dependency) -> bool {
+    dep.path.is_some()
+        || dep
+            .source
+            .as_ref()
+            .is_some_and(|url| url.starts_with("git+"))
+}


Test patch:
diff --git a/tests/bans.rs b/tests/bans.rs
index bc0118c94..fce726a28 100644
--- a/tests/bans.rs
+++ b/tests/bans.rs
@@ -96,6 +96,22 @@ allow-wildcard-paths = true
     insta::assert_json_snapshot!(diags);
 }
 
+/// Ensures that dependencies with wildcard and git are allowed for private packages
+#[test]
+fn allow_git_wildcards_private_package() {
+    let diags = gather_bans(
+        func_name!(),
+        KrateGather::new("wildcards/allow-git"),
+        r#"
+multiple-versions = 'allow'
+wildcards = 'deny'
+allow-wildcard-paths = true
+"#,
+    );
+
+    insta::assert_json_snapshot!(diags);
+}
+
 /// Ensures that multiple versions are always deterministically sorted by
 /// version number
 /// See <https://github.com/EmbarkStudios/cargo-deny/issues/384>
diff --git a/tests/snapshots/bans__allow_git_wildcards_private_package.snap b/tests/snapshots/bans__allow_git_wildcards_private_package.snap
new file mode 100644
index 000000000..0683bea45
--- /dev/null
+++ b/tests/snapshots/bans__allow_git_wildcards_private_package.snap
@@ -0,0 +1,5 @@
+---
+source: tests/bans.rs
+expression: diags
+---
+[]
diff --git a/tests/test_data/wildcards/allow-git/Cargo.lock b/tests/test_data/wildcards/allow-git/Cargo.lock
new file mode 100644
index 000000000..f7dc95566
--- /dev/null
+++ b/tests/test_data/wildcards/allow-git/Cargo.lock
@@ -0,0 +1,213 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "camino"
+version = "1.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.18.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "semver",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
+name = "cfg-expr"
+version = "0.15.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6100bc57b6209840798d95cb2775684849d332f7bd788db2a8c8caf7ef82a41a"
+dependencies = [
+ "smallvec",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
+name = "fixedbitset"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
+
+[[package]]
+name = "hashbrown"
+version = "0.14.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+
+[[package]]
+name = "indexmap"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
+
+[[package]]
+name = "krates"
+version = "0.16.6"
+source = "git+https://github.com/EmbarkStudios/krates?rev=b03ecd6f3204a1b1ec04fbaead2d0d122a3a4494#b03ecd6f3204a1b1ec04fbaead2d0d122a3a4494"
+dependencies = [
+ "cargo_metadata",
+ "cfg-expr",
+ "petgraph",
+ "semver",
+]
+
+[[package]]
+name = "petgraph"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
+dependencies = [
+ "fixedbitset",
+ "indexmap",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.49"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
+
+[[package]]
+name = "semver"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.156"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.156"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.99"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
+name = "syn"
+version = "1.0.107"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
+
+[[package]]
+name = "wildcards-test-allow-git"
+version = "0.1.0"
+dependencies = [
+ "krates",
+]
diff --git a/tests/test_data/wildcards/allow-git/Cargo.toml b/tests/test_data/wildcards/allow-git/Cargo.toml
new file mode 100644
index 000000000..e2e40f488
--- /dev/null
+++ b/tests/test_data/wildcards/allow-git/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "wildcards-test-allow-git"
+version = "0.1.0"
+authors = []
+edition = "2018"
+license = "MIT"
+
+publish = false
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+# An arbitrary choice of actually existant Git repository
+wildcards-test-allow-git = { package = "krates", git = "https://github.com/EmbarkStudios/krates", rev = "b03ecd6f3204a1b1ec04fbaead2d0d122a3a4494" }
diff --git a/tests/test_data/wildcards/allow-git/src/main.rs b/tests/test_data/wildcards/allow-git/src/main.rs
new file mode 100644
index 000000000..f328e4d9d
--- /dev/null
+++ b/tests/test_data/wildcards/allow-git/src/main.rs
@@ -0,0 +1,1 @@
+fn main() {}