Repository: rust-lang/cargo (rust)

Issue:
`cargo update --config net.git-fetch-with-cli=true` fetches using git2
### Problem

As reported in renovatebot/renovate#29277
- Private git repo dependency fetching worked on 1.77 but not 1.78
- They used `net.git-fetch-with-cli=true` on the command-line

I git bisected it to #13479, specifically f525e1f383fc0d0a7adbdfb1bac6d6228ae79b33

### Steps

```console
$ git clone https://github.com/crate-ci/cargo-release.git
$ cd cargo-release
$ rm -rf ~/.cargo/git  # avoiding the github fast path
$ cargo update --config net.git-fetch-with-cli=true
```
Notice that the fetch is done using libgit2 instead of git.  To make this more obvious, I ran from master with a `dbg!` around the `git_fetch_with_cli` check at
https://github.com/rust-lang/cargo/blob/d04355a8c42f8c173a0c02625477edd668fc0cdd/src/cargo/sources/git/utils.rs#L1008

### Possible Solution(s)

_No response_

### Notes

_No response_

### Version

_No response_

Pull request description:
fix(config): Ensure `--config net.git-fetch-with-cli=true` is respected
### What does this PR try to resolve?

#13479 changed the global context initialization order so that command line stuff is processed after we read some config.
This had a side effect of breaking `--config net.git-fetch-with-cli=true`.
I reverted the change to restore support for `--config`.

Fixes #13991

### How should we test and review this PR?


### Additional information

This reverts commit https://github.com/rust-lang/cargo/commit/f525e1f383fc0d0a7adbdfb1bac6d6228ae79b33.

This removes color control from warnings for unstable features.
For some reason this removed color support from `cargo -Zhelp` in the
tests but I can't reproduce it locally.

The most important thing was getting the config fix in.
There are two follow ups
- Can we have the config working *and* color?
- Why did this fail for this field and not the others we already had
  tests for?

I ran out my immediate time box for looking into these.

Patch:
diff --git a/src/cargo/util/context/mod.rs b/src/cargo/util/context/mod.rs
index 2ce4f2ace..85eeccab6 100644
--- a/src/cargo/util/context/mod.rs
+++ b/src/cargo/util/context/mod.rs
@@ -1020,6 +1020,31 @@ impl GlobalContext {
         unstable_flags: &[String],
         cli_config: &[String],
     ) -> CargoResult<()> {
+        for warning in self
+            .unstable_flags
+            .parse(unstable_flags, self.nightly_features_allowed)?
+        {
+            self.shell().warn(warning)?;
+        }
+        if !unstable_flags.is_empty() {
+            // store a copy of the cli flags separately for `load_unstable_flags_from_config`
+            // (we might also need it again for `reload_rooted_at`)
+            self.unstable_flags_cli = Some(unstable_flags.to_vec());
+        }
+        if !cli_config.is_empty() {
+            self.cli_config = Some(cli_config.iter().map(|s| s.to_string()).collect());
+            self.merge_cli_args()?;
+        }
+        if self.unstable_flags.config_include {
+            // If the config was already loaded (like when fetching the
+            // `[alias]` table), it was loaded with includes disabled because
+            // the `unstable_flags` hadn't been set up, yet. Any values
+            // fetched before this step will not process includes, but that
+            // should be fine (`[alias]` is one of the only things loaded
+            // before configure). This can be removed when stabilized.
+            self.reload_rooted_at(self.cwd.clone())?;
+        }
+
         // Ignore errors in the configuration files. We don't want basic
         // commands like `cargo version` to error out due to config file
         // problems.
@@ -1066,31 +1091,6 @@ impl GlobalContext {
         let cli_target_dir = target_dir.as_ref().map(|dir| Filesystem::new(dir.clone()));
         self.target_dir = cli_target_dir;
 
-        for warning in self
-            .unstable_flags
-            .parse(unstable_flags, self.nightly_features_allowed)?
-        {
-            self.shell().warn(warning)?;
-        }
-        if !unstable_flags.is_empty() {
-            // store a copy of the cli flags separately for `load_unstable_flags_from_config`
-            // (we might also need it again for `reload_rooted_at`)
-            self.unstable_flags_cli = Some(unstable_flags.to_vec());
-        }
-        if !cli_config.is_empty() {
-            self.cli_config = Some(cli_config.iter().map(|s| s.to_string()).collect());
-            self.merge_cli_args()?;
-        }
-        if self.unstable_flags.config_include {
-            // If the config was already loaded (like when fetching the
-            // `[alias]` table), it was loaded with includes disabled because
-            // the `unstable_flags` hadn't been set up, yet. Any values
-            // fetched before this step will not process includes, but that
-            // should be fine (`[alias]` is one of the only things loaded
-            // before configure). This can be removed when stabilized.
-            self.reload_rooted_at(self.cwd.clone())?;
-        }
-
         self.load_unstable_flags_from_config()?;
 
         Ok(())


Test patch:
diff --git a/tests/testsuite/cargo/z_help/stdout.term.svg b/tests/testsuite/cargo/z_help/stdout.term.svg
index c453ebc0b..a4c8e579b 100644
--- a/tests/testsuite/cargo/z_help/stdout.term.svg
+++ b/tests/testsuite/cargo/z_help/stdout.term.svg
@@ -2,13 +2,10 @@
   <style>
     .fg { fill: #AAAAAA }
     .bg { background: #000000 }
-    .fg-cyan { fill: #00AAAA }
-    .fg-green { fill: #00AA00 }
     .container {
       padding: 0 10px;
       line-height: 18px;
     }
-    .bold { font-weight: bold; }
     tspan {
       font: 14px SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
       white-space: pre;
@@ -19,75 +16,75 @@
   <rect width="100%" height="100%" y="0" rx="4.5" class="bg" />
 
   <text xml:space="preserve" class="container fg">
-    <tspan x="10px" y="28px"><tspan class="fg-green bold">Available unstable (nightly-only) flags:</tspan>
+    <tspan x="10px" y="28px"><tspan>Available unstable (nightly-only) flags:</tspan>
 </tspan>
     <tspan x="10px" y="46px">
 </tspan>
-    <tspan x="10px" y="64px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z allow-features         </tspan><tspan>  Allow *only* the listed unstable features</tspan>
+    <tspan x="10px" y="64px"><tspan>    -Z allow-features           Allow *only* the listed unstable features</tspan>
 </tspan>
-    <tspan x="10px" y="82px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z asymmetric-token       </tspan><tspan>  Allows authenticating with asymmetric tokens</tspan>
+    <tspan x="10px" y="82px"><tspan>    -Z asymmetric-token         Allows authenticating with asymmetric tokens</tspan>
 </tspan>
-    <tspan x="10px" y="100px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z avoid-dev-deps         </tspan><tspan>  Avoid installing dev-dependencies if possible</tspan>
+    <tspan x="10px" y="100px"><tspan>    -Z avoid-dev-deps           Avoid installing dev-dependencies if possible</tspan>
 </tspan>
-    <tspan x="10px" y="118px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z binary-dep-depinfo     </tspan><tspan>  Track changes to dependency artifacts</tspan>
+    <tspan x="10px" y="118px"><tspan>    -Z binary-dep-depinfo       Track changes to dependency artifacts</tspan>
 </tspan>
-    <tspan x="10px" y="136px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z bindeps                </tspan><tspan>  Allow Cargo packages to depend on bin, cdylib, and staticlib crates, and use the artifacts built by those crates</tspan>
+    <tspan x="10px" y="136px"><tspan>    -Z bindeps                  Allow Cargo packages to depend on bin, cdylib, and staticlib crates, and use the artifacts built by those crates</tspan>
 </tspan>
-    <tspan x="10px" y="154px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z build-std              </tspan><tspan>  Enable Cargo to compile the standard library itself as part of a crate graph compilation</tspan>
+    <tspan x="10px" y="154px"><tspan>    -Z build-std                Enable Cargo to compile the standard library itself as part of a crate graph compilation</tspan>
 </tspan>
-    <tspan x="10px" y="172px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z build-std-features     </tspan><tspan>  Configure features enabled for the standard library itself when building the standard library</tspan>
+    <tspan x="10px" y="172px"><tspan>    -Z build-std-features       Configure features enabled for the standard library itself when building the standard library</tspan>
 </tspan>
-    <tspan x="10px" y="190px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z cargo-lints            </tspan><tspan>  Enable the `[lints.cargo]` table</tspan>
+    <tspan x="10px" y="190px"><tspan>    -Z cargo-lints              Enable the `[lints.cargo]` table</tspan>
 </tspan>
-    <tspan x="10px" y="208px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z codegen-backend        </tspan><tspan>  Enable the `codegen-backend` option in profiles in .cargo/config.toml file</tspan>
+    <tspan x="10px" y="208px"><tspan>    -Z codegen-backend          Enable the `codegen-backend` option in profiles in .cargo/config.toml file</tspan>
 </tspan>
-    <tspan x="10px" y="226px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z config-include         </tspan><tspan>  Enable the `include` key in config files</tspan>
+    <tspan x="10px" y="226px"><tspan>    -Z config-include           Enable the `include` key in config files</tspan>
 </tspan>
-    <tspan x="10px" y="244px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z direct-minimal-versions</tspan><tspan>  Resolve minimal dependency versions instead of maximum (direct dependencies only)</tspan>
+    <tspan x="10px" y="244px"><tspan>    -Z direct-minimal-versions  Resolve minimal dependency versions instead of maximum (direct dependencies only)</tspan>
 </tspan>
-    <tspan x="10px" y="262px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z doctest-xcompile       </tspan><tspan>  Compile and run doctests for non-host target using runner config</tspan>
+    <tspan x="10px" y="262px"><tspan>    -Z doctest-xcompile         Compile and run doctests for non-host target using runner config</tspan>
 </tspan>
-    <tspan x="10px" y="280px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z dual-proc-macros       </tspan><tspan>  Build proc-macros for both the host and the target</tspan>
+    <tspan x="10px" y="280px"><tspan>    -Z dual-proc-macros         Build proc-macros for both the host and the target</tspan>
 </tspan>
-    <tspan x="10px" y="298px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z gc                     </tspan><tspan>  Track cache usage and "garbage collect" unused files</tspan>
+    <tspan x="10px" y="298px"><tspan>    -Z gc                       Track cache usage and "garbage collect" unused files</tspan>
 </tspan>
-    <tspan x="10px" y="316px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z git                    </tspan><tspan>  Enable support for shallow git fetch operations</tspan>
+    <tspan x="10px" y="316px"><tspan>    -Z git                      Enable support for shallow git fetch operations</tspan>
 </tspan>
-    <tspan x="10px" y="334px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z gitoxide               </tspan><tspan>  Use gitoxide for the given git interactions, or all of them if no argument is given</tspan>
+    <tspan x="10px" y="334px"><tspan>    -Z gitoxide                 Use gitoxide for the given git interactions, or all of them if no argument is given</tspan>
 </tspan>
-    <tspan x="10px" y="352px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z host-config            </tspan><tspan>  Enable the `[host]` section in the .cargo/config.toml file</tspan>
+    <tspan x="10px" y="352px"><tspan>    -Z host-config              Enable the `[host]` section in the .cargo/config.toml file</tspan>
 </tspan>
-    <tspan x="10px" y="370px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z minimal-versions       </tspan><tspan>  Resolve minimal dependency versions instead of maximum</tspan>
+    <tspan x="10px" y="370px"><tspan>    -Z minimal-versions         Resolve minimal dependency versions instead of maximum</tspan>
 </tspan>
-    <tspan x="10px" y="388px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z msrv-policy            </tspan><tspan>  Enable rust-version aware policy within cargo</tspan>
+    <tspan x="10px" y="388px"><tspan>    -Z msrv-policy              Enable rust-version aware policy within cargo</tspan>
 </tspan>
-    <tspan x="10px" y="406px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z mtime-on-use           </tspan><tspan>  Configure Cargo to update the mtime of used files</tspan>
+    <tspan x="10px" y="406px"><tspan>    -Z mtime-on-use             Configure Cargo to update the mtime of used files</tspan>
 </tspan>
-    <tspan x="10px" y="424px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z no-index-update        </tspan><tspan>  Do not update the registry index even if the cache is outdated</tspan>
+    <tspan x="10px" y="424px"><tspan>    -Z no-index-update          Do not update the registry index even if the cache is outdated</tspan>
 </tspan>
-    <tspan x="10px" y="442px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z panic-abort-tests      </tspan><tspan>  Enable support to run tests with -Cpanic=abort</tspan>
+    <tspan x="10px" y="442px"><tspan>    -Z panic-abort-tests        Enable support to run tests with -Cpanic=abort</tspan>
 </tspan>
-    <tspan x="10px" y="460px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z profile-rustflags      </tspan><tspan>  Enable the `rustflags` option in profiles in .cargo/config.toml file</tspan>
+    <tspan x="10px" y="460px"><tspan>    -Z profile-rustflags        Enable the `rustflags` option in profiles in .cargo/config.toml file</tspan>
 </tspan>
-    <tspan x="10px" y="478px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z public-dependency      </tspan><tspan>  Respect a dependency's `public` field in Cargo.toml to control public/private dependencies</tspan>
+    <tspan x="10px" y="478px"><tspan>    -Z public-dependency        Respect a dependency's `public` field in Cargo.toml to control public/private dependencies</tspan>
 </tspan>
-    <tspan x="10px" y="496px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z publish-timeout        </tspan><tspan>  Enable the `publish.timeout` key in .cargo/config.toml file</tspan>
+    <tspan x="10px" y="496px"><tspan>    -Z publish-timeout          Enable the `publish.timeout` key in .cargo/config.toml file</tspan>
 </tspan>
-    <tspan x="10px" y="514px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z rustdoc-map            </tspan><tspan>  Allow passing external documentation mappings to rustdoc</tspan>
+    <tspan x="10px" y="514px"><tspan>    -Z rustdoc-map              Allow passing external documentation mappings to rustdoc</tspan>
 </tspan>
-    <tspan x="10px" y="532px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z rustdoc-scrape-examples</tspan><tspan>  Allows Rustdoc to scrape code examples from reverse-dependencies</tspan>
+    <tspan x="10px" y="532px"><tspan>    -Z rustdoc-scrape-examples  Allows Rustdoc to scrape code examples from reverse-dependencies</tspan>
 </tspan>
-    <tspan x="10px" y="550px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z script                 </tspan><tspan>  Enable support for single-file, `.rs` packages</tspan>
+    <tspan x="10px" y="550px"><tspan>    -Z script                   Enable support for single-file, `.rs` packages</tspan>
 </tspan>
-    <tspan x="10px" y="568px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z target-applies-to-host </tspan><tspan>  Enable the `target-applies-to-host` key in the .cargo/config.toml file</tspan>
+    <tspan x="10px" y="568px"><tspan>    -Z target-applies-to-host   Enable the `target-applies-to-host` key in the .cargo/config.toml file</tspan>
 </tspan>
-    <tspan x="10px" y="586px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z trim-paths             </tspan><tspan>  Enable the `trim-paths` option in profiles</tspan>
+    <tspan x="10px" y="586px"><tspan>    -Z trim-paths               Enable the `trim-paths` option in profiles</tspan>
 </tspan>
-    <tspan x="10px" y="604px"><tspan>    </tspan><tspan class="fg-cyan bold">-Z unstable-options       </tspan><tspan>  Allow the usage of unstable options</tspan>
+    <tspan x="10px" y="604px"><tspan>    -Z unstable-options         Allow the usage of unstable options</tspan>
 </tspan>
     <tspan x="10px" y="622px">
 </tspan>
-    <tspan x="10px" y="640px"><tspan>Run with `</tspan><tspan class="fg-cyan bold">cargo -Z</tspan><tspan> </tspan><tspan class="fg-cyan">[FLAG] [COMMAND]</tspan><tspan>`</tspan>
+    <tspan x="10px" y="640px"><tspan>Run with `cargo -Z [FLAG] [COMMAND]`</tspan>
 </tspan>
     <tspan x="10px" y="658px">
 </tspan>
diff --git a/tests/testsuite/config_cli.rs b/tests/testsuite/config_cli.rs
index f8dcb0073..4fb8e419b 100644
--- a/tests/testsuite/config_cli.rs
+++ b/tests/testsuite/config_cli.rs
@@ -11,8 +11,12 @@ use std::{collections::HashMap, fs};
 #[cargo_test]
 fn basic() {
     // Simple example.
-    let gctx = GlobalContextBuilder::new().config_arg("foo='bar'").build();
+    let gctx = GlobalContextBuilder::new()
+        .config_arg("foo='bar'")
+        .config_arg("net.git-fetch-with-cli=true")
+        .build();
     assert_eq!(gctx.get::<String>("foo").unwrap(), "bar");
+    assert_eq!(gctx.net_config().unwrap().git_fetch_with_cli, Some(true));
 }
 
 #[cargo_test]
@@ -39,13 +43,16 @@ fn cli_priority() {
         .env("CARGO_BUILD_JOBS", "2")
         .env("CARGO_BUILD_RUSTC", "env")
         .env("CARGO_TERM_VERBOSE", "false")
+        .env("CARGO_NET_GIT_FETCH_WITH_CLI", "false")
         .config_arg("build.jobs=1")
         .config_arg("build.rustc='cli'")
         .config_arg("term.verbose=true")
+        .config_arg("net.git-fetch-with-cli=true")
         .build();
     assert_eq!(gctx.get::<i32>("build.jobs").unwrap(), 1);
     assert_eq!(gctx.get::<String>("build.rustc").unwrap(), "cli");
     assert_eq!(gctx.get::<bool>("term.verbose").unwrap(), true);
+    assert_eq!(gctx.net_config().unwrap().git_fetch_with_cli, Some(true));
 
     // Setting both term.verbose and term.quiet is invalid and is tested
     // in the run test suite.