← back to joescharf__wt

Function bodies 244 total

All specs Real LLM only Function bodies
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, merge
mcp.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.NewTool
mcp.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.saveRa
claude.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
}
‹ prevpage 2 / 5next ›