Function bodies 244 total
mcp.Server.deleteTool method · go · L346-L354 (9 LOC)internal/mcp/server.go
func (s *Server) deleteTool() (mcp.Tool, server.ToolHandlerFunc) {
tool := mcp.NewTool("wt_delete",
mcp.WithDescription("Close iTerm2 window + remove worktree. Checks for uncommitted changes and unpushed commits unless force is set."),
mcp.WithString("repo_path", mcp.Required(), mcp.Description("Absolute path to the git repository")),
mcp.WithString("branch", mcp.Required(), mcp.Description("Branch name of the worktree to delete")),
mcp.WithBoolean("force", mcp.Description("Force removal, skip safety checks")),
)
return tool, s.handleDelete
}mcp.Server.handleDelete method · go · L356-L419 (64 LOC)internal/mcp/server.go
func (s *Server) handleDelete(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
repoPath, err := request.RequireString("repo_path")
if err != nil {
return mcp.NewToolResultError("missing required parameter: repo_path"), nil
}
branch, err := request.RequireString("branch")
if err != nil {
return mcp.NewToolResultError("missing required parameter: branch"), nil
}
force := request.GetBool("force", false)
// Find the worktree path
wtPath, err := s.resolveWorktreePath(repoPath, branch)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("worktree not found for branch '%s': %v", branch, err)), nil
}
// Safety checks (skip with force)
if !force {
dirty, err := s.git.IsWorktreeDirty(wtPath)
if err == nil && dirty {
return mcp.NewToolResultError(fmt.Sprintf("worktree '%s' has uncommitted changes (use force=true to override)", filepath.Base(wtPath))), nil
}
unpushed, err := s.git.HasUnpushedCommits(wtPath, s.cfg.BaseBranch)
mcp.Server.syncTool method · go · L422-L430 (9 LOC)internal/mcp/server.go
func (s *Server) syncTool() (mcp.Tool, server.ToolHandlerFunc) {
tool := mcp.NewTool("wt_sync",
mcp.WithDescription("Sync worktree with base branch by merging or rebasing base into the feature branch."),
mcp.WithString("repo_path", mcp.Required(), mcp.Description("Absolute path to the git repository")),
mcp.WithString("branch", mcp.Required(), mcp.Description("Branch name of the worktree to sync")),
mcp.WithString("strategy", mcp.Description("Sync strategy: merge (default) or rebase")),
)
return tool, s.handleSync
}mcp.Server.handleSync method · go · L432-L498 (67 LOC)internal/mcp/server.go
func (s *Server) handleSync(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
repoPath, err := request.RequireString("repo_path")
if err != nil {
return mcp.NewToolResultError("missing required parameter: repo_path"), nil
}
branch, err := request.RequireString("branch")
if err != nil {
return mcp.NewToolResultError("missing required parameter: branch"), nil
}
strategy := request.GetString("strategy", "merge")
// Find the worktree path
wtPath, err := s.resolveWorktreePath(repoPath, branch)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("worktree not found for branch '%s': %v", branch, err)), nil
}
baseBranch := s.cfg.BaseBranch
mergeSource := baseBranch
// Fetch if remote exists
hasRemote, _ := s.git.HasRemote(repoPath)
if hasRemote {
_ = s.git.Fetch(repoPath)
mergeSource = "origin/" + baseBranch
}
// Check status
behind, _ := s.git.CommitsBehind(wtPath, mergeSource)
ahead, _ := s.git.CommitsAhead(wtPath, mergemcp.Server.mergeTool method · go · L501-L510 (10 LOC)internal/mcp/server.go
func (s *Server) mergeTool() (mcp.Tool, server.ToolHandlerFunc) {
tool := mcp.NewTool("wt_merge",
mcp.WithDescription("Merge worktree branch into base branch (local merge or push for PR)."),
mcp.WithString("repo_path", mcp.Required(), mcp.Description("Absolute path to the git repository")),
mcp.WithString("branch", mcp.Required(), mcp.Description("Branch name of the worktree to merge")),
mcp.WithString("strategy", mcp.Description("Merge strategy: merge (default) or rebase (rebase-then-fast-forward)")),
mcp.WithBoolean("pr", mcp.Description("Push branch for PR instead of local merge")),
)
return tool, s.handleMerge
}mcp.Server.handleMerge method · go · L512-L548 (37 LOC)internal/mcp/server.go
func (s *Server) handleMerge(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
repoPath, err := request.RequireString("repo_path")
if err != nil {
return mcp.NewToolResultError("missing required parameter: repo_path"), nil
}
branch, err := request.RequireString("branch")
if err != nil {
return mcp.NewToolResultError("missing required parameter: branch"), nil
}
strategy := request.GetString("strategy", "merge")
pr := request.GetBool("pr", false)
// Find the worktree path
wtPath, err := s.resolveWorktreePath(repoPath, branch)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("worktree not found for branch '%s': %v", branch, err)), nil
}
baseBranch := s.cfg.BaseBranch
// Check if there are commits to merge
hasCommits, _ := s.git.HasUnpushedCommits(wtPath, baseBranch)
if !hasCommits {
result := map[string]any{
"branch": branch,
"status": "no commits to merge",
}
data, _ := json.Marshal(result)
return mcp.NewToolmcp.Server.handleMergeLocal method · go · L550-L602 (53 LOC)internal/mcp/server.go
func (s *Server) handleMergeLocal(repoPath, wtPath, branch, baseBranch, strategy string) (*mcp.CallToolResult, error) {
repoRoot, err := s.git.RepoRoot(repoPath)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("failed to get repo root: %v", err)), nil
}
if strategy == "rebase" {
// Rebase-then-fast-forward
if err := s.git.Rebase(wtPath, baseBranch); err != nil {
return mcp.NewToolResultError(fmt.Sprintf("rebase failed: %v", err)), nil
}
if err := s.git.Merge(repoRoot, branch); err != nil {
return mcp.NewToolResultError(fmt.Sprintf("fast-forward merge failed: %v", err)), nil
}
} else {
if err := s.git.Merge(repoRoot, branch); err != nil {
return mcp.NewToolResultError(fmt.Sprintf("merge failed: %v", err)), nil
}
}
// Push if remote exists
hasRemote, _ := s.git.HasRemote(repoPath)
if hasRemote {
_ = s.git.Push(repoRoot, baseBranch, false)
}
// Post-merge cleanup: close iTerm, remove worktree, delete branch, clean state
ws, _ := s.state.Same scanner, your repo: https://repobility.com — Repobility
mcp.Server.handleMergePR method · go · L604-L622 (19 LOC)internal/mcp/server.go
func (s *Server) handleMergePR(repoPath, wtPath, branch, baseBranch string) (*mcp.CallToolResult, error) {
// Push branch
if err := s.git.Push(wtPath, branch, true); err != nil {
return mcp.NewToolResultError(fmt.Sprintf("push failed: %v", err)), nil
}
result := map[string]any{
"branch": branch,
"base": baseBranch,
"pushed": true,
"action": "push for PR — create the PR on GitHub",
}
data, err := json.Marshal(result)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("failed to marshal result: %v", err)), nil
}
return mcp.NewToolResultText(string(data)), nil
}mcp.Server.resolveWorktreePath method · go · L630-L641 (12 LOC)internal/mcp/server.go
func (s *Server) resolveWorktreePath(repoPath, branch string) (string, error) {
worktrees, err := s.git.WorktreeList(repoPath)
if err != nil {
return "", err
}
if path := gitops.ResolveWorktreeFromList(branch, worktrees); path != "" {
return path, nil
}
return "", fmt.Errorf("not found")
}mcp.formatAge function · go · L643-L652 (10 LOC)internal/mcp/server.go
func formatAge(d time.Duration) string {
switch {
case d < time.Hour:
return fmt.Sprintf("%dm", int(d.Minutes()))
case d < 24*time.Hour:
return fmt.Sprintf("%dh", int(d.Hours()))
default:
return fmt.Sprintf("%dd", int(d.Hours()/24))
}
}ui.New function · go · L22-L27 (6 LOC)internal/ui/ui.go
func New() *UI {
return &UI{
Out: os.Stdout,
ErrOut: os.Stderr,
}
}ui.StatusColor function · go · L62-L73 (12 LOC)internal/ui/ui.go
func StatusColor(status string) string {
switch status {
case "open":
return green(status)
case "stale":
return yellow(status)
case "closed":
return red(status)
default:
return status
}
}ui.SourceColor function · go · L77-L88 (12 LOC)internal/ui/ui.go
func SourceColor(source string) string {
switch source {
case "wt":
return green(source)
case "adopted":
return cyan(source)
case "external":
return yellow(source)
default:
return source
}
}ui.GitStatusColor function · go · L92-L105 (14 LOC)internal/ui/ui.go
func GitStatusColor(status string) string {
switch {
case strings.HasPrefix(status, "rebasing"),
strings.HasPrefix(status, "merging"),
strings.HasPrefix(status, "dirty"):
return red(status)
case status == "clean":
return green(status)
case strings.Contains(status, "↑") || strings.Contains(status, "↓"):
return yellow(status)
default:
return status
}
}ui.TermWidth function · go · L138-L143 (6 LOC)internal/ui/ui.go
func TermWidth() int {
if w, _, err := term.GetSize(int(os.Stdout.Fd())); err == nil && w > 0 {
return w
}
return defaultTermWidth
}Source: Repobility analyzer · https://repobility.com
claude.DefaultPath function · go · L21-L27 (7 LOC)pkg/claude/trust.go
func DefaultPath() (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, ".claude.json"), nil
}claude.TrustManager.TrustProject method · go · L36-L80 (45 LOC)pkg/claude/trust.go
func (m *TrustManager) TrustProject(projectPath string) (bool, error) {
top, err := m.loadRaw()
if err != nil {
return false, err
}
key := encodeProjectKey(projectPath)
// Get or create the projects map
projects, err := getOrCreateMap(top, "projects")
if err != nil {
return false, err
}
// Get or create the project entry
project, err := getOrCreateMap(projects, key)
if err != nil {
return false, err
}
// Check if already trusted
if hasTrust(project, "hasTrustDialogAccepted") && hasTrust(project, "hasTrustDialogHooksAccepted") {
return false, nil
}
// Set trust flags
trueVal, _ := json.Marshal(true)
project["hasTrustDialogAccepted"] = trueVal
project["hasTrustDialogHooksAccepted"] = trueVal
// Write back
projectData, err := json.Marshal(project)
if err != nil {
return false, err
}
projects[key] = projectData
projectsData, err := json.Marshal(projects)
if err != nil {
return false, err
}
top["projects"] = projectsData
return true, m.saveRaclaude.TrustManager.UntrustProject method · go · L83-L114 (32 LOC)pkg/claude/trust.go
func (m *TrustManager) UntrustProject(projectPath string) error {
top, err := m.loadRaw()
if err != nil {
return err
}
key := encodeProjectKey(projectPath)
projectsRaw, ok := top["projects"]
if !ok {
return nil
}
var projects map[string]json.RawMessage
if err := json.Unmarshal(projectsRaw, &projects); err != nil {
return nil // not a valid projects map, nothing to do
}
if _, exists := projects[key]; !exists {
return nil
}
delete(projects, key)
projectsData, err := json.Marshal(projects)
if err != nil {
return err
}
top["projects"] = projectsData
return m.saveRaw(top)
}claude.TrustManager.PruneProjects method · go · L118-L156 (39 LOC)pkg/claude/trust.go
func (m *TrustManager) PruneProjects(worktreesDir string) (int, error) {
top, err := m.loadRaw()
if err != nil {
return 0, err
}
projectsRaw, ok := top["projects"]
if !ok {
return 0, nil
}
var projects map[string]json.RawMessage
if err := json.Unmarshal(projectsRaw, &projects); err != nil {
return 0, nil
}
pruned := 0
for key := range projects {
projectPath := decodeProjectKey(key)
if !strings.HasPrefix(projectPath, worktreesDir+string(filepath.Separator)) {
continue
}
if _, err := os.Stat(projectPath); os.IsNotExist(err) {
delete(projects, key)
pruned++
}
}
if pruned > 0 {
projectsData, err := json.Marshal(projects)
if err != nil {
return pruned, err
}
top["projects"] = projectsData
return pruned, m.saveRaw(top)
}
return 0, nil
}claude.TrustManager.loadRaw method · go · L159-L178 (20 LOC)pkg/claude/trust.go
func (m *TrustManager) loadRaw() (map[string]json.RawMessage, error) {
data, err := os.ReadFile(m.path)
if err != nil {
if os.IsNotExist(err) {
return make(map[string]json.RawMessage), nil
}
return nil, err
}
// Handle empty file
if len(data) == 0 {
return make(map[string]json.RawMessage), nil
}
var top map[string]json.RawMessage
if err := json.Unmarshal(data, &top); err != nil {
return nil, err
}
return top, nil
}claude.TrustManager.saveRaw method · go · L181-L197 (17 LOC)pkg/claude/trust.go
func (m *TrustManager) saveRaw(top map[string]json.RawMessage) error {
dir := filepath.Dir(m.path)
if err := os.MkdirAll(dir, 0755); err != nil {
return err
}
data, err := json.MarshalIndent(top, "", " ")
if err != nil {
return err
}
tmp := m.path + ".tmp"
if err := os.WriteFile(tmp, data, 0644); err != nil {
return err
}
return os.Rename(tmp, m.path)
}claude.getOrCreateMap function · go · L211-L222 (12 LOC)pkg/claude/trust.go
func getOrCreateMap(parent map[string]json.RawMessage, key string) (map[string]json.RawMessage, error) {
raw, ok := parent[key]
if !ok || string(raw) == "null" {
return make(map[string]json.RawMessage), nil
}
var m map[string]json.RawMessage
if err := json.Unmarshal(raw, &m); err != nil {
return nil, err
}
return m, nil
}claude.hasTrust function · go · L225-L235 (11 LOC)pkg/claude/trust.go
func hasTrust(project map[string]json.RawMessage, field string) bool {
raw, ok := project[field]
if !ok {
return false
}
var val bool
if err := json.Unmarshal(raw, &val); err != nil {
return false
}
return val
}Want fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
gitops.RealClient.RepoRoot method · go · L61-L90 (30 LOC)pkg/gitops/gitops.go
func (c *RealClient) RepoRoot(repoPath string) (string, error) {
out, err := exec.Command("git", "-C", repoPath, "rev-parse", "--git-common-dir").Output()
if err != nil {
return "", fmt.Errorf("not inside a git repository: %w", err)
}
gitCommonDir := strings.TrimSpace(string(out))
var root string
if gitCommonDir == ".git" {
absPath, err := filepath.Abs(repoPath)
if err != nil {
return "", err
}
root = absPath
} else {
absGitDir, err := filepath.Abs(gitCommonDir)
if err != nil {
return "", err
}
root = filepath.Dir(absGitDir)
}
// Resolve symlinks for consistent paths (e.g., macOS /var -> /private/var)
resolved, err := filepath.EvalSymlinks(root)
if err != nil {
return root, nil
}
return resolved, nil
}gitops.RealClient.RepoName method · go · L92-L98 (7 LOC)pkg/gitops/gitops.go
func (c *RealClient) RepoName(repoPath string) (string, error) {
root, err := c.RepoRoot(repoPath)
if err != nil {
return "", err
}
return filepath.Base(root), nil
}gitops.RealClient.WorktreesDir method · go · L100-L106 (7 LOC)pkg/gitops/gitops.go
func (c *RealClient) WorktreesDir(repoPath string) (string, error) {
root, err := c.RepoRoot(repoPath)
if err != nil {
return "", err
}
return root + ".worktrees", nil
}gitops.RealClient.WorktreeList method · go · L108-L120 (13 LOC)pkg/gitops/gitops.go
func (c *RealClient) WorktreeList(repoPath string) ([]WorktreeInfo, error) {
root, err := c.RepoRoot(repoPath)
if err != nil {
return nil, err
}
out, err := exec.Command("git", "-C", root, "worktree", "list", "--porcelain").Output()
if err != nil {
return nil, fmt.Errorf("failed to list worktrees: %w", err)
}
return ParseWorktreeListPorcelain(string(out)), nil
}gitops.ParseWorktreeListPorcelain function · go · L123-L149 (27 LOC)pkg/gitops/gitops.go
func ParseWorktreeListPorcelain(output string) []WorktreeInfo {
var worktrees []WorktreeInfo
var current WorktreeInfo
for _, line := range strings.Split(output, "\n") {
switch {
case strings.HasPrefix(line, "worktree "):
current.Path = strings.TrimPrefix(line, "worktree ")
case strings.HasPrefix(line, "HEAD "):
current.HEAD = strings.TrimPrefix(line, "HEAD ")
case strings.HasPrefix(line, "branch "):
branch := strings.TrimPrefix(line, "branch ")
current.Branch = strings.TrimPrefix(branch, "refs/heads/")
case line == "":
if current.Path != "" {
worktrees = append(worktrees, current)
current = WorktreeInfo{}
}
}
}
// Handle last entry if no trailing newline
if current.Path != "" {
worktrees = append(worktrees, current)
}
return worktrees
}gitops.RealClient.WorktreeAdd method · go · L151-L169 (19 LOC)pkg/gitops/gitops.go
func (c *RealClient) WorktreeAdd(repoPath, wtPath, branch, base string, newBranch bool) error {
root, err := c.RepoRoot(repoPath)
if err != nil {
return err
}
var cmd *exec.Cmd
if newBranch {
cmd = exec.Command("git", "-C", root, "worktree", "add", "-b", branch, wtPath, base)
} else {
cmd = exec.Command("git", "-C", root, "worktree", "add", wtPath, branch)
}
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("git worktree add failed: %s: %w", strings.TrimSpace(string(out)), err)
}
return nil
}gitops.RealClient.WorktreeRemove method · go · L171-L188 (18 LOC)pkg/gitops/gitops.go
func (c *RealClient) WorktreeRemove(repoPath, wtPath string, force bool) error {
root, err := c.RepoRoot(repoPath)
if err != nil {
return err
}
args := []string{"-C", root, "worktree", "remove"}
if force {
args = append(args, "--force")
}
args = append(args, wtPath)
out, err := exec.Command("git", args...).CombinedOutput()
if err != nil {
return fmt.Errorf("git worktree remove failed: %s: %w", strings.TrimSpace(string(out)), err)
}
return nil
}gitops.RealClient.BranchExists method · go · L190-L204 (15 LOC)pkg/gitops/gitops.go
func (c *RealClient) BranchExists(repoPath, branch string) (bool, error) {
root, err := c.RepoRoot(repoPath)
if err != nil {
return false, err
}
err = exec.Command("git", "-C", root, "show-ref", "--verify", "--quiet", "refs/heads/"+branch).Run()
if err != nil {
if exitErr, ok := err.(*exec.ExitError); ok && exitErr.ExitCode() == 1 {
return false, nil
}
return false, err
}
return true, nil
}Repobility · code-quality intelligence platform · https://repobility.com
gitops.RealClient.BranchDelete method · go · L206-L222 (17 LOC)pkg/gitops/gitops.go
func (c *RealClient) BranchDelete(repoPath, branch string, force bool) error {
root, err := c.RepoRoot(repoPath)
if err != nil {
return err
}
flag := "-d"
if force {
flag = "-D"
}
out, err := exec.Command("git", "-C", root, "branch", flag, branch).CombinedOutput()
if err != nil {
return fmt.Errorf("git branch delete failed: %s: %w", strings.TrimSpace(string(out)), err)
}
return nil
}gitops.RealClient.BranchList method · go · L224-L242 (19 LOC)pkg/gitops/gitops.go
func (c *RealClient) BranchList(repoPath string) ([]string, error) {
root, err := c.RepoRoot(repoPath)
if err != nil {
return nil, err
}
out, err := exec.Command("git", "-C", root, "branch", "--format=%(refname:short)").Output()
if err != nil {
return nil, fmt.Errorf("failed to list branches: %w", err)
}
var branches []string
for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
if line != "" {
branches = append(branches, line)
}
}
return branches, nil
}gitops.RealClient.IsWorktreeDirty method · go · L244-L250 (7 LOC)pkg/gitops/gitops.go
func (c *RealClient) IsWorktreeDirty(path string) (bool, error) {
out, err := exec.Command("git", "-C", path, "status", "--porcelain").Output()
if err != nil {
return false, fmt.Errorf("failed to check worktree status: %w", err)
}
return strings.TrimSpace(string(out)) != "", nil
}gitops.RealClient.HasUnpushedCommits method · go · L252-L265 (14 LOC)pkg/gitops/gitops.go
func (c *RealClient) HasUnpushedCommits(path, baseBranch string) (bool, error) {
// Try upstream first
out, err := exec.Command("git", "-C", path, "log", "@{upstream}..HEAD", "--oneline").Output()
if err == nil {
return strings.TrimSpace(string(out)) != "", nil
}
// No upstream configured, fall back to baseBranch
out, err = exec.Command("git", "-C", path, "log", baseBranch+"..HEAD", "--oneline").Output()
if err != nil {
return false, fmt.Errorf("failed to check unpushed commits: %w", err)
}
return strings.TrimSpace(string(out)) != "", nil
}gitops.RealClient.WorktreePrune method · go · L267-L278 (12 LOC)pkg/gitops/gitops.go
func (c *RealClient) WorktreePrune(repoPath string) error {
root, err := c.RepoRoot(repoPath)
if err != nil {
return err
}
out, err := exec.Command("git", "-C", root, "worktree", "prune").CombinedOutput()
if err != nil {
return fmt.Errorf("git worktree prune failed: %s: %w", strings.TrimSpace(string(out)), err)
}
return nil
}gitops.RealClient.CurrentBranch method · go · L280-L286 (7 LOC)pkg/gitops/gitops.go
func (c *RealClient) CurrentBranch(worktreePath string) (string, error) {
out, err := exec.Command("git", "-C", worktreePath, "rev-parse", "--abbrev-ref", "HEAD").Output()
if err != nil {
return "", fmt.Errorf("failed to get current branch: %w", err)
}
return strings.TrimSpace(string(out)), nil
}gitops.RealClient.ResolveWorktree method · go · L288-L323 (36 LOC)pkg/gitops/gitops.go
func (c *RealClient) ResolveWorktree(repoPath, input string) (string, error) {
// Fast path: absolute path passthrough
if filepath.IsAbs(input) {
if isDir(input) {
return input, nil
}
return "", fmt.Errorf("worktree not found: %s", input)
}
// Fast path: check standard <repo>.worktrees/ directory
wtDir, err := c.WorktreesDir(repoPath)
if err != nil {
return "", err
}
candidate := filepath.Join(wtDir, input)
if isDir(candidate) {
return candidate, nil
}
dirname := BranchToDirname(input)
candidate = filepath.Join(wtDir, dirname)
if isDir(candidate) {
return candidate, nil
}
// Fallback: search git worktree list for branch/dirname match
worktrees, err := c.WorktreeList(repoPath)
if err != nil {
return "", fmt.Errorf("worktree not found: %s", input)
}
if path := ResolveWorktreeFromList(input, worktrees); path != "" {
return path, nil
}
return "", fmt.Errorf("worktree not found: %s", input)
}gitops.ResolveWorktreeFromList function · go · L328-L352 (25 LOC)pkg/gitops/gitops.go
func ResolveWorktreeFromList(input string, worktrees []WorktreeInfo) string {
// Try exact branch name match
for _, wt := range worktrees {
if wt.Branch == input {
return wt.Path
}
}
// Try dirname match (last segment of branch)
dirname := BranchToDirname(input)
for _, wt := range worktrees {
if filepath.Base(wt.Path) == dirname {
return wt.Path
}
}
// Try matching worktree branch's dirname against input
for _, wt := range worktrees {
if BranchToDirname(wt.Branch) == input {
return wt.Path
}
}
return ""
}Same scanner, your repo: https://repobility.com — Repobility
gitops.ResolveWorktreePath function · go · L357-L380 (24 LOC)pkg/gitops/gitops.go
func ResolveWorktreePath(input, worktreesDir string) (string, error) {
// Full path
if filepath.IsAbs(input) {
if isDir(input) {
return input, nil
}
return "", fmt.Errorf("worktree not found: %s", input)
}
// Try as dirname first
candidate := filepath.Join(worktreesDir, input)
if isDir(candidate) {
return candidate, nil
}
// Try converting from branch name
dirname := BranchToDirname(input)
candidate = filepath.Join(worktreesDir, dirname)
if isDir(candidate) {
return candidate, nil
}
return "", fmt.Errorf("worktree not found: %s", input)
}gitops.RealClient.Merge method · go · L388-L394 (7 LOC)pkg/gitops/gitops.go
func (c *RealClient) Merge(repoPath, branch string) error {
out, err := exec.Command("git", "-C", repoPath, "merge", branch, "--no-edit").CombinedOutput()
if err != nil {
return fmt.Errorf("git merge failed: %s: %w", strings.TrimSpace(string(out)), err)
}
return nil
}gitops.RealClient.MergeContinue method · go · L396-L404 (9 LOC)pkg/gitops/gitops.go
func (c *RealClient) MergeContinue(repoPath string) error {
cmd := exec.Command("git", "-C", repoPath, "merge", "--continue")
cmd.Env = append(os.Environ(), "GIT_EDITOR=true") // skip editor prompt
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("git merge --continue failed: %s: %w", strings.TrimSpace(string(out)), err)
}
return nil
}gitops.RealClient.IsMergeInProgress method · go · L406-L430 (25 LOC)pkg/gitops/gitops.go
func (c *RealClient) IsMergeInProgress(repoPath string) (bool, error) {
// git has a MERGE_HEAD file when a merge is in progress
gitDir := filepath.Join(repoPath, ".git")
info, err := os.Stat(gitDir)
if err != nil {
return false, fmt.Errorf("cannot find .git directory: %w", err)
}
// If .git is a file (worktree), read the actual git dir
if !info.IsDir() {
data, err := os.ReadFile(gitDir)
if err != nil {
return false, err
}
// Format: "gitdir: /path/to/actual/.git/worktrees/name"
gitDir = strings.TrimSpace(strings.TrimPrefix(string(data), "gitdir: "))
}
_, err = os.Stat(filepath.Join(gitDir, "MERGE_HEAD"))
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
return true, nil
}gitops.RealClient.HasConflicts method · go · L432-L438 (7 LOC)pkg/gitops/gitops.go
func (c *RealClient) HasConflicts(repoPath string) (bool, error) {
out, err := exec.Command("git", "-C", repoPath, "diff", "--name-only", "--diff-filter=U").Output()
if err != nil {
return false, fmt.Errorf("failed to check for conflicts: %w", err)
}
return strings.TrimSpace(string(out)) != "", nil
}gitops.RealClient.Rebase method · go · L440-L446 (7 LOC)pkg/gitops/gitops.go
func (c *RealClient) Rebase(repoPath, branch string) error {
out, err := exec.Command("git", "-C", repoPath, "rebase", branch).CombinedOutput()
if err != nil {
return fmt.Errorf("git rebase failed: %s: %w", strings.TrimSpace(string(out)), err)
}
return nil
}gitops.RealClient.RebaseContinue method · go · L448-L456 (9 LOC)pkg/gitops/gitops.go
func (c *RealClient) RebaseContinue(repoPath string) error {
cmd := exec.Command("git", "-C", repoPath, "rebase", "--continue")
cmd.Env = append(os.Environ(), "GIT_EDITOR=true") // skip editor prompt
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("git rebase --continue failed: %s: %w", strings.TrimSpace(string(out)), err)
}
return nil
}gitops.RealClient.RebaseAbort method · go · L458-L464 (7 LOC)pkg/gitops/gitops.go
func (c *RealClient) RebaseAbort(repoPath string) error {
out, err := exec.Command("git", "-C", repoPath, "rebase", "--abort").CombinedOutput()
if err != nil {
return fmt.Errorf("git rebase --abort failed: %s: %w", strings.TrimSpace(string(out)), err)
}
return nil
}Source: Repobility analyzer · https://repobility.com
gitops.RealClient.IsRebaseInProgress method · go · L466-L488 (23 LOC)pkg/gitops/gitops.go
func (c *RealClient) IsRebaseInProgress(repoPath string) (bool, error) {
gitDir := filepath.Join(repoPath, ".git")
info, err := os.Stat(gitDir)
if err != nil {
return false, fmt.Errorf("cannot find .git directory: %w", err)
}
// If .git is a file (worktree), read the actual git dir
if !info.IsDir() {
data, err := os.ReadFile(gitDir)
if err != nil {
return false, err
}
gitDir = strings.TrimSpace(strings.TrimPrefix(string(data), "gitdir: "))
}
// Check for rebase-merge or rebase-apply directories
if _, err := os.Stat(filepath.Join(gitDir, "rebase-merge")); err == nil {
return true, nil
}
if _, err := os.Stat(filepath.Join(gitDir, "rebase-apply")); err == nil {
return true, nil
}
return false, nil
}gitops.RealClient.Pull method · go · L490-L496 (7 LOC)pkg/gitops/gitops.go
func (c *RealClient) Pull(repoPath string) error {
out, err := exec.Command("git", "-C", repoPath, "pull").CombinedOutput()
if err != nil {
return fmt.Errorf("git pull failed: %s: %w", strings.TrimSpace(string(out)), err)
}
return nil
}gitops.RealClient.Push method · go · L498-L508 (11 LOC)pkg/gitops/gitops.go
func (c *RealClient) Push(worktreePath, branch string, setUpstream bool) error {
args := []string{"-C", worktreePath, "push"}
if setUpstream {
args = append(args, "-u", "origin", branch)
}
out, err := exec.Command("git", args...).CombinedOutput()
if err != nil {
return fmt.Errorf("git push failed: %s: %w", strings.TrimSpace(string(out)), err)
}
return nil
}