fix: derive worktree name from path, not branch name
Git worktree names are stored in .git/worktrees/<name> and cannot contain slashes. The code was using branch names like "feature/slug" or "rfc/name" as worktree names, which git2 rejects silently. Now the worktree name is derived from the path's directory name (the slug), which is always a simple identifier without slashes. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
71c3d3caa9
commit
ddce9e8b03
3 changed files with 32 additions and 8 deletions
|
|
@ -346,6 +346,13 @@ pub fn create_worktree(
|
|||
branch_name: &str,
|
||||
worktree_path: &Path,
|
||||
) -> Result<(), RepoError> {
|
||||
// Derive worktree name from path (directory name = slug, no slashes)
|
||||
// Git worktree names are stored in .git/worktrees/<name> and cannot contain slashes
|
||||
let worktree_name = worktree_path
|
||||
.file_name()
|
||||
.and_then(|n| n.to_str())
|
||||
.ok_or_else(|| RepoError::Git(git2::Error::from_str("Invalid worktree path")))?;
|
||||
|
||||
// Create the branch if it doesn't exist
|
||||
let head = repo.head()?;
|
||||
let head_commit = head.peel_to_commit()?;
|
||||
|
|
@ -358,7 +365,7 @@ pub fn create_worktree(
|
|||
// Create the worktree
|
||||
let reference = branch.into_reference();
|
||||
repo.worktree(
|
||||
branch_name,
|
||||
worktree_name,
|
||||
worktree_path,
|
||||
Some(git2::WorktreeAddOptions::new().reference(Some(&reference))),
|
||||
)?;
|
||||
|
|
@ -366,9 +373,17 @@ pub fn create_worktree(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove a worktree
|
||||
pub fn remove_worktree(repo: &git2::Repository, name: &str) -> Result<(), RepoError> {
|
||||
let worktree = repo.find_worktree(name)?;
|
||||
/// Remove a worktree by path
|
||||
///
|
||||
/// Derives the worktree name from the path's directory name.
|
||||
pub fn remove_worktree(repo: &git2::Repository, worktree_path: &Path) -> Result<(), RepoError> {
|
||||
// Derive worktree name from path (same as create_worktree)
|
||||
let worktree_name = worktree_path
|
||||
.file_name()
|
||||
.and_then(|n| n.to_str())
|
||||
.ok_or_else(|| RepoError::Git(git2::Error::from_str("Invalid worktree path")))?;
|
||||
|
||||
let worktree = repo.find_worktree(worktree_name)?;
|
||||
|
||||
// Prune the worktree (this removes the worktree but keeps the branch)
|
||||
worktree.prune(Some(
|
||||
|
|
|
|||
|
|
@ -701,6 +701,13 @@ fn create_git_worktree(
|
|||
return Err("Worktree path already exists".to_string());
|
||||
}
|
||||
|
||||
// Derive worktree name from path (directory name = slug, no slashes)
|
||||
// Git worktree names are stored in .git/worktrees/<name> and cannot contain slashes
|
||||
let worktree_name = worktree_path
|
||||
.file_name()
|
||||
.and_then(|n| n.to_str())
|
||||
.ok_or("Invalid worktree path")?;
|
||||
|
||||
// Get HEAD commit to branch from
|
||||
let head = repo.head().map_err(|e| format!("Failed to get HEAD: {}", e))?;
|
||||
let commit = head.peel_to_commit().map_err(|e| format!("Failed to get commit: {}", e))?;
|
||||
|
|
@ -720,7 +727,7 @@ fn create_git_worktree(
|
|||
|
||||
// Create the worktree
|
||||
repo.worktree(
|
||||
branch_name,
|
||||
worktree_name,
|
||||
worktree_path,
|
||||
Some(git2::WorktreeAddOptions::new().reference(Some(&reference))),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -380,8 +380,9 @@ pub fn handle_cleanup(state: &ProjectState, args: &Value) -> Result<Value, Serve
|
|||
}
|
||||
|
||||
// Remove worktree from git
|
||||
let worktree_removed = if worktree.is_some() {
|
||||
blue_core::repo::remove_worktree(&repo, &branch_name).is_ok()
|
||||
let worktree_removed = if let Some(ref wt) = worktree {
|
||||
let wt_path = Path::new(&wt.worktree_path);
|
||||
blue_core::repo::remove_worktree(&repo, wt_path).is_ok()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
|
@ -465,8 +466,9 @@ pub fn handle_remove(state: &ProjectState, args: &Value) -> Result<Value, Server
|
|||
|
||||
// Remove from git
|
||||
let repo_path = state.home.root.clone();
|
||||
let wt_path = Path::new(&worktree.worktree_path);
|
||||
if let Ok(repo) = git2::Repository::open(&repo_path) {
|
||||
if let Err(e) = blue_core::repo::remove_worktree(&repo, &worktree.branch_name) {
|
||||
if let Err(e) = blue_core::repo::remove_worktree(&repo, wt_path) {
|
||||
return Ok(json!({
|
||||
"status": "error",
|
||||
"message": blue_core::voice::error(
|
||||
|
|
|
|||
Loading…
Reference in a new issue