feat: initial commit of Git Automation CLI
- 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
This commit is contained in:
283
internal/cmd/commit.go
Normal file
283
internal/cmd/commit.go
Normal file
@@ -0,0 +1,283 @@
|
||||
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)
|
||||
}
|
Reference in New Issue
Block a user