Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(dotgit): set publicheads correctly for transparent git mode #969

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 45 additions & 8 deletions eden/scm/lib/gitcompat/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This performs a network call, which might be unexpected or undesirable.

How about parsing the output of git rev-parse --symbolic refs/remotes/origin/HEAD instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea! If it's as robust as ls-remote then this will save a network call.

Copy link
Contributor

@quark-zju quark-zju Oct 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use lookup_reference to resolve the reference without the spawning process overhead.

.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
Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -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<String> {
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::*;
Expand All @@ -148,16 +175,22 @@ 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]
# from git config: user.name and user.email
username = Foo Bar <foorbar@example.com>
"#
);
assert_eq!(
repo,
let got = repo;
let want =
r#"[paths]
# from git config: remote.origin.url
default = https://example.com/foo/repo
Expand All @@ -169,8 +202,12 @@ upstream = https://example.com/upstream/repo
[ui]
# from git config: user.name and user.email
username = Foo Bar <foo@bar.net>
"#
);

[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]
Expand Down
15 changes: 11 additions & 4 deletions eden/scm/tests/test-git-clone-sets-publicheads.t
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading