diff --git a/src/main.go b/src/main.go index 5bd5cfc..c37fa19 100644 --- a/src/main.go +++ b/src/main.go @@ -186,6 +186,24 @@ func versionString() string { return fmt.Sprintf("%s (%s)", AppVersion, AppCommit) } +func normalizeArgs(args []string) ([]string, error) { + if len(args) == 0 { + return args, nil + } + first := strings.TrimSpace(args[0]) + if first == "" || strings.HasPrefix(first, "-") { + return args, nil + } + switch strings.ToLower(first) { + case "major", "minor", "patch": + return append([]string{"-part=" + strings.ToLower(first)}, args[1:]...), nil + case "build": + return append([]string{"-part=patch"}, args[1:]...), nil + default: + return nil, fmt.Errorf("unknown positional argument %q (expected major/minor/patch/build or flags)", first) + } +} + func main() { const cfg_name = ".bumpversion.cfg" args := os.Args[1:] @@ -198,24 +216,41 @@ func main() { // Печатаем название и версию при старте fmt.Printf("Starting %s version %s\n", AppName, versionString()) + normalizedArgs, err := normalizeArgs(args) + if err != nil { + fmt.Printf("Error: %v\n", err) + os.Exit(2) + } + bc, err := getBumpConfig(cfg_name) if err != nil { log.Fatalf("Error reading bumpversion configuration: %v", err) } // Парсинг аргументов командной строки - part := flag.String("part", "patch", "Part of the version to bump (major/minor/patch)") + part := flag.String("part", "patch", "Part of the version to bump (major/minor/patch). Positional form is also supported: bumpversion.run major") commit := flag.Bool("commit", false, "Create a commit") noCommit := flag.Bool("no-commit", false, "Do not create a commit") tag := flag.Bool("tag", false, "Add a git tag") noTag := flag.Bool("no-tag", false, "Do not add a git tag") noFatal := flag.Bool("no-fatal", false, "Do not fail if a configured file does not contain the current version") push := flag.Bool("push", false, "Force push to repository") - flag.Parse() + if err := flag.CommandLine.Parse(normalizedArgs); err != nil { + log.Fatalf("Error parsing flags: %v", err) + } // Обработка флагов - if *part != "major" && *part != "minor" && *part != "patch" { - fmt.Printf("Error: part must be one of 'major', 'minor', or 'patch'. Got '%s'\n", *part) + if flag.NArg() != 0 { + fmt.Printf("Error: unexpected arguments: %v\n", flag.Args()) + os.Exit(2) + } + + partValue := strings.ToLower(strings.TrimSpace(*part)) + if partValue == "build" { + partValue = "patch" + } + if partValue != "major" && partValue != "minor" && partValue != "patch" { + fmt.Printf("Error: part must be one of 'major', 'minor', or 'patch' (alias: build). Got '%s'\n", *part) os.Exit(1) } @@ -229,7 +264,7 @@ func main() { log.Fatalf("Error resolving tag flags: %v", err) } - newVersion, err := bumpVersion(bc, *part) + newVersion, err := bumpVersion(bc, partValue) if err != nil { log.Fatalf("Error bumping version: %v", err) } diff --git a/src/main_test.go b/src/main_test.go index 5cdc4eb..f19de60 100644 --- a/src/main_test.go +++ b/src/main_test.go @@ -121,6 +121,37 @@ func TestBumpVersion(t *testing.T) { } } +func TestNormalizeArgs(t *testing.T) { + tests := []struct { + name string + in []string + want []string + wantErr bool + }{ + {name: "empty", in: nil, want: nil}, + {name: "flags_only", in: []string{"--tag"}, want: []string{"--tag"}}, + {name: "positional_major", in: []string{"major"}, want: []string{"-part=major"}}, + {name: "positional_minor_plus_flags", in: []string{"minor", "--tag"}, want: []string{"-part=minor", "--tag"}}, + {name: "positional_build_alias", in: []string{"build"}, want: []string{"-part=patch"}}, + {name: "unknown_positional", in: []string{"wat"}, wantErr: true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := normalizeArgs(tt.in) + if (err != nil) != tt.wantErr { + t.Fatalf("normalizeArgs error = %v, wantErr %v", err, tt.wantErr) + } + if err != nil { + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Fatalf("normalizeArgs = %#v, want %#v", got, tt.want) + } + }) + } +} + func TestBumpVersionInvalidCurrent(t *testing.T) { bc := &BumpConfig{ CurrentVersion: "1.2",