Skip to content

Commit f2aba14

Browse files
committed
Auto merge of #8364 - alexcrichton:default-no-master, r=ehuss
Improve support for non-`master` main branches This commit improves Cargo's support for git repositories whose "main branch" is not called `master`. Cargo currently pretty liberally assumes that if nothing else about a git repository is specified then `master` is the branch name to use. Instead now Cargo has a fourth option as the desired reference of a repository named `DefaultBranch`. Cargo doesn't know anything about the actual name of the default branch, it just updates how git references are fetched internally. This commit is motivated by news that GitHub is likely to switch away from the default branch being named `master` in the near future. It would be a bit of a bummer if from now on everyone had to type `branch = '...'`, so this tries to improve that! Closes #3517
2 parents 39b48d5 + 4c02977 commit f2aba14

File tree

11 files changed

+79
-18
lines changed

11 files changed

+79
-18
lines changed

src/bin/cargo/commands/install.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
140140
} else if let Some(rev) = args.value_of("rev") {
141141
GitReference::Rev(rev.to_string())
142142
} else {
143-
GitReference::Branch("master".to_string())
143+
GitReference::DefaultBranch
144144
};
145145
SourceId::for_git(&url, gitref)?
146146
} else if let Some(path) = args.value_of_path("path", config) {

src/cargo/core/source/source_id.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,12 @@ enum SourceKind {
6363
pub enum GitReference {
6464
/// From a tag.
6565
Tag(String),
66-
/// From the HEAD of a branch.
66+
/// From a branch.
6767
Branch(String),
6868
/// From a specific revision.
6969
Rev(String),
70+
/// The default branch of the repository, the reference named `HEAD`.
71+
DefaultBranch,
7072
}
7173

7274
impl SourceId {
@@ -114,7 +116,7 @@ impl SourceId {
114116
match kind {
115117
"git" => {
116118
let mut url = url.into_url()?;
117-
let mut reference = GitReference::Branch("master".to_string());
119+
let mut reference = GitReference::DefaultBranch;
118120
for (k, v) in url.query_pairs() {
119121
match &k[..] {
120122
// Map older 'ref' to branch.
@@ -549,10 +551,10 @@ impl<'a> fmt::Display for SourceIdIntoUrl<'a> {
549551

550552
impl GitReference {
551553
/// Returns a `Display`able view of this git reference, or None if using
552-
/// the head of the "master" branch
554+
/// the head of the default branch
553555
pub fn pretty_ref(&self) -> Option<PrettyRef<'_>> {
554556
match *self {
555-
GitReference::Branch(ref s) if *s == "master" => None,
557+
GitReference::DefaultBranch => None,
556558
_ => Some(PrettyRef { inner: self }),
557559
}
558560
}
@@ -569,6 +571,7 @@ impl<'a> fmt::Display for PrettyRef<'a> {
569571
GitReference::Branch(ref b) => write!(f, "branch={}", b),
570572
GitReference::Tag(ref s) => write!(f, "tag={}", s),
571573
GitReference::Rev(ref s) => write!(f, "rev={}", s),
574+
GitReference::DefaultBranch => unreachable!(),
572575
}
573576
}
574577
}
@@ -581,11 +584,11 @@ mod tests {
581584
#[test]
582585
fn github_sources_equal() {
583586
let loc = "https://github.com/foo/bar".into_url().unwrap();
584-
let master = SourceKind::Git(GitReference::Branch("master".to_string()));
585-
let s1 = SourceId::new(master.clone(), loc).unwrap();
587+
let default = SourceKind::Git(GitReference::DefaultBranch);
588+
let s1 = SourceId::new(default.clone(), loc).unwrap();
586589

587590
let loc = "git://github.com/foo/bar".into_url().unwrap();
588-
let s2 = SourceId::new(master, loc.clone()).unwrap();
591+
let s2 = SourceId::new(default, loc.clone()).unwrap();
589592

590593
assert_eq!(s1, s2);
591594

src/cargo/ops/vendor.rs

+1
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ fn sync(
275275
GitReference::Branch(ref b) => branch = Some(b.clone()),
276276
GitReference::Tag(ref t) => tag = Some(t.clone()),
277277
GitReference::Rev(ref r) => rev = Some(r.clone()),
278+
GitReference::DefaultBranch => {}
278279
}
279280
}
280281
VendorSource::Git {

src/cargo/sources/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ restore the source replacement configuration to continue the build
225225
Some(b) => GitReference::Tag(b.val),
226226
None => match def.rev {
227227
Some(b) => GitReference::Rev(b.val),
228-
None => GitReference::Branch("master".to_string()),
228+
None => GitReference::DefaultBranch,
229229
},
230230
},
231231
};

src/cargo/sources/git/source.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,6 @@ mod test {
261261
}
262262

263263
fn src(s: &str) -> SourceId {
264-
SourceId::for_git(
265-
&s.into_url().unwrap(),
266-
GitReference::Branch("master".to_string()),
267-
)
268-
.unwrap()
264+
SourceId::for_git(&s.into_url().unwrap(), GitReference::DefaultBranch).unwrap()
269265
}
270266
}

src/cargo/sources/git/utils.rs

+14
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,14 @@ impl GitReference {
250250
.target()
251251
.ok_or_else(|| anyhow::format_err!("branch `{}` did not have a target", s))?
252252
}
253+
GitReference::DefaultBranch => {
254+
let refname = "refs/remotes/origin/HEAD";
255+
let id = repo.refname_to_id(refname)?;
256+
let obj = repo.find_object(id, None)?;
257+
let obj = obj.peel(ObjectType::Commit)?;
258+
obj.id()
259+
}
260+
253261
GitReference::Rev(s) => {
254262
let obj = repo.revparse_single(s)?;
255263
match obj.as_tag() {
@@ -734,11 +742,16 @@ pub fn fetch(
734742
refspecs.push(format!("refs/tags/{0}:refs/remotes/origin/tags/{0}", t));
735743
}
736744

745+
GitReference::DefaultBranch => {
746+
refspecs.push(format!("HEAD:refs/remotes/origin/HEAD"));
747+
}
748+
737749
// For `rev` dependencies we don't know what the rev will point to. To
738750
// handle this situation we fetch all branches and tags, and then we
739751
// pray it's somewhere in there.
740752
GitReference::Rev(_) => {
741753
refspecs.push(format!("refs/heads/*:refs/remotes/origin/*"));
754+
refspecs.push(format!("HEAD:refs/remotes/origin/HEAD"));
742755
tags = true;
743756
}
744757
}
@@ -957,6 +970,7 @@ fn github_up_to_date(
957970
let github_branch_name = match reference {
958971
GitReference::Branch(branch) => branch,
959972
GitReference::Tag(tag) => tag,
973+
GitReference::DefaultBranch => "HEAD",
960974
GitReference::Rev(_) => {
961975
debug!("can't use github fast path with `rev`");
962976
return Ok(false);

src/cargo/sources/registry/remote.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl<'cfg> RemoteRegistry<'cfg> {
4848
source_id,
4949
config,
5050
// TODO: we should probably make this configurable
51-
index_git_ref: GitReference::Branch("master".to_string()),
51+
index_git_ref: GitReference::DefaultBranch,
5252
tree: RefCell::new(None),
5353
repo: LazyCell::new(),
5454
head: Cell::new(None),

src/cargo/util/toml/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1689,7 +1689,7 @@ impl DetailedTomlDependency {
16891689
.map(GitReference::Branch)
16901690
.or_else(|| self.tag.clone().map(GitReference::Tag))
16911691
.or_else(|| self.rev.clone().map(GitReference::Rev))
1692-
.unwrap_or_else(|| GitReference::Branch("master".to_string()));
1692+
.unwrap_or_else(|| GitReference::DefaultBranch);
16931693
let loc = git.into_url()?;
16941694

16951695
if let Some(fragment) = loc.fragment() {

src/doc/src/reference/specifying-dependencies.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ Cargo will fetch the `git` repository at this location then look for a
137137
of a workspace and setting `git` to the repository containing the workspace).
138138

139139
Since we haven’t specified any other information, Cargo assumes that
140-
we intend to use the latest commit on the `master` branch to build our package.
140+
we intend to use the latest commit on the main branch to build our package.
141141
You can combine the `git` key with the `rev`, `tag`, or `branch` keys to
142142
specify something else. Here's an example of specifying that you want to use
143143
the latest commit on a branch named `next`:

tests/build-std/main.rs

-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ use std::path::Path;
2525
fn enable_build_std(e: &mut Execs, arg: Option<&str>) {
2626
e.env_remove("CARGO_HOME");
2727
e.env_remove("HOME");
28-
e.arg("-Zno-index-update");
2928

3029
// And finally actually enable `build-std` for now
3130
let arg = match arg {

tests/testsuite/git.rs

+48
Original file line numberDiff line numberDiff line change
@@ -2784,3 +2784,51 @@ to proceed despite [..]
27842784
git::commit(&repo);
27852785
git_project.cargo("package --no-verify").run();
27862786
}
2787+
2788+
#[cargo_test]
2789+
fn default_not_master() {
2790+
let project = project();
2791+
2792+
// Create a repository with a `master` branch ...
2793+
let (git_project, repo) = git::new_repo("dep1", |project| {
2794+
project.file("Cargo.toml", &basic_lib_manifest("dep1"))
2795+
});
2796+
2797+
// Then create a `main` branch with actual code, and set the head of the
2798+
// repository (default branch) to `main`.
2799+
git_project.change_file("src/lib.rs", "pub fn foo() {}");
2800+
git::add(&repo);
2801+
let rev = git::commit(&repo);
2802+
let commit = repo.find_commit(rev).unwrap();
2803+
repo.branch("main", &commit, false).unwrap();
2804+
repo.set_head("refs/heads/main").unwrap();
2805+
2806+
let project = project
2807+
.file(
2808+
"Cargo.toml",
2809+
&format!(
2810+
r#"
2811+
[project]
2812+
name = "foo"
2813+
version = "0.5.0"
2814+
2815+
[dependencies]
2816+
dep1 = {{ git = '{}' }}
2817+
"#,
2818+
git_project.url()
2819+
),
2820+
)
2821+
.file("src/lib.rs", "pub fn foo() { dep1::foo() }")
2822+
.build();
2823+
2824+
project
2825+
.cargo("build")
2826+
.with_stderr(
2827+
"\
2828+
[UPDATING] git repository `[..]`
2829+
[COMPILING] dep1 v0.5.0 ([..])
2830+
[COMPILING] foo v0.5.0 ([..])
2831+
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
2832+
)
2833+
.run();
2834+
}

0 commit comments

Comments
 (0)