feat(context): centralize RepoContext API for git operations (#1102)
Centralizes repository context resolution via RepoContext API, fixing bugs where git commands run in the wrong repo when BEADS_DIR points elsewhere or in worktree scenarios.
This commit is contained in:
committed by
GitHub
parent
159114563b
commit
0a48519561
@@ -3,11 +3,11 @@ package daemon
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/steveyegge/beads/internal/beads"
|
||||
"github.com/steveyegge/beads/internal/lockfile"
|
||||
"github.com/steveyegge/beads/internal/rpc"
|
||||
"github.com/steveyegge/beads/internal/utils"
|
||||
@@ -252,44 +252,37 @@ func FindDaemonByWorkspace(workspacePath string) (*DaemonInfo, error) {
|
||||
return nil, fmt.Errorf("no daemon found for workspace: %s", workspacePath)
|
||||
}
|
||||
|
||||
// findBeadsDirForWorkspace determines the correct .beads directory for a workspace
|
||||
// For worktrees, this is the main repository root; for regular repos, it's the workspace itself
|
||||
// findBeadsDirForWorkspace determines the correct .beads directory for a workspace.
|
||||
// For worktrees, this is the main repository root; for regular repos, it's the workspace itself.
|
||||
//
|
||||
// This function delegates to beads.GetRepoContextForWorkspace() for proper resolution
|
||||
// including worktree detection and path validation (DMN-001).
|
||||
func findBeadsDirForWorkspace(workspacePath string) string {
|
||||
// Change to the workspace directory to check if it's a worktree
|
||||
originalDir, err := os.Getwd()
|
||||
// Use the centralized RepoContext API for workspace resolution
|
||||
rc, err := beads.GetRepoContextForWorkspace(workspacePath)
|
||||
if err != nil {
|
||||
return filepath.Join(workspacePath, ".beads") // fallback
|
||||
// Fallback to simple path join if context resolution fails
|
||||
// This maintains backward compatibility for edge cases
|
||||
return filepath.Join(workspacePath, ".beads")
|
||||
}
|
||||
defer func() {
|
||||
_ = os.Chdir(originalDir) // restore original directory
|
||||
}()
|
||||
return rc.BeadsDir
|
||||
}
|
||||
|
||||
if err := os.Chdir(workspacePath); err != nil {
|
||||
return filepath.Join(workspacePath, ".beads") // fallback
|
||||
}
|
||||
|
||||
// Check if we're in a git worktree
|
||||
cmd := exec.Command("git", "rev-parse", "--git-dir", "--git-common-dir")
|
||||
output, err := cmd.Output()
|
||||
// getRepoContextForWorkspace returns the full RepoContext for a workspace.
|
||||
// This provides access to RepoRoot, BeadsDir, and worktree status for operations
|
||||
// that need more than just the .beads directory path.
|
||||
//
|
||||
// Returns an error if the workspace cannot be resolved or validated.
|
||||
func getRepoContextForWorkspace(workspacePath string) (*beads.RepoContext, error) {
|
||||
rc, err := beads.GetRepoContextForWorkspace(workspacePath)
|
||||
if err != nil {
|
||||
return filepath.Join(workspacePath, ".beads") // fallback
|
||||
return nil, fmt.Errorf("cannot resolve workspace context: %w", err)
|
||||
}
|
||||
|
||||
lines := strings.Split(strings.TrimSpace(string(output)), "\n")
|
||||
if len(lines) >= 2 {
|
||||
gitDir := strings.TrimSpace(lines[0])
|
||||
commonDir := strings.TrimSpace(lines[1])
|
||||
|
||||
// If git-dir != git-common-dir, we're in a worktree
|
||||
if gitDir != commonDir {
|
||||
// Worktree: .beads is in main repo root (parent of git-common-dir)
|
||||
mainRepoRoot := filepath.Dir(commonDir)
|
||||
return filepath.Join(mainRepoRoot, ".beads")
|
||||
}
|
||||
// Validate the context is still valid (paths exist)
|
||||
if err := rc.Validate(); err != nil {
|
||||
return nil, fmt.Errorf("workspace context is stale: %w", err)
|
||||
}
|
||||
|
||||
// Regular repository: .beads is in the workspace
|
||||
return filepath.Join(workspacePath, ".beads")
|
||||
return rc, nil
|
||||
}
|
||||
|
||||
// checkDaemonErrorFile checks for a daemon-error file in the .beads directory
|
||||
|
||||
Reference in New Issue
Block a user