aboutsummaryrefslogtreecommitdiff
path: root/src/workspace/git
diff options
context:
space:
mode:
Diffstat (limited to 'src/workspace/git')
-rw-r--r--src/workspace/git/discovery.rs49
-rw-r--r--src/workspace/git/mod.rs4
-rw-r--r--src/workspace/git/status.rs25
-rw-r--r--src/workspace/git/test_support.rs62
4 files changed, 124 insertions, 16 deletions
diff --git a/src/workspace/git/discovery.rs b/src/workspace/git/discovery.rs
index 9e1be74d..3e867443 100644
--- a/src/workspace/git/discovery.rs
+++ b/src/workspace/git/discovery.rs
@@ -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,
}
@@ -405,6 +409,29 @@ mod tests {
}
#[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");
run_git(&root, &["init", "--bare", ".git"]);
diff --git a/src/workspace/git/mod.rs b/src/workspace/git/mod.rs
index 87a6b06e..b00cf3b3 100644
--- a/src/workspace/git/mod.rs
+++ b/src/workspace/git/mod.rs
@@ -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::{
diff --git a/src/workspace/git/status.rs b/src/workspace/git/status.rs
index fe873e29..dcfc1aff 100644
--- a/src/workspace/git/status.rs
+++ b/src/workspace/git/status.rs
@@ -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
@@ -530,6 +530,23 @@ mod tests {
}
#[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");
let common_dir = base.join("repo/.git");
diff --git a/src/workspace/git/test_support.rs b/src/workspace/git/test_support.rs
index feba4b3a..01996782 100644
--- a/src/workspace/git/test_support.rs
+++ b/src/workspace/git/test_support.rs
@@ -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";