
- 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
283 lines
8.0 KiB
Go
283 lines
8.0 KiB
Go
package cmd
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"github.com/spf13/cobra"
|
|
"github.com/iwasforcedtobehere/git-automation-cli/internal/git"
|
|
"github.com/iwasforcedtobehere/git-automation-cli/internal/validation"
|
|
)
|
|
|
|
var commitCmd = &cobra.Command{
|
|
Use: "commit",
|
|
Short: "Commit utilities",
|
|
Long: `Create and manage Git commits with templates and helpers.
|
|
Supports conventional commit format and commit message templates.`,
|
|
}
|
|
|
|
var commitCreateCmd = &cobra.Command{
|
|
Use: "create [message]",
|
|
Short: "Create a new commit",
|
|
Args: cobra.MinimumNArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
ctx := cmd.Context()
|
|
message := strings.Join(args, " ")
|
|
|
|
// Validate Git repository
|
|
if validationResult := validation.ValidateGitRepository(ctx); !validationResult.IsValid {
|
|
return fmt.Errorf(validationResult.GetErrors())
|
|
}
|
|
|
|
// Validate commit message
|
|
if validationResult := validation.ValidateCommitMessage(message); !validationResult.IsValid {
|
|
return fmt.Errorf("invalid commit message: %s", validationResult.GetErrors())
|
|
}
|
|
|
|
// Check if working directory is clean
|
|
if validationResult := validation.ValidateWorkingDirectory(ctx); !validationResult.IsValid {
|
|
return fmt.Errorf(validationResult.GetErrors())
|
|
}
|
|
|
|
// Add all changes
|
|
if err := git.AddAll(ctx); err != nil {
|
|
return fmt.Errorf("failed to add changes: %w", err)
|
|
}
|
|
|
|
// Create commit
|
|
if err := git.Commit(ctx, message); err != nil {
|
|
return fmt.Errorf("failed to create commit: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Created commit: %s\n", message)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var commitAmendCmd = &cobra.Command{
|
|
Use: "amend",
|
|
Short: "Amend the last commit",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
ctx := cmd.Context()
|
|
|
|
// Validate Git repository
|
|
if validationResult := validation.ValidateGitRepository(ctx); !validationResult.IsValid {
|
|
return fmt.Errorf(validationResult.GetErrors())
|
|
}
|
|
|
|
// Check if working directory is clean
|
|
if validationResult := validation.ValidateWorkingDirectory(ctx); !validationResult.IsValid {
|
|
return fmt.Errorf(validationResult.GetErrors())
|
|
}
|
|
|
|
// Add all changes
|
|
if err := git.AddAll(ctx); err != nil {
|
|
return fmt.Errorf("failed to add changes: %w", err)
|
|
}
|
|
|
|
// Amend commit
|
|
var err error
|
|
_, err = git.Run(ctx, "commit", "--amend", "--no-edit")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to amend commit: %w", err)
|
|
}
|
|
|
|
fmt.Println("Amended last commit")
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var commitFixupCmd = &cobra.Command{
|
|
Use: "fixup [commit]",
|
|
Short: "Create a fixup commit",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
ctx := cmd.Context()
|
|
commit := args[0]
|
|
|
|
// Validate Git repository
|
|
if validationResult := validation.ValidateGitRepository(ctx); !validationResult.IsValid {
|
|
return fmt.Errorf(validationResult.GetErrors())
|
|
}
|
|
|
|
// Check if working directory is clean
|
|
if validationResult := validation.ValidateWorkingDirectory(ctx); !validationResult.IsValid {
|
|
return fmt.Errorf(validationResult.GetErrors())
|
|
}
|
|
|
|
// Add all changes
|
|
if err := git.AddAll(ctx); err != nil {
|
|
return fmt.Errorf("failed to add changes: %w", err)
|
|
}
|
|
|
|
// Create fixup commit
|
|
var err error
|
|
_, err = git.Run(ctx, "commit", "--fixup", commit)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create fixup commit: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Created fixup commit for %s\n", commit)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var commitConventionalCmd = &cobra.Command{
|
|
Use: "conventional",
|
|
Short: "Create a conventional commit",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
ctx := cmd.Context()
|
|
|
|
// Get commit type
|
|
fmt.Println("Select commit type:")
|
|
fmt.Println("1. feat: A new feature")
|
|
fmt.Println("2. fix: A bug fix")
|
|
fmt.Println("3. docs: Documentation only changes")
|
|
fmt.Println("4. style: Changes that do not affect the meaning of the code")
|
|
fmt.Println("5. refactor: A code change that neither fixes a bug nor adds a feature")
|
|
fmt.Println("6. perf: A code change that improves performance")
|
|
fmt.Println("7. test: Adding missing tests or correcting existing tests")
|
|
fmt.Println("8. build: Changes that affect the build system or external dependencies")
|
|
fmt.Println("9. ci: Changes to our CI configuration files and scripts")
|
|
fmt.Println("10. chore: Other changes that don't modify src or test files")
|
|
|
|
var choice int
|
|
fmt.Print("Enter choice (1-10): ")
|
|
fmt.Scanln(&choice)
|
|
|
|
var commitType string
|
|
switch choice {
|
|
case 1:
|
|
commitType = "feat"
|
|
case 2:
|
|
commitType = "fix"
|
|
case 3:
|
|
commitType = "docs"
|
|
case 4:
|
|
commitType = "style"
|
|
case 5:
|
|
commitType = "refactor"
|
|
case 6:
|
|
commitType = "perf"
|
|
case 7:
|
|
commitType = "test"
|
|
case 8:
|
|
commitType = "build"
|
|
case 9:
|
|
commitType = "ci"
|
|
case 10:
|
|
commitType = "chore"
|
|
default:
|
|
return fmt.Errorf("invalid choice")
|
|
}
|
|
|
|
// Get scope
|
|
fmt.Print("Enter scope (optional, press Enter to skip): ")
|
|
reader := bufio.NewReader(os.Stdin)
|
|
scope, _ := reader.ReadString('\n')
|
|
scope = strings.TrimSpace(scope)
|
|
|
|
// Get description
|
|
fmt.Print("Enter description: ")
|
|
description, _ := reader.ReadString('\n')
|
|
description = strings.TrimSpace(description)
|
|
if description == "" {
|
|
return fmt.Errorf("description is required")
|
|
}
|
|
|
|
// Get body (optional)
|
|
fmt.Print("Enter detailed description (optional, press Enter to skip): ")
|
|
body, _ := reader.ReadString('\n')
|
|
body = strings.TrimSpace(body)
|
|
|
|
// Build commit message
|
|
var message string
|
|
if scope != "" {
|
|
message = fmt.Sprintf("%s(%s): %s", commitType, scope, description)
|
|
} else {
|
|
message = fmt.Sprintf("%s: %s", commitType, description)
|
|
}
|
|
|
|
if body != "" {
|
|
message += "\n\n" + body
|
|
}
|
|
|
|
// Validate Git repository
|
|
if validationResult := validation.ValidateGitRepository(ctx); !validationResult.IsValid {
|
|
return fmt.Errorf(validationResult.GetErrors())
|
|
}
|
|
|
|
// Validate conventional commit message
|
|
if validationResult := validation.ValidateConventionalCommit(message); !validationResult.IsValid {
|
|
return fmt.Errorf("invalid conventional commit message: %s", validationResult.GetErrors())
|
|
}
|
|
|
|
// Check if working directory is clean
|
|
if validationResult := validation.ValidateWorkingDirectory(ctx); !validationResult.IsValid {
|
|
return fmt.Errorf(validationResult.GetErrors())
|
|
}
|
|
|
|
// Add all changes
|
|
if err := git.AddAll(ctx); err != nil {
|
|
return fmt.Errorf("failed to add changes: %w", err)
|
|
}
|
|
|
|
// Create commit
|
|
if err := git.Commit(ctx, message); err != nil {
|
|
return fmt.Errorf("failed to create commit: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Created conventional commit: %s\n", message)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var commitSignoffCmd = &cobra.Command{
|
|
Use: "signoff [message]",
|
|
Short: "Create a commit with sign-off",
|
|
Args: cobra.MinimumNArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
ctx := cmd.Context()
|
|
message := strings.Join(args, " ")
|
|
|
|
// Validate Git repository
|
|
if validationResult := validation.ValidateGitRepository(ctx); !validationResult.IsValid {
|
|
return fmt.Errorf(validationResult.GetErrors())
|
|
}
|
|
|
|
// Validate commit message
|
|
if validationResult := validation.ValidateCommitMessage(message); !validationResult.IsValid {
|
|
return fmt.Errorf("invalid commit message: %s", validationResult.GetErrors())
|
|
}
|
|
|
|
// Check if working directory is clean
|
|
if validationResult := validation.ValidateWorkingDirectory(ctx); !validationResult.IsValid {
|
|
return fmt.Errorf(validationResult.GetErrors())
|
|
}
|
|
|
|
// Add all changes
|
|
if err := git.AddAll(ctx); err != nil {
|
|
return fmt.Errorf("failed to add changes: %w", err)
|
|
}
|
|
|
|
// Create commit with sign-off
|
|
var err error
|
|
_, err = git.Run(ctx, "commit", "-s", "-m", message)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create commit: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Created signed-off commit: %s\n", message)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
rootCmd.AddCommand(commitCmd)
|
|
commitCmd.AddCommand(commitCreateCmd)
|
|
commitCmd.AddCommand(commitAmendCmd)
|
|
commitCmd.AddCommand(commitFixupCmd)
|
|
commitCmd.AddCommand(commitConventionalCmd)
|
|
commitCmd.AddCommand(commitSignoffCmd)
|
|
} |