cli: correctly update to remote's default branch after clone

It turns out that `FETCH_HEAD` is not the remote's `HEAD` (it's
actually not even a normal symbolic ref; it contains many lines of
commits and names). We're supposed to ask the remote for its default
branch instead. That's what this patch does.
This commit is contained in:
Martin von Zweigbergk 2021-09-13 22:01:56 -07:00
parent ce5e95fa80
commit 48f237e33e
2 changed files with 30 additions and 14 deletions

View File

@ -127,7 +127,7 @@ pub fn fetch(
mut_repo: &mut MutableRepo,
git_repo: &git2::Repository,
remote_name: &str,
) -> Result<(), GitFetchError> {
) -> Result<Option<String>, GitFetchError> {
let mut remote =
git_repo
.find_remote(remote_name)
@ -149,10 +149,22 @@ pub fn fetch(
fetch_options.prune(FetchPrune::On);
let refspec: &[&str] = &[];
remote.fetch(refspec, Some(&mut fetch_options), None)?;
// TODO: We could make it optional to get the default branch since we only care
// about it on clone.
let mut default_branch = None;
if let Ok(default_ref_buf) = remote.default_branch() {
if let Some(default_ref) = default_ref_buf.as_str() {
// LocalBranch here is the local branch on the remote, so it's really the remote
// branch
if let Some(RefName::LocalBranch(branch_name)) = parse_git_ref(default_ref) {
default_branch = Some(branch_name);
}
}
}
import_refs(mut_repo, git_repo).map_err(|err| match err {
GitImportError::InternalGitError(source) => GitFetchError::InternalGitError(source),
})?;
Ok(())
Ok(default_branch)
}
#[derive(Error, Debug, PartialEq)]

View File

@ -3271,18 +3271,22 @@ fn cmd_git_clone(
let remote_name = "origin";
git_repo.remote(remote_name, source).unwrap();
let mut tx = repo.start_transaction("fetch from git remote into empty repo");
git::fetch(tx.mut_repo(), &git_repo, remote_name).map_err(|err| match err {
GitFetchError::NoSuchRemote(_) => {
panic!("should't happen as we just created the git remote")
}
GitFetchError::InternalGitError(err) => {
CommandError::UserError(format!("Fetch failed: {:?}", err))
}
})?;
if let Ok(fetch_head_ref) = git_repo.find_reference("FETCH_HEAD") {
if let Ok(fetch_head_git_commit) = fetch_head_ref.peel_to_commit() {
let fetch_head_id = CommitId(fetch_head_git_commit.id().as_bytes().to_vec());
if let Ok(fetch_head_commit) = repo.store().get_commit(&fetch_head_id) {
let maybe_default_branch =
git::fetch(tx.mut_repo(), &git_repo, remote_name).map_err(|err| match err {
GitFetchError::NoSuchRemote(_) => {
panic!("should't happen as we just created the git remote")
}
GitFetchError::InternalGitError(err) => {
CommandError::UserError(format!("Fetch failed: {:?}", err))
}
})?;
if let Some(default_branch) = maybe_default_branch {
let default_branch_target = tx
.mut_repo()
.view()
.get_remote_branch(&default_branch, "origin");
if let Some(RefTarget::Normal(commit_id)) = default_branch_target {
if let Ok(fetch_head_commit) = repo.store().get_commit(&commit_id) {
tx.mut_repo().check_out(ui.settings(), &fetch_head_commit);
}
}