diff --git a/src/bin/cargo/commands/install.rs b/src/bin/cargo/commands/install.rs index b26c0cc6d4a..07edfb0c1e0 100644 --- a/src/bin/cargo/commands/install.rs +++ b/src/bin/cargo/commands/install.rs @@ -139,7 +139,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { } else if let Some(rev) = args.value_of("rev") { GitReference::Rev(rev.to_string()) } else { - GitReference::Branch("master".to_string()) + GitReference::DefaultBranch }; SourceId::for_git(&url, gitref)? } else if let Some(path) = args.value_of_path("path", config) { diff --git a/src/cargo/core/source/source_id.rs b/src/cargo/core/source/source_id.rs index d54b1f4fb0a..a493a18072c 100644 --- a/src/cargo/core/source/source_id.rs +++ b/src/cargo/core/source/source_id.rs @@ -63,10 +63,12 @@ enum SourceKind { pub enum GitReference { /// From a tag. Tag(String), - /// From the HEAD of a branch. + /// From a branch. Branch(String), /// From a specific revision. Rev(String), + /// The default branch of the repository, the reference named `HEAD`. + DefaultBranch, } impl SourceId { @@ -114,7 +116,7 @@ impl SourceId { match kind { "git" => { let mut url = url.into_url()?; - let mut reference = GitReference::Branch("master".to_string()); + let mut reference = GitReference::DefaultBranch; for (k, v) in url.query_pairs() { match &k[..] { // Map older 'ref' to branch. @@ -549,10 +551,10 @@ impl<'a> fmt::Display for SourceIdIntoUrl<'a> { impl GitReference { /// Returns a `Display`able view of this git reference, or None if using - /// the head of the "master" branch + /// the head of the default branch pub fn pretty_ref(&self) -> Option> { match *self { - GitReference::Branch(ref s) if *s == "master" => None, + GitReference::DefaultBranch => None, _ => Some(PrettyRef { inner: self }), } } @@ -569,6 +571,7 @@ impl<'a> fmt::Display for PrettyRef<'a> { GitReference::Branch(ref b) => write!(f, "branch={}", b), GitReference::Tag(ref s) => write!(f, "tag={}", s), GitReference::Rev(ref s) => write!(f, "rev={}", s), + GitReference::DefaultBranch => unreachable!(), } } } @@ -581,11 +584,11 @@ mod tests { #[test] fn github_sources_equal() { let loc = "https://github.com/foo/bar".into_url().unwrap(); - let master = SourceKind::Git(GitReference::Branch("master".to_string())); - let s1 = SourceId::new(master.clone(), loc).unwrap(); + let default = SourceKind::Git(GitReference::DefaultBranch); + let s1 = SourceId::new(default.clone(), loc).unwrap(); let loc = "git://github.com/foo/bar".into_url().unwrap(); - let s2 = SourceId::new(master, loc.clone()).unwrap(); + let s2 = SourceId::new(default, loc.clone()).unwrap(); assert_eq!(s1, s2); diff --git a/src/cargo/ops/vendor.rs b/src/cargo/ops/vendor.rs index 2c446fa1639..3b087f6e37c 100644 --- a/src/cargo/ops/vendor.rs +++ b/src/cargo/ops/vendor.rs @@ -275,6 +275,7 @@ fn sync( GitReference::Branch(ref b) => branch = Some(b.clone()), GitReference::Tag(ref t) => tag = Some(t.clone()), GitReference::Rev(ref r) => rev = Some(r.clone()), + GitReference::DefaultBranch => {} } } VendorSource::Git { diff --git a/src/cargo/sources/config.rs b/src/cargo/sources/config.rs index b64d073025a..71a9a7194c0 100644 --- a/src/cargo/sources/config.rs +++ b/src/cargo/sources/config.rs @@ -225,7 +225,7 @@ restore the source replacement configuration to continue the build Some(b) => GitReference::Tag(b.val), None => match def.rev { Some(b) => GitReference::Rev(b.val), - None => GitReference::Branch("master".to_string()), + None => GitReference::DefaultBranch, }, }, }; diff --git a/src/cargo/sources/git/source.rs b/src/cargo/sources/git/source.rs index be8dd4dd2e8..7f8134ca373 100644 --- a/src/cargo/sources/git/source.rs +++ b/src/cargo/sources/git/source.rs @@ -261,10 +261,6 @@ mod test { } fn src(s: &str) -> SourceId { - SourceId::for_git( - &s.into_url().unwrap(), - GitReference::Branch("master".to_string()), - ) - .unwrap() + SourceId::for_git(&s.into_url().unwrap(), GitReference::DefaultBranch).unwrap() } } diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs index 53bda10f3bd..9e23cd1d3e3 100644 --- a/src/cargo/sources/git/utils.rs +++ b/src/cargo/sources/git/utils.rs @@ -250,6 +250,14 @@ impl GitReference { .target() .ok_or_else(|| anyhow::format_err!("branch `{}` did not have a target", s))? } + GitReference::DefaultBranch => { + let refname = "refs/remotes/origin/HEAD"; + let id = repo.refname_to_id(refname)?; + let obj = repo.find_object(id, None)?; + let obj = obj.peel(ObjectType::Commit)?; + obj.id() + } + GitReference::Rev(s) => { let obj = repo.revparse_single(s)?; match obj.as_tag() { @@ -734,11 +742,16 @@ pub fn fetch( refspecs.push(format!("refs/tags/{0}:refs/remotes/origin/tags/{0}", t)); } + GitReference::DefaultBranch => { + refspecs.push(format!("HEAD:refs/remotes/origin/HEAD")); + } + // For `rev` dependencies we don't know what the rev will point to. To // handle this situation we fetch all branches and tags, and then we // pray it's somewhere in there. GitReference::Rev(_) => { refspecs.push(format!("refs/heads/*:refs/remotes/origin/*")); + refspecs.push(format!("HEAD:refs/remotes/origin/HEAD")); tags = true; } } @@ -957,6 +970,7 @@ fn github_up_to_date( let github_branch_name = match reference { GitReference::Branch(branch) => branch, GitReference::Tag(tag) => tag, + GitReference::DefaultBranch => "HEAD", GitReference::Rev(_) => { debug!("can't use github fast path with `rev`"); return Ok(false); diff --git a/src/cargo/sources/registry/remote.rs b/src/cargo/sources/registry/remote.rs index 6f1ae1e58dd..9c610ae82ab 100644 --- a/src/cargo/sources/registry/remote.rs +++ b/src/cargo/sources/registry/remote.rs @@ -48,7 +48,7 @@ impl<'cfg> RemoteRegistry<'cfg> { source_id, config, // TODO: we should probably make this configurable - index_git_ref: GitReference::Branch("master".to_string()), + index_git_ref: GitReference::DefaultBranch, tree: RefCell::new(None), repo: LazyCell::new(), head: Cell::new(None), diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index c88de42142a..fe56383875e 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -1686,7 +1686,7 @@ impl DetailedTomlDependency { .map(GitReference::Branch) .or_else(|| self.tag.clone().map(GitReference::Tag)) .or_else(|| self.rev.clone().map(GitReference::Rev)) - .unwrap_or_else(|| GitReference::Branch("master".to_string())); + .unwrap_or_else(|| GitReference::DefaultBranch); let loc = git.into_url()?; if let Some(fragment) = loc.fragment() { diff --git a/src/doc/src/reference/specifying-dependencies.md b/src/doc/src/reference/specifying-dependencies.md index a55467bc29f..72ee9851e49 100644 --- a/src/doc/src/reference/specifying-dependencies.md +++ b/src/doc/src/reference/specifying-dependencies.md @@ -137,7 +137,7 @@ Cargo will fetch the `git` repository at this location then look for a of a workspace and setting `git` to the repository containing the workspace). Since we haven’t specified any other information, Cargo assumes that -we intend to use the latest commit on the `master` branch to build our package. +we intend to use the latest commit on the main branch to build our package. You can combine the `git` key with the `rev`, `tag`, or `branch` keys to specify something else. Here's an example of specifying that you want to use the latest commit on a branch named `next`: diff --git a/tests/build-std/main.rs b/tests/build-std/main.rs index 6a16e39db42..d5aa6ca54b8 100644 --- a/tests/build-std/main.rs +++ b/tests/build-std/main.rs @@ -25,7 +25,6 @@ use std::path::Path; fn enable_build_std(e: &mut Execs, arg: Option<&str>) { e.env_remove("CARGO_HOME"); e.env_remove("HOME"); - e.arg("-Zno-index-update"); // And finally actually enable `build-std` for now let arg = match arg { diff --git a/tests/testsuite/git.rs b/tests/testsuite/git.rs index 2feab38884b..212869af8bc 100644 --- a/tests/testsuite/git.rs +++ b/tests/testsuite/git.rs @@ -2784,3 +2784,51 @@ to proceed despite [..] git::commit(&repo); git_project.cargo("package --no-verify").run(); } + +#[cargo_test] +fn default_not_master() { + let project = project(); + + // Create a repository with a `master` branch ... + let (git_project, repo) = git::new_repo("dep1", |project| { + project.file("Cargo.toml", &basic_lib_manifest("dep1")) + }); + + // Then create a `main` branch with actual code, and set the head of the + // repository (default branch) to `main`. + git_project.change_file("src/lib.rs", "pub fn foo() {}"); + git::add(&repo); + let rev = git::commit(&repo); + let commit = repo.find_commit(rev).unwrap(); + repo.branch("main", &commit, false).unwrap(); + repo.set_head("refs/heads/main").unwrap(); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [project] + name = "foo" + version = "0.5.0" + + [dependencies] + dep1 = {{ git = '{}' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "pub fn foo() { dep1::foo() }") + .build(); + + project + .cargo("build") + .with_stderr( + "\ +[UPDATING] git repository `[..]` +[COMPILING] dep1 v0.5.0 ([..]) +[COMPILING] foo v0.5.0 ([..]) +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]", + ) + .run(); +}