Skip to content

Commit

Permalink
Auto-detect increment method and syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
MMulthaupt committed Feb 8, 2021
1 parent 86cc339 commit b7e3034
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 16 deletions.
38 changes: 36 additions & 2 deletions flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,41 @@ import (
"os"
)

const FlagMajor = "major"
const FlagMinor = "minor"
const FlagAuto = "auto"

type Flags struct {
ScriptPrefix string
ScriptPrefix string
VersionIncrementMethod VersionIncrementMethod
}

type VersionIncrementMethod int

const IncrementMajor VersionIncrementMethod = 0
const IncrementMinor VersionIncrementMethod = 1
const IncrementAuto VersionIncrementMethod = 2

func Parse(args []string) *Flags {
f := Flags{}
fs := flag.NewFlagSet("app", flag.ContinueOnError)
fs.Usage = func() {}
var major, minor, auto bool
fs.BoolVar(&major, FlagMajor, false, "make a major version increment")
fs.BoolVar(&minor, FlagMinor, false, "make a minor version increment")
fs.BoolVar(&auto, FlagAuto, false, "automatically decide how to increment version (default)")
fs.Parse(args)
if auto && (major || minor) {
fmt.Println("Explicit --auto disallows usage of --major and --minor.")
os.Exit(1)
}
if major && minor {
fmt.Println("Cannot use --major and --minor at the same time.")
os.Exit(1)
}
f.VersionIncrementMethod = readVersionIncrementMethod(major, minor, auto)
if fs.NArg() > 1 {
fmt.Println("Provide at most 1 argument: script file name suffix.")
fmt.Println("Must provide only script file name suffix as last argument.")
os.Exit(1)
}
if fs.NArg() == 1 {
Expand All @@ -26,3 +50,13 @@ func Parse(args []string) *Flags {
}
return &f
}

func readVersionIncrementMethod(major, minor, auto bool) VersionIncrementMethod {
if major {
return IncrementMajor
}
if minor {
return IncrementMinor
}
return IncrementAuto
}
66 changes: 52 additions & 14 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"path/filepath"
"regexp"
"strconv"
"strings"

"github.com/setlog/fly/flags"
"github.com/setlog/panik"
Expand All @@ -18,42 +19,79 @@ func main() {
defer panik.ExitTraceTo(os.Stderr)
f := flags.Parse(os.Args[1:])
panik.OnError(os.MkdirAll(filepath.FromSlash("src/main/migration"), 0700))
scriptFilePath := filepath.FromSlash(path.Join("src/main/migration", nextFlywayScriptPrefix("src/main/migration")+f.ScriptPrefix+".sql"))
panik.OnError(ioutil.WriteFile(scriptFilePath, []byte("USE ${schema_client};\n\n\n"), 0600))
scriptFilePath := filepath.FromSlash(path.Join("src/main/migration", nextFlywayScriptPrefix("src/main/migration", f.VersionIncrementMethod)+f.ScriptPrefix+".sql"))
panik.OnError(ioutil.WriteFile(scriptFilePath, []byte("USE ${"+extractSchemaName(f.ScriptPrefix)+"};\n\n\n"), 0600))
openInVsCode(scriptFilePath)
}

func nextFlywayScriptPrefix(folderPath string) string {
major, minor := nextFlywayScriptVersion(folderPath)
return fmt.Sprintf("V%03d.%03d__", major, minor)
func nextFlywayScriptPrefix(folderPath string, incrementMethod flags.VersionIncrementMethod) string {
major, minor := nextFlywayScriptVersion(folderPath, incrementMethod)
return fmt.Sprintf("V%s.%s__", major, minor)
}

func nextFlywayScriptVersion(folderPath string) (major, minor int) {
func extractSchemaName(scriptPrefix string) string {
adminIndex := strings.Index(scriptPrefix, "_admin")
if adminIndex == 3 {
return "schema_admin"
}
if adminIndex > 3 {
return "schema_client_admin"
}
return "schema_client"
}

func nextFlywayScriptVersion(folderPath string, incrementMethod flags.VersionIncrementMethod) (major, minor string) {
latestScriptFileName, wasMinorIncrement := latestFlywayScriptFileName(folderPath)
incrementMinor := wasMinorIncrement
if incrementMethod == flags.IncrementMajor {
incrementMinor = false
} else if incrementMethod == flags.IncrementMinor {
incrementMinor = true
}
if latestScriptFileName == "" {
return incrementFlywayScriptVersion("000", "000", incrementMinor)
}
major, minor, _ = getFlywayScriptVersion(latestScriptFileName)
return incrementFlywayScriptVersion(major, minor, wasMinorIncrement)
}

func latestFlywayScriptFileName(folderPath string) (scriptFileName string, wasMinorIncrement bool) {
largestMajor, largestMinor := 1, 0
infos, err := ioutil.ReadDir(filepath.FromSlash(folderPath))
panik.OnError(err)
for _, info := range infos {
if !info.IsDir() {
major, minor, err := getFlywayScriptVersion(info.Name())
if err == nil {
if major > largestMajor {
largestMajor, largestMinor = major, minor
} else if major == largestMajor && minor > largestMinor {
largestMinor = minor
if atoi(major) > largestMajor {
largestMajor, largestMinor = atoi(major), atoi(minor)
scriptFileName = info.Name()
wasMinorIncrement = false
} else if atoi(major) == largestMajor && atoi(minor) > largestMinor {
largestMinor = atoi(minor)
scriptFileName = info.Name()
wasMinorIncrement = true
}
}
}
}
return largestMajor, largestMinor + 1
return scriptFileName, wasMinorIncrement
}

func getFlywayScriptVersion(fileName string) (major, minor int, err error) {
func getFlywayScriptVersion(fileName string) (major, minor string, err error) {
r := regexp.MustCompile(`^(V|v)([0-9]+)\.([0-9]+)__.+\.sql$`)
if !r.Match([]byte(fileName)) {
return 0, 0, fmt.Errorf("regexp mismatch")
return "", "", fmt.Errorf("regexp mismatch")
}
versions := regexp.MustCompile("[0-9]+").FindAllString(fileName, 2)
return atoi(versions[0]), atoi(versions[1]), nil
return versions[0], versions[1], nil
}

func incrementFlywayScriptVersion(major, minor string, incrementMinor bool) (newMajor, newMinor string) {
if incrementMinor {
return major, fmt.Sprintf(fmt.Sprintf("%%0%dd", len(minor)), atoi(minor)+1)
}
return fmt.Sprintf(fmt.Sprintf("%%0%dd", len(major)), atoi(major)+1), fmt.Sprintf(fmt.Sprintf("%%%d0d", len(minor)), 1)
}

func atoi(s string) int {
Expand Down

0 comments on commit b7e3034

Please sign in to comment.