Something went wrong. Try again.
CLI that turns LLM input into well-formatted Conventional Commits
Something went wrong. Try again.
git-format main.go
6.1 kB · 223 lines
Go
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>//// SPDX-License-Identifier: AGPL-3.0-or-later
package main
import ( "context" "fmt" "os" "path/filepath" "runtime/debug" "strings"
"charm.land/fang/v2" "github.com/spf13/cobra")
type mode int
const ( modeUnknown mode = iota modeCommit modeTag modeRoot)
var ( version = "dev" commitType string message string trailers []string body string scope string breakingChange string add bool amend bool)
func detectMode() mode { base := filepath.Base(os.Args[0]) switch { case strings.HasSuffix(base, "git-formatted-commit"): return modeCommit case strings.HasSuffix(base, "git-formatted-tag"): return modeTag case strings.HasSuffix(base, "git-format"): return modeRoot default: return modeUnknown }}
var rootCmd = &cobra.Command{ Use: "git-format", Short: "Format git commits and tags with proper conventions", Long: `git-format helps you create well-formatted Git commits and tags with propersubject length validation, body wrapping, and trailer formatting.
This tool is meant to be invoked via symlinks: git formatted-commit - Create conventionally formatted commits git formatted-tag - Create formatted annotated tags
Run 'git-format install' to create the symlinks.`, RunE: func(cmd *cobra.Command, args []string) error { return cmd.Help() },}
var commitCmd = &cobra.Command{ Use: "git-formatted-commit", Short: "Create conventionally formatted Git commits", Long: `git-formatted-commit helps you create well-formatted Git commits that followthe Conventional Commits specification with proper subject length validation,body wrapping, and trailer formatting.`, Example: `# With Assisted-bygit formatted-commit -t feat -m "do a thing" -T "Assisted-by: GLM 4.6 via Crush"
# Breaking change with descriptiongit formatted-commit -t feat -m "remove deprecated API" \ -B "The old /v1/users endpoint is removed. Use /v2/users instead."
# Breaking change with multi-line description using heredocgit formatted-commit -t feat -m "restructure config format" -B "$(cat <<'EOF'Configuration format changed from JSON to TOML.Migrate by running: ./migrate-config.shEOF)" -b "Improves readability and supports comments"
# Including scope for more precise changesgit formatted-commit -t refactor -s "web/git-bug" -m "fancy shmancy" \ -b "Had to do a weird thing because..."`, RunE: func(cmd *cobra.Command, args []string) error { subject, err := buildAndValidateSubject(commitType, scope, message, breakingChange) if err != nil { return err }
var commitMsg strings.Builder commitMsg.WriteString(subject)
if body != "" { formattedBody, err := formatBody(body) if err != nil { return fmt.Errorf("failed to format body: %w", err) } commitMsg.WriteString("\n\n") commitMsg.WriteString(formattedBody) }
if breakingChange != "" { formattedBreaking, err := formatBody("BREAKING CHANGE: " + breakingChange) if err != nil { return fmt.Errorf("failed to format breaking change: %w", err) } commitMsg.WriteString("\n\n") commitMsg.WriteString(formattedBreaking) }
if len(trailers) > 0 { trailersBlock, err := buildTrailersBlock(trailers) if err != nil { return fmt.Errorf("failed to build trailers: %w", err) } commitMsg.WriteString("\n\n") commitMsg.WriteString(trailersBlock) }
gitArgs := []string{"commit"} if add { gitArgs = append(gitArgs, "-a") } if amend { gitArgs = append(gitArgs, "--amend") } gitArgs = append(gitArgs, "-F", "-")
return runGitWithStdin(gitArgs, commitMsg.String()) },}
func init() { commitCmd.Flags().StringVarP(&commitType, "type", "t", "", "commit type (required)") commitCmd.Flags().StringVarP(&message, "message", "m", "", "commit message (required)") commitCmd.Flags().StringArrayVarP(&trailers, "trailer", "T", []string{}, "trailer in 'Sentence-case-key: value' format (optional, repeatable)") commitCmd.Flags().StringVarP(&body, "body", "b", "", "commit body (optional)") commitCmd.Flags().StringVarP(&scope, "scope", "s", "", "commit scope (optional)") commitCmd.Flags().StringVarP(&breakingChange, "breaking", "B", "", "breaking change description (optional)") commitCmd.Flags().BoolVarP(&add, "add", "a", false, "stage all modified files before committing (optional)") commitCmd.Flags().BoolVar(&amend, "amend", false, "amend the previous commit (optional)")
if err := commitCmd.MarkFlagRequired("type"); err != nil { panic(err) } if err := commitCmd.MarkFlagRequired("message"); err != nil { panic(err) }
rootCmd.AddCommand(installCmd)}
func buildAndValidateSubject(commitType, scope, message string, breaking string) (string, error) { var subject strings.Builder
subject.WriteString(commitType)
if scope != "" { subject.WriteString("(") subject.WriteString(scope) subject.WriteString(")") }
if breaking != "" { subject.WriteString("!") }
subject.WriteString(": ") subject.WriteString(message)
result := subject.String() if err := validateSubjectLength(result); err != nil { return "", err } return result, nil}
func main() { ctx := context.Background()
if version == "dev" { if info, ok := debug.ReadBuildInfo(); ok && info.Main.Version != "" && info.Main.Version != "(devel)" { version = info.Main.Version } }
var cmd *cobra.Command switch detectMode() { case modeCommit: cmd = commitCmd case modeTag: cmd = tagCmd case modeRoot: cmd = rootCmd default: fmt.Fprintln(os.Stderr, "Error: git-format must be invoked via symlink or as 'git-format'") fmt.Fprintln(os.Stderr, "") fmt.Fprintln(os.Stderr, "Run 'git-format install' to create:") fmt.Fprintln(os.Stderr, " ~/.local/bin/git-formatted-commit") fmt.Fprintln(os.Stderr, " ~/.local/bin/git-formatted-tag") fmt.Fprintln(os.Stderr, "") fmt.Fprintln(os.Stderr, "Then use: git formatted-commit ... or git formatted-tag ...") os.Exit(1) }
if err := fang.Execute(ctx, cmd, fang.WithVersion(version), fang.WithoutCompletions(), ); err != nil { os.Exit(1) }}