Application

This commit is contained in:
2025-03-29 20:09:41 +03:00
parent 3f9d79f842
commit fa6dbeaaac
3 changed files with 225 additions and 0 deletions

7
go.mod Normal file
View File

@@ -0,0 +1,7 @@
module src
go 1.24.0
require github.com/go-ini/ini v1.67.0
require github.com/stretchr/testify v1.10.0 // indirect

10
go.sum Normal file
View File

@@ -0,0 +1,10 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

208
src/main.go Normal file
View File

@@ -0,0 +1,208 @@
package main
import (
"flag"
"fmt"
"log"
"os"
"os/exec"
"regexp"
"strconv"
"strings"
"github.com/go-ini/ini"
)
type BumpConfig struct {
CurrentVersion string
Commit bool
Tag bool
TagName string
Parse string
Serialize string
Message string
FilePaths []string
}
func loadConfig(configPath string) (*ini.File, error) {
return ini.Load(configPath)
}
func getBumpConfig(cfg *ini.File) (*BumpConfig, error) {
sec, err := cfg.GetSection("bumpversion")
if err != nil {
return nil, fmt.Errorf("missing [bumpversion] section: %w", err)
}
bc := &BumpConfig{
CurrentVersion: sec.Key("current_version").String(),
Commit: sec.Key("commit").MustBool(false),
Tag: sec.Key("tag").MustBool(false),
TagName: sec.Key("tag_name").String(),
Parse: sec.Key("parse").String(),
Serialize: strings.TrimSpace(sec.Key("serialize").String()),
Message: sec.Key("message").String(),
}
// Получим список файлов для обновления из секций, начинающихся с "bumpversion:file:"
for _, s := range cfg.Sections() {
if strings.HasPrefix(s.Name(), "bumpversion:file:") {
// Имя файла после последнего двоеточия:
parts := strings.SplitN(s.Name(), ":", 3)
if len(parts) == 3 {
filePath := strings.TrimSpace(parts[2])
bc.FilePaths = append(bc.FilePaths, filePath)
}
}
}
return bc, nil
}
// bumpVersion парсит current_version, увеличивает нужную часть и возвращает новую версию.
func bumpVersion(bc *BumpConfig, part string) (string, error) {
re, err := regexp.Compile(bc.Parse)
if err != nil {
return "", fmt.Errorf("failed to compile parse regex: %w", err)
}
matches := re.FindStringSubmatch(bc.CurrentVersion)
if matches == nil {
return "", fmt.Errorf("current version %s does not match parse pattern", bc.CurrentVersion)
}
// Создадим карту групп по именам
groupNames := re.SubexpNames()
var major, minor, patch int
for i, name := range groupNames {
switch name {
case "major":
major, err = strconv.Atoi(matches[i])
if err != nil {
return "", err
}
case "minor":
minor, err = strconv.Atoi(matches[i])
if err != nil {
return "", err
}
case "patch":
patch, err = strconv.Atoi(matches[i])
if err != nil {
return "", err
}
}
}
switch part {
case "major":
major++
minor = 0
patch = 0
case "minor":
minor++
patch = 0
case "patch":
patch++
default:
return "", fmt.Errorf("unknown bump part: %s", part)
}
newVersion := bc.Serialize
newVersion = strings.ReplaceAll(newVersion, "{major}", fmt.Sprintf("%d", major))
newVersion = strings.ReplaceAll(newVersion, "{minor}", fmt.Sprintf("%d", minor))
newVersion = strings.ReplaceAll(newVersion, "{patch}", fmt.Sprintf("%d", patch))
return newVersion, nil
}
func updateFiles(filePaths []string, oldVersion, newVersion string) {
for _, path := range filePaths {
data, err := os.ReadFile(path)
if err != nil {
log.Printf("Unable to read file %s: %v", path, err)
continue
}
newData := strings.ReplaceAll(string(data), oldVersion, newVersion)
if err := os.WriteFile(path, []byte(newData), 0644); err != nil {
log.Printf("Unable to write file %s: %v", path, err)
} else {
log.Printf("Updated file: %s", path)
}
}
}
func gitCommitAndTag(currentVersion, newVersion string, bc *BumpConfig) error {
commitMsg := strings.ReplaceAll(bc.Message, "{current_version}", currentVersion)
commitMsg = strings.ReplaceAll(commitMsg, "{new_version}", newVersion)
if bc.Commit {
if err := exec.Command("git", "add", ".").Run(); err != nil {
return fmt.Errorf("git add error: %w", err)
}
if err := exec.Command("git", "commit", "-m", commitMsg).Run(); err != nil {
return fmt.Errorf("git commit error: %w", err)
}
log.Printf("Committed with message: %s", commitMsg)
}
if bc.Tag {
tagName := strings.ReplaceAll(bc.TagName, "{new_version}", newVersion)
if err := exec.Command("git", "tag", tagName).Run(); err != nil {
return fmt.Errorf("git tag error: %w", err)
}
log.Printf("Created git tag: %s", tagName)
}
return nil
}
func updateConfigFile(configPath string, newVersion string) error {
cfg, err := ini.Load(configPath)
if err != nil {
return err
}
cfg.Section("bumpversion").Key("current_version").SetValue(newVersion)
return cfg.SaveTo(configPath)
}
// Версия приложения
const (
AppName = "BumpVersion"
AppVersion = "0.1.0"
)
func main() {
// Проверяем аргументы командной строки
args := os.Args[1:]
if len(args) > 0 && strings.ToLower(args[0]) == "--version" {
fmt.Printf("%s version %s\n", AppName, AppVersion)
return
}
// Печатаем название и версию при старте
fmt.Printf("Starting %s version %s\n", AppName, AppVersion)
part := flag.String("part", "patch", "Part to bump: major, minor, patch")
configPath := flag.String("config", ".bumpversion.cfg", "Path to config file")
flag.Parse()
cfgFile, err := loadConfig(*configPath)
if err != nil {
log.Fatalf("Error loading config: %v", err)
}
bc, err := getBumpConfig(cfgFile)
if err != nil {
log.Fatalf("Error reading bumpversion configuration: %v", err)
}
fmt.Printf("Current version: %s\n", bc.CurrentVersion)
newVersion, err := bumpVersion(bc, *part)
if err != nil {
log.Fatalf("Error bumping version: %v", err)
}
fmt.Printf("New version: %s\n", newVersion)
// Обновляем файлы, указанные в конфигурации
updateFiles(bc.FilePaths, bc.CurrentVersion, newVersion)
// Выполняем git commit и tag, если требуется
if err := gitCommitAndTag(bc.CurrentVersion, newVersion, bc); err != nil {
log.Printf("Git commit/tag error: %v", err)
}
// Обновляем конфигурационный файл
if err := updateConfigFile(*configPath, newVersion); err != nil {
log.Printf("Error updating config file: %v", err)
}
}