fix: preserve linked worktree workspace labels
This commit is contained in:
parent
81f355fada
commit
e16d7d8c07
|
|
@ -4136,7 +4136,7 @@ mod tests {
|
|||
space: Some(crate::workspace::GitSpaceMetadata {
|
||||
key: "other-repo-key".into(),
|
||||
checkout_key: "/other/checkout".into(),
|
||||
label: "other".into(),
|
||||
repo_name: "other".into(),
|
||||
repo_root: "/other/repo".into(),
|
||||
is_linked_worktree: false,
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ impl App {
|
|||
source_checkout_path: space.repo_root.clone(),
|
||||
source_repo_root: space.repo_root,
|
||||
repo_key: space.key,
|
||||
repo_name: space.label,
|
||||
repo_name: space.repo_name,
|
||||
};
|
||||
return Ok(source);
|
||||
}
|
||||
|
|
@ -324,7 +324,7 @@ impl App {
|
|||
source_checkout_path: space.repo_root.clone(),
|
||||
source_repo_root: space.repo_root,
|
||||
repo_key: space.key,
|
||||
repo_name: space.label,
|
||||
repo_name: space.repo_name,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -678,7 +678,7 @@ fn worktree_source_from_space(
|
|||
source_checkout_path: source_checkout_path.clone(),
|
||||
source_repo_root: source_checkout_path,
|
||||
repo_key: space.key,
|
||||
repo_name: space.label,
|
||||
repo_name: space.repo_name,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ impl App {
|
|||
Some(crate::workspace::GitSpaceMetadata {
|
||||
key: membership.key.clone(),
|
||||
checkout_key: membership.checkout_path.display().to_string(),
|
||||
label: membership.label.clone(),
|
||||
repo_name: membership.label.clone(),
|
||||
repo_root: membership.repo_root.clone(),
|
||||
is_linked_worktree: membership.is_linked_worktree,
|
||||
})
|
||||
|
|
@ -88,7 +88,7 @@ impl App {
|
|||
}
|
||||
};
|
||||
|
||||
let repo_name = space.label.clone();
|
||||
let repo_name = space.repo_name.clone();
|
||||
let seed = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map(|duration| duration.as_micros().min(u128::from(u64::MAX)) as u64)
|
||||
|
|
@ -224,7 +224,7 @@ impl App {
|
|||
source_checkout_path,
|
||||
source_repo_root: space.repo_root,
|
||||
repo_key: space.key,
|
||||
repo_name: space.label,
|
||||
repo_name: space.repo_name,
|
||||
entries,
|
||||
selected: 0,
|
||||
query: String::new(),
|
||||
|
|
|
|||
|
|
@ -2386,7 +2386,7 @@ rows = [[{ token = "git_status", fg = "#123456" }]]
|
|||
ws.cached_git_space = Some(crate::workspace::GitSpaceMetadata {
|
||||
key: key.into(),
|
||||
checkout_key: format!("/repo/{name}"),
|
||||
label: "herdr".into(),
|
||||
repo_name: "herdr".into(),
|
||||
repo_root: std::path::PathBuf::from(format!("/repo/{name}")),
|
||||
is_linked_worktree: false,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ pub(crate) fn discover_workspace_git_identity(
|
|||
let space = git_space_metadata(cwd);
|
||||
let auto_label = space
|
||||
.as_ref()
|
||||
.map(|space| space.label.clone())
|
||||
.map(|space| self::git::automatic_workspace_label(cwd, &space.repo_root))
|
||||
.unwrap_or_else(|| fallback_label_from_cwd(cwd));
|
||||
let status_cache_key = space
|
||||
.as_ref()
|
||||
|
|
@ -1677,6 +1677,22 @@ mod tests {
|
|||
std::fs::remove_dir_all(root).expect("remove test repo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn linked_worktree_auto_label_uses_checkout_name_not_repo_name() {
|
||||
let (base, repo, checkout) =
|
||||
self::git::test_support::create_repo_with_linked_worktree("linked-auto-label");
|
||||
|
||||
let (space, auto_label, _) = discover_workspace_git_identity(&checkout);
|
||||
|
||||
assert_eq!(
|
||||
space.unwrap().repo_name,
|
||||
repo.file_name().unwrap().to_str().unwrap()
|
||||
);
|
||||
assert_eq!(auto_label, checkout.file_name().unwrap().to_str().unwrap());
|
||||
|
||||
std::fs::remove_dir_all(base).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_name_reads_cached_identity_without_rechecking_filesystem() {
|
||||
let stamp = std::time::SystemTime::now()
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use std::path::{Path, PathBuf};
|
|||
pub struct GitSpaceMetadata {
|
||||
pub key: String,
|
||||
pub checkout_key: String,
|
||||
pub label: String,
|
||||
pub repo_name: String,
|
||||
pub repo_root: PathBuf,
|
||||
pub is_linked_worktree: bool,
|
||||
}
|
||||
|
|
@ -19,13 +19,9 @@ pub struct GitWorktreeInfo {
|
|||
}
|
||||
|
||||
pub fn derive_label_from_cwd(cwd: &Path) -> String {
|
||||
if let Some(repo_root) = git_repo_root(cwd) {
|
||||
if let Some(name) = repo_root.file_name().and_then(|n| n.to_str()) {
|
||||
return name.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
fallback_label_from_cwd(cwd)
|
||||
git_repo_root(cwd)
|
||||
.map(|repo_root| automatic_workspace_label(cwd, &repo_root))
|
||||
.unwrap_or_else(|| fallback_label_from_cwd(cwd))
|
||||
}
|
||||
|
||||
pub fn fallback_label_from_cwd(cwd: &Path) -> String {
|
||||
|
|
@ -64,6 +60,14 @@ pub fn git_space_metadata(cwd: &Path) -> Option<GitSpaceMetadata> {
|
|||
Some(git_space_metadata_from_info(&info))
|
||||
}
|
||||
|
||||
pub(crate) fn automatic_workspace_label(cwd: &Path, repo_root: &Path) -> String {
|
||||
repo_root
|
||||
.file_name()
|
||||
.and_then(|name| name.to_str())
|
||||
.map(str::to_string)
|
||||
.unwrap_or_else(|| fallback_label_from_cwd(cwd))
|
||||
}
|
||||
|
||||
pub(super) fn git_space_metadata_from_info(info: &GitWorktreeInfo) -> GitSpaceMetadata {
|
||||
let key = canonicalize_best_effort_path(&info.git_common_dir)
|
||||
.display()
|
||||
|
|
@ -79,9 +83,9 @@ pub(super) fn git_space_metadata_from_info(info: &GitWorktreeInfo) -> GitSpaceMe
|
|||
{
|
||||
info.git_common_dir.parent().unwrap_or(&info.repo_root)
|
||||
} else {
|
||||
&info.repo_root
|
||||
&info.git_common_dir
|
||||
};
|
||||
let label = label_path
|
||||
let repo_name = label_path
|
||||
.file_name()
|
||||
.and_then(|name| name.to_str())
|
||||
.unwrap_or("repo")
|
||||
|
|
@ -89,7 +93,7 @@ pub(super) fn git_space_metadata_from_info(info: &GitWorktreeInfo) -> GitSpaceMe
|
|||
GitSpaceMetadata {
|
||||
key,
|
||||
checkout_key,
|
||||
label,
|
||||
repo_name,
|
||||
repo_root: info.repo_root.clone(),
|
||||
is_linked_worktree: info.is_linked_worktree,
|
||||
}
|
||||
|
|
@ -404,6 +408,29 @@ mod tests {
|
|||
std::fs::remove_dir_all(bare).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bare_source_and_linked_checkout_share_repo_name_but_not_auto_label() {
|
||||
let (base, bare, checkout) =
|
||||
crate::workspace::git::test_support::create_bare_repo_with_linked_worktree(
|
||||
"bare-linked-labels",
|
||||
);
|
||||
|
||||
let bare_space = git_space_metadata(&bare).unwrap();
|
||||
let checkout_space = git_space_metadata(&checkout).unwrap();
|
||||
let bare_auto_label = automatic_workspace_label(&bare, &bare_space.repo_root);
|
||||
let checkout_auto_label = automatic_workspace_label(&checkout, &checkout_space.repo_root);
|
||||
|
||||
assert_eq!(bare_space.key, checkout_space.key);
|
||||
assert_eq!(bare_space.repo_name, checkout_space.repo_name);
|
||||
assert_eq!(bare_auto_label, bare.file_name().unwrap().to_str().unwrap());
|
||||
assert_eq!(
|
||||
checkout_auto_label,
|
||||
checkout.file_name().unwrap().to_str().unwrap()
|
||||
);
|
||||
|
||||
std::fs::remove_dir_all(base).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn git_space_metadata_marks_bare_dot_git_repo() {
|
||||
let root = temp_test_dir("bare-dot-git");
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ mod config_tests;
|
|||
mod discovery;
|
||||
mod status;
|
||||
#[cfg(test)]
|
||||
mod test_support;
|
||||
pub(super) mod test_support;
|
||||
|
||||
pub(crate) use self::discovery::automatic_workspace_label;
|
||||
|
||||
pub use self::{
|
||||
discovery::{
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ use crate::workspace::{GitSpaceMetadata, WorkspaceGitStatusSnapshot};
|
|||
use super::{
|
||||
config::{read_branch_config, upstream_full_ref},
|
||||
discovery::{
|
||||
canonicalize_best_effort_path, fallback_label_from_cwd, git_ref_storage_is_reftable,
|
||||
git_rev_parse_verify, git_space_metadata_from_info, git_symbolic_head_full,
|
||||
git_worktree_info, read_ref_oid, GitWorktreeInfo,
|
||||
automatic_workspace_label, canonicalize_best_effort_path, fallback_label_from_cwd,
|
||||
git_ref_storage_is_reftable, git_rev_parse_verify, git_space_metadata_from_info,
|
||||
git_symbolic_head_full, git_worktree_info, read_ref_oid, GitWorktreeInfo,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -111,8 +111,8 @@ pub fn git_status_snapshot_for_cwd_with_demand(
|
|||
}),
|
||||
);
|
||||
};
|
||||
let auto_label = automatic_workspace_label(cwd, &info.repo_root);
|
||||
let space = git_space_metadata_from_info(&info);
|
||||
let auto_label = space.label.clone();
|
||||
|
||||
if !demand.ahead_behind {
|
||||
let branch = demand
|
||||
|
|
@ -529,6 +529,23 @@ mod tests {
|
|||
std::fs::remove_dir_all(root).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn linked_worktree_refresh_keeps_checkout_name_as_auto_label() {
|
||||
let (base, _, checkout) =
|
||||
crate::workspace::git::test_support::create_repo_with_linked_worktree(
|
||||
"linked-refresh-label",
|
||||
);
|
||||
|
||||
let (snapshot, _) = git_status_snapshot_for_cwd(&checkout, None);
|
||||
|
||||
assert_eq!(
|
||||
snapshot.auto_label,
|
||||
checkout.file_name().unwrap().to_str().unwrap()
|
||||
);
|
||||
|
||||
std::fs::remove_dir_all(base).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn git_status_cache_key_is_per_linked_worktree_checkout() {
|
||||
let base = temp_test_dir("linked-worktree-keys");
|
||||
|
|
|
|||
|
|
@ -16,6 +16,68 @@ pub(super) fn temp_test_dir(name: &str) -> PathBuf {
|
|||
path
|
||||
}
|
||||
|
||||
fn init_repo_with_commit(repo: &Path) {
|
||||
std::fs::create_dir_all(repo).unwrap();
|
||||
run_git(repo, &["init", "--quiet"]);
|
||||
run_git(repo, &["config", "user.email", "herdr@example.invalid"]);
|
||||
run_git(repo, &["config", "user.name", "Herdr Test"]);
|
||||
run_git(
|
||||
repo,
|
||||
&["commit", "--quiet", "--allow-empty", "-m", "initial"],
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn create_repo_with_linked_worktree(name: &str) -> (PathBuf, PathBuf, PathBuf) {
|
||||
let base = temp_test_dir(name);
|
||||
let repo = base.join("herdr");
|
||||
let checkout = base.join("testr56");
|
||||
init_repo_with_commit(&repo);
|
||||
run_git(
|
||||
&repo,
|
||||
&[
|
||||
"worktree",
|
||||
"add",
|
||||
"--quiet",
|
||||
"-b",
|
||||
"testr56",
|
||||
checkout.to_str().unwrap(),
|
||||
"HEAD",
|
||||
],
|
||||
);
|
||||
(base, repo, checkout)
|
||||
}
|
||||
|
||||
pub(crate) fn create_bare_repo_with_linked_worktree(name: &str) -> (PathBuf, PathBuf, PathBuf) {
|
||||
let base = temp_test_dir(name);
|
||||
let seed = base.join("seed");
|
||||
let bare = base.join("herdr.git");
|
||||
let checkout = base.join("feature");
|
||||
init_repo_with_commit(&seed);
|
||||
run_git(
|
||||
&base,
|
||||
&[
|
||||
"clone",
|
||||
"--quiet",
|
||||
"--bare",
|
||||
seed.to_str().unwrap(),
|
||||
bare.to_str().unwrap(),
|
||||
],
|
||||
);
|
||||
run_git(
|
||||
&bare,
|
||||
&[
|
||||
"worktree",
|
||||
"add",
|
||||
"--quiet",
|
||||
"-b",
|
||||
"feature",
|
||||
checkout.to_str().unwrap(),
|
||||
"HEAD",
|
||||
],
|
||||
);
|
||||
(base, bare, checkout)
|
||||
}
|
||||
|
||||
pub(super) fn write_fake_tracked_repo(root: &Path) {
|
||||
let head_oid = "1111111111111111111111111111111111111111";
|
||||
let upstream_oid = "2222222222222222222222222222222222222222";
|
||||
|
|
|
|||
Loading…
Reference in New Issue