
- Add comprehensive Git workflow automation tools - Include branch management utilities - Add commit helpers with conventional commit support - Implement GitHub integration for PR management - Add configuration management system - Include comprehensive test coverage - Add professional documentation and examples
272 lines
6.8 KiB
Go
272 lines
6.8 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"github.com/spf13/cobra"
|
|
"github.com/iwasforcedtobehere/git-automation-cli/internal/config"
|
|
"github.com/iwasforcedtobehere/git-automation-cli/internal/git"
|
|
"github.com/iwasforcedtobehere/git-automation-cli/internal/validation"
|
|
)
|
|
|
|
var branchCmd = &cobra.Command{
|
|
Use: "branch",
|
|
Short: "Branch utilities",
|
|
Long: `Create, list, switch, and manage Git branches.
|
|
Supports common branch naming conventions and workflows.`,
|
|
}
|
|
|
|
var branchListCmd = &cobra.Command{
|
|
Use: "list",
|
|
Short: "List branches",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
ctx := cmd.Context()
|
|
branches, err := git.LocalBranches(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to list branches: %w", err)
|
|
}
|
|
|
|
currentBranch, err := git.CurrentBranch(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get current branch: %w", err)
|
|
}
|
|
|
|
for _, branch := range branches {
|
|
if branch == currentBranch {
|
|
fmt.Printf("* %s\n", branch)
|
|
} else {
|
|
fmt.Printf(" %s\n", branch)
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var branchCreateCmd = &cobra.Command{
|
|
Use: "create [name]",
|
|
Short: "Create a new branch",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
ctx := cmd.Context()
|
|
name := args[0]
|
|
|
|
// Validate Git repository
|
|
if validationResult := validation.ValidateGitRepository(ctx); !validationResult.IsValid {
|
|
return fmt.Errorf(validationResult.GetErrors())
|
|
}
|
|
|
|
// Apply prefix if configured
|
|
originalName := name
|
|
if config.GlobalConfig.BranchPrefix != "" {
|
|
name = config.GlobalConfig.BranchPrefix + name
|
|
}
|
|
|
|
// Validate branch name
|
|
if validationResult := validation.ValidateBranchName(name); !validationResult.IsValid {
|
|
return fmt.Errorf("invalid branch name '%s': %s", originalName, validationResult.GetErrors())
|
|
}
|
|
|
|
// Check if branch already exists
|
|
branches, err := git.LocalBranches(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to check existing branches: %w", err)
|
|
}
|
|
|
|
for _, branch := range branches {
|
|
if branch == name {
|
|
return fmt.Errorf("branch '%s' already exists", name)
|
|
}
|
|
}
|
|
|
|
// Create the branch
|
|
if err := git.CreateBranch(ctx, name); err != nil {
|
|
return fmt.Errorf("failed to create branch: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Created branch: %s\n", name)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var branchSwitchCmd = &cobra.Command{
|
|
Use: "switch [name]",
|
|
Short: "Switch to a branch",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
ctx := cmd.Context()
|
|
name := args[0]
|
|
|
|
// Apply prefix if configured
|
|
if config.GlobalConfig.BranchPrefix != "" && !strings.HasPrefix(name, config.GlobalConfig.BranchPrefix) {
|
|
name = config.GlobalConfig.BranchPrefix + name
|
|
}
|
|
|
|
// Check if branch exists
|
|
branches, err := git.LocalBranches(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to list branches: %w", err)
|
|
}
|
|
|
|
found := false
|
|
for _, branch := range branches {
|
|
if branch == name {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
return fmt.Errorf("branch '%s' does not exist", name)
|
|
}
|
|
|
|
// Switch to the branch
|
|
if err := git.SwitchBranch(ctx, name); err != nil {
|
|
return fmt.Errorf("failed to switch branch: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Switched to branch: %s\n", name)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var branchDeleteCmd = &cobra.Command{
|
|
Use: "delete [name]",
|
|
Short: "Delete a branch",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
ctx := cmd.Context()
|
|
name := args[0]
|
|
|
|
// Apply prefix if configured
|
|
if config.GlobalConfig.BranchPrefix != "" && !strings.HasPrefix(name, config.GlobalConfig.BranchPrefix) {
|
|
name = config.GlobalConfig.BranchPrefix + name
|
|
}
|
|
|
|
// Check if branch exists
|
|
branches, err := git.LocalBranches(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to list branches: %w", err)
|
|
}
|
|
|
|
found := false
|
|
for _, branch := range branches {
|
|
if branch == name {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
return fmt.Errorf("branch '%s' does not exist", name)
|
|
}
|
|
|
|
// Check if it's the current branch
|
|
currentBranch, err := git.CurrentBranch(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get current branch: %w", err)
|
|
}
|
|
|
|
if currentBranch == name {
|
|
return fmt.Errorf("cannot delete the current branch '%s'", name)
|
|
}
|
|
|
|
// Confirm deletion if configured
|
|
if config.GlobalConfig.ConfirmDestructive {
|
|
fmt.Printf("Are you sure you want to delete branch '%s'? [y/N]: ", name)
|
|
var response string
|
|
fmt.Scanln(&response)
|
|
if strings.ToLower(response) != "y" && strings.ToLower(response) != "yes" {
|
|
fmt.Println("Branch deletion cancelled")
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Delete the branch
|
|
if err := git.DeleteBranch(ctx, name); err != nil {
|
|
return fmt.Errorf("failed to delete branch: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Deleted branch: %s\n", name)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var branchFeatureCmd = &cobra.Command{
|
|
Use: "feature [name]",
|
|
Short: "Create a new feature branch",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
ctx := cmd.Context()
|
|
name := args[0]
|
|
|
|
// Apply feature prefix
|
|
if config.GlobalConfig.FeaturePrefix != "" {
|
|
name = config.GlobalConfig.FeaturePrefix + name
|
|
}
|
|
|
|
// Check if branch already exists
|
|
branches, err := git.LocalBranches(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to check existing branches: %w", err)
|
|
}
|
|
|
|
for _, branch := range branches {
|
|
if branch == name {
|
|
return fmt.Errorf("feature branch '%s' already exists", name)
|
|
}
|
|
}
|
|
|
|
// Create the feature branch
|
|
if err := git.CreateBranch(ctx, name); err != nil {
|
|
return fmt.Errorf("failed to create feature branch: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Created feature branch: %s\n", name)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var branchHotfixCmd = &cobra.Command{
|
|
Use: "hotfix [name]",
|
|
Short: "Create a new hotfix branch",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
ctx := cmd.Context()
|
|
name := args[0]
|
|
|
|
// Apply hotfix prefix
|
|
if config.GlobalConfig.HotfixPrefix != "" {
|
|
name = config.GlobalConfig.HotfixPrefix + name
|
|
}
|
|
|
|
// Check if branch already exists
|
|
branches, err := git.LocalBranches(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to check existing branches: %w", err)
|
|
}
|
|
|
|
for _, branch := range branches {
|
|
if branch == name {
|
|
return fmt.Errorf("hotfix branch '%s' already exists", name)
|
|
}
|
|
}
|
|
|
|
// Create the hotfix branch
|
|
if err := git.CreateBranch(ctx, name); err != nil {
|
|
return fmt.Errorf("failed to create hotfix branch: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Created hotfix branch: %s\n", name)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
rootCmd.AddCommand(branchCmd)
|
|
branchCmd.AddCommand(branchListCmd)
|
|
branchCmd.AddCommand(branchCreateCmd)
|
|
branchCmd.AddCommand(branchSwitchCmd)
|
|
branchCmd.AddCommand(branchDeleteCmd)
|
|
branchCmd.AddCommand(branchFeatureCmd)
|
|
branchCmd.AddCommand(branchHotfixCmd)
|
|
} |