Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions cmd/down.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package cmd

import (
"bufio"
"fmt"
"os"
"strconv"
"strings"

"github.com/javoire/stackinator/internal/git"
"github.com/javoire/stackinator/internal/stack"
"github.com/spf13/cobra"
)

var downCmd = &cobra.Command{
Use: "down",
Short: "Move to a child branch in the stack",
Long: `Checkout a child branch of the current branch in the stack.

If the current branch has no children (is at the tip of the stack),
an error message will be displayed.

If there are multiple children, you will be prompted to select one.`,
Example: ` # Move to child branch
stack down`,
Run: func(cmd *cobra.Command, args []string) {
gitClient := git.NewGitClient()

if err := runDown(gitClient); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
},
}

func runDown(gitClient git.GitClient) error {
// Get current branch
currentBranch, err := gitClient.GetCurrentBranch()
if err != nil {
return fmt.Errorf("failed to get current branch: %w", err)
}

// Get children of current branch
children, err := stack.GetChildrenOf(gitClient, currentBranch)
if err != nil {
return fmt.Errorf("failed to get children: %w", err)
}

if len(children) == 0 {
return fmt.Errorf("no children (tip of stack)")
}

var targetBranch string

if len(children) == 1 {
// Only one child, checkout directly
targetBranch = children[0].Name
} else {
// Multiple children, prompt for selection
fmt.Printf("Multiple children found for %s:\n", currentBranch)
for i, child := range children {
fmt.Printf(" %d) %s\n", i+1, child.Name)
}
fmt.Print("\nSelect branch (1-" + strconv.Itoa(len(children)) + "): ")

reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
return fmt.Errorf("failed to read input: %w", err)
}

input = strings.TrimSpace(input)
selection, err := strconv.Atoi(input)
if err != nil || selection < 1 || selection > len(children) {
return fmt.Errorf("invalid selection: %s", input)
}

targetBranch = children[selection-1].Name
}

// Checkout the target branch
if err := gitClient.CheckoutBranch(targetBranch); err != nil {
return fmt.Errorf("failed to checkout child branch %s: %w", targetBranch, err)
}

fmt.Printf("Switched to child branch: %s\n", targetBranch)
return nil
}
2 changes: 2 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ func init() {
rootCmd.AddCommand(renameCmd)
rootCmd.AddCommand(reparentCmd)
rootCmd.AddCommand(worktreeCmd)
rootCmd.AddCommand(upCmd)
rootCmd.AddCommand(downCmd)
}

// Execute runs the root command
Expand Down
51 changes: 51 additions & 0 deletions cmd/up.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package cmd

import (
"fmt"
"os"

"github.com/javoire/stackinator/internal/git"
"github.com/spf13/cobra"
)

var upCmd = &cobra.Command{
Use: "up",
Short: "Move to the parent branch in the stack",
Long: `Checkout the parent branch of the current branch in the stack.

If the current branch has no parent (is at the root of the stack),
an error message will be displayed.`,
Example: ` # Move to parent branch
stack up`,
Run: func(cmd *cobra.Command, args []string) {
gitClient := git.NewGitClient()

if err := runUp(gitClient); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
},
}

func runUp(gitClient git.GitClient) error {
// Get current branch
currentBranch, err := gitClient.GetCurrentBranch()
if err != nil {
return fmt.Errorf("failed to get current branch: %w", err)
}

// Get parent from git config
parent := gitClient.GetConfig(fmt.Sprintf("branch.%s.stackparent", currentBranch))

if parent == "" {
return fmt.Errorf("already at stack root (no parent for %s)", currentBranch)
}

// Checkout the parent branch
if err := gitClient.CheckoutBranch(parent); err != nil {
return fmt.Errorf("failed to checkout parent branch %s: %w", parent, err)
}

fmt.Printf("Switched to parent branch: %s\n", parent)
return nil
}