diff --git a/eden/scm/lib/gitcompat/src/config.rs b/eden/scm/lib/gitcompat/src/config.rs index f2c40b1302345..2421b46a05ebc 100644 --- a/eden/scm/lib/gitcompat/src/config.rs +++ b/eden/scm/lib/gitcompat/src/config.rs @@ -22,12 +22,17 @@ impl GlobalGit { &["--show-scope", "--get-regexp", "^(remote|user)\\."], ) .output()?; - let out = String::from_utf8(out.stdout)?; - Ok(translate_git_config_output(&out)) + let config = String::from_utf8(out.stdout)?; + let remotes_out = self + .git_cmd( + "ls-remote", &["--symref", ".", "HEAD"]) + .output()?; + let remotes = String::from_utf8(remotes_out.stdout)?; + Ok(translate_git_config_output(&config, &remotes)) } } -fn translate_git_config_output(out: &str) -> (String, String) { +fn translate_git_config_output(out: &str, remotes: &str) -> (String, String) { // Example output: // global user.name Foo Bar // global user.email foo@example.com @@ -94,6 +99,16 @@ fn translate_git_config_output(out: &str) -> (String, String) { )); } + let default_publicheads = "origin/master,origin/main"; + if let Some(default_branch) = parse_symref_head(remotes) { + repo_config.push_str(&format!( + "\n[remotenames]\n# from git ls-remote\npublicheads=origin/{},{}\n", + default_branch, + default_publicheads, + )); + } + + (user_config, repo_config) } @@ -135,6 +150,18 @@ fn parse_git_config_output_line(line: &str) -> Option<(&str, &str, &str)> { Some((scope, name, value)) } +fn parse_symref_head(lines: &str) -> Option { + for line in lines.lines() { + // example: "ref: refs/heads/defaultbranch HEAD" + let prefix = "ref: refs/heads/"; + let suffix = "\tHEAD"; + if line.starts_with(prefix) && line.match_indices(suffix).count() ==1 { + return Some(line[prefix.len()..line.len()-suffix.len()].to_string()); + } + } + return None +} + #[cfg(test)] mod tests { use super::*; @@ -148,7 +175,13 @@ local remote.origin.pushurl git@example.com:foo/repo local remote.upstream.url https://example.com/upstream/repo local user.email foo@bar.net "#; - let (user, repo) = translate_git_config_output(out); + let remotes = r#" +ref: refs/heads/defaultbranch HEAD +4661e74b5ebe8727d1b0f8c29b1697f1f42daf70 HEAD +ref: refs/remotes/origin/defaultbranch refs/remotes/origin/HEAD +4661e74b5ebe8727d1b0f8c29b1697f1f42daf70 refs/remotes/origin/HEAD + "#; + let (user, repo) = translate_git_config_output(out, remotes); assert_eq!( user, r#"[ui] @@ -156,8 +189,8 @@ local user.email foo@bar.net username = Foo Bar "# ); - assert_eq!( - repo, + let got = repo; + let want = r#"[paths] # from git config: remote.origin.url default = https://example.com/foo/repo @@ -169,8 +202,12 @@ upstream = https://example.com/upstream/repo [ui] # from git config: user.name and user.email username = Foo Bar -"# - ); + +[remotenames] +# from git ls-remote +publicheads=origin/defaultbranch,origin/master,origin/main +"#; + assert_eq!(got, want, "\n expanded left: {got}\n------------\nexpanded right: {want}\n"); } #[test] diff --git a/eden/scm/tests/test-git-clone-sets-publicheads.t b/eden/scm/tests/test-git-clone-sets-publicheads.t index ec14dda30871c..de6cfa49e7f46 100644 --- a/eden/scm/tests/test-git-clone-sets-publicheads.t +++ b/eden/scm/tests/test-git-clone-sets-publicheads.t @@ -18,11 +18,18 @@ Prepare a git repo: $ git add beta $ git commit -q -mbeta -Test git clone sets publicheads - $ hg clone --git "$TESTTMP/gitrepo" cloned + +Test hg clone sets publicheads + $ hg clone --git "$TESTTMP/gitrepo" cloned-hg From $TESTTMP/gitrepo * [new ref] 3f5848713286c67b8a71a450e98c7fa66787bde2 -> remote/foo 2 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cd cloned - $ hg config remotenames.publicheads + $ (cd cloned-hg && hg config remotenames.publicheads) remote/foo,remote/main,remote/master + +Test git clone sets publicheads + $ git clone "$TESTTMP/gitrepo" cloned-git + Cloning into 'cloned-git'... + done. + $ (cd cloned-git && hg config remotenames.publicheads ) + origin/foo,origin/master,origin/main