From 2172887876b19bd0f1b1307930f891924168e842 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Mon, 31 Oct 2022 10:00:44 -0700 Subject: [PATCH] git: don't detach head if the ref already points to the right place The first time we export to Git, we don't actually export anything. That's a little weird and I don't know why I did it that way. It seems more natural to export the current state. I'd like to change it to do that. However, that currently means we'll detach the current HEAD if it points to any of the branches we export. This patch restructures the code a bit and skips the detach step if the target branch already points to the right commit. --- lib/src/git.rs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/lib/src/git.rs b/lib/src/git.rs index 1533b53d6..c41db5544 100644 --- a/lib/src/git.rs +++ b/lib/src/git.rs @@ -182,14 +182,6 @@ pub fn export_changes( ) -> Result<(), GitExportError> { let old_branches: HashSet<_> = old_view.branches().keys().cloned().collect(); let new_branches: HashSet<_> = new_view.branches().keys().cloned().collect(); - // TODO: Check that the ref is not pointed to by any worktree's HEAD. - let mut active_branches = HashSet::new(); - if let Ok(head_ref) = git_repo.find_reference("HEAD") { - if let Some(head_target) = head_ref.symbolic_target() { - active_branches.insert(head_target.to_string()); - } - } - let mut detach_head = false; // First find the changes we want need to make and then make them all at once to // reduce the risk of making some changes before we fail. let mut refs_to_update = BTreeMap::new(); @@ -216,13 +208,18 @@ pub fn export_changes( } else { refs_to_delete.insert(git_ref_name.clone()); } - if active_branches.contains(&git_ref_name) { - detach_head = true; - } } - if detach_head { - if let Ok(head_ref) = git_repo.find_reference("HEAD") { - if let Ok(current_git_commit) = head_ref.peel_to_commit() { + // TODO: Also check other worktrees' HEAD. + if let Ok(head_ref) = git_repo.find_reference("HEAD") { + if let (Some(head_target), Ok(current_git_commit)) = + (head_ref.symbolic_target(), head_ref.peel_to_commit()) + { + let detach_head = if let Some(new_target) = refs_to_update.get(head_target) { + *new_target != current_git_commit.id() + } else { + refs_to_delete.contains(head_target) + }; + if detach_head { git_repo.set_head_detached(current_git_commit.id())?; } }