From 398b199b17f9bfa44d39a62ea968e13da770036e Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Mon, 30 Oct 2023 14:39:46 +0330 Subject: [PATCH 01/69] Add gen-migdoc script --- scripts/gen-migdoc | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100755 scripts/gen-migdoc diff --git a/scripts/gen-migdoc b/scripts/gen-migdoc new file mode 100755 index 0000000000..7b4984f3fe --- /dev/null +++ b/scripts/gen-migdoc @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + +set -e + +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P) +IGNITE_REPO="https://github.com/ignite/cli.git" +SCAFFOLD_CMDS=( + "chain example --no-module --skip-git" + "module example --params param1:string,param2:bool --yes" + "list list1 field1:string field2:int --module example --yes" +) +DIFF_EXCLUDE=( + ".git" + "*.md" + "go.sum" +) + +# Cleans up temporary files and directories +clean_up() { + test -d "$1" && rm -fr "$1" +} + +# Checks out to the given version tag and builds the Ignite CLI +checkout_and_build_ignite() ( + local ignite_dir="$1" version="$2" + + cd "$ignite_dir" + git checkout --quiet "$version" && make build > /dev/null || exit 1 +) + +# Runs list of scaffold commands with the given ignite cli +scaffold_chain() { + local ignite_cmd="$1" scaffold_path="$2" + + for cmd in "${SCAFFOLD_CMDS[@]}"; do + $ignite_cmd scaffold $cmd --path $scaffold_path || (echo "Failed at scaffolding $cmd"; exit 1) + done +} + +# Generates diff between two directories +generate_diff() { + local first_path="$1" second_path="$2" + + exclude_flags=() + for exclude in "${DIFF_EXCLUDE[@]}"; do exclude_flags+=(-x "$exclude"); done + + diff -bur "$first_path" "$second_path" "${exclude_flags[@]}" +} + +main() { + tmp_dir=$(mktemp -d) + trap "clean_up $tmp_dir" SIGINT SIGTERM ERR EXIT + + git clone "$IGNITE_REPO" "$tmp_dir/ignite" --quiet + + # Gets the latest version and the previous version + versions=$(git tag --list --sort=version:refname 'v*') + new_version=$(echo "${versions}" | tail -n 1); mkdir -p "$tmp_dir/$new_version" + previous_version=$(echo "${versions}" | tail -n 3 | head -n 1); mkdir -p "$tmp_dir/$previous_version" + echo "Generating migration documentation: ${previous_version} -> ${new_version}" + + checkout_and_build_ignite "$tmp_dir/ignite" "$previous_version" + scaffold_chain "$tmp_dir/ignite/dist/ignite" "$tmp_dir/$previous_version" + + checkout_and_build_ignite "$tmp_dir/ignite" "$new_version" + scaffold_chain "$tmp_dir/ignite/dist/ignite" "$tmp_dir/$new_version" + + # Getting diff between the two chains + generate_diff "$tmp_dir/$previous_version" "$tmp_dir/$new_version" > "$SCRIPT_DIR"/"$previous_version"-"$new_version".diff +} + +main \ No newline at end of file From 6a0d76eabced77ade2b7258591de9714956e1530 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Mon, 30 Oct 2023 14:55:13 +0330 Subject: [PATCH 02/69] Fix gen-migdoc script --- scripts/gen-migdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/gen-migdoc b/scripts/gen-migdoc index 7b4984f3fe..5ff94e3405 100755 --- a/scripts/gen-migdoc +++ b/scripts/gen-migdoc @@ -33,7 +33,7 @@ scaffold_chain() { local ignite_cmd="$1" scaffold_path="$2" for cmd in "${SCAFFOLD_CMDS[@]}"; do - $ignite_cmd scaffold $cmd --path $scaffold_path || (echo "Failed at scaffolding $cmd"; exit 1) + $ignite_cmd scaffold $cmd --path $scaffold_path > /dev/null || (echo "Failed at scaffolding $cmd"; exit 1) done } @@ -56,7 +56,7 @@ main() { # Gets the latest version and the previous version versions=$(git tag --list --sort=version:refname 'v*') new_version=$(echo "${versions}" | tail -n 1); mkdir -p "$tmp_dir/$new_version" - previous_version=$(echo "${versions}" | tail -n 3 | head -n 1); mkdir -p "$tmp_dir/$previous_version" + previous_version=$(echo "${versions}" | tail -n 2 | head -n 1); mkdir -p "$tmp_dir/$previous_version" echo "Generating migration documentation: ${previous_version} -> ${new_version}" checkout_and_build_ignite "$tmp_dir/ignite" "$previous_version" From e5bd24913e4c30bad1e1d4191c140b53031e081d Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Mon, 13 Nov 2023 16:38:52 +0330 Subject: [PATCH 03/69] Add gen-mig-docs tool --- go.mod | 1 + go.sum | 2 + ignite/internal/tools/gen-mig-docs/diff.go | 122 +++++++++++++ ignite/internal/tools/gen-mig-docs/main.go | 199 +++++++++++++++++++++ 4 files changed, 324 insertions(+) create mode 100644 ignite/internal/tools/gen-mig-docs/diff.go create mode 100644 ignite/internal/tools/gen-mig-docs/main.go diff --git a/go.mod b/go.mod index 14bd50e4d4..fe441e14e8 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/99designs/keyring v1.2.1 github.com/AlecAivazis/survey/v2 v2.3.6 github.com/DATA-DOG/go-sqlmock v1.5.0 + github.com/Masterminds/semver/v3 v3.2.0 github.com/blang/semver/v4 v4.0.0 github.com/briandowns/spinner v1.23.0 github.com/buger/jsonparser v1.1.1 diff --git a/go.sum b/go.sum index ba6420ea47..6bf26091b5 100644 --- a/go.sum +++ b/go.sum @@ -92,6 +92,8 @@ github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 h1:+r1rSv4gvYn0wmRjC8X7I github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmcxJL+UEG2f8cQploZm1mR/v6BW0mU0= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= diff --git a/ignite/internal/tools/gen-mig-docs/diff.go b/ignite/internal/tools/gen-mig-docs/diff.go new file mode 100644 index 0000000000..2d20aee68e --- /dev/null +++ b/ignite/internal/tools/gen-mig-docs/diff.go @@ -0,0 +1,122 @@ +package main + +import ( + "os" + "path/filepath" + "strings" + + "github.com/hexops/gotextdiff" + "github.com/hexops/gotextdiff/myers" + "github.com/hexops/gotextdiff/span" +) + +var diffExceptions = []string{ + "*.md", + "go.sum", +} + +// Diff returns unified diff between all files in two directories recursively. +func Diff(dir1, dir2 string) ([]gotextdiff.Unified, error) { + var ( + diffs []gotextdiff.Unified + marked map[string]struct{} = make(map[string]struct{}) + ) + + dirsLCP := longestCommonPrefix(dir1, dir2) + + // Consider dir1 as reference and walk through all of the files comparing them with files in dir2. + err := filepath.Walk(dir1, func(path string, info os.FileInfo, err error) error { + if info.IsDir() { + return nil + } + + for _, exception := range diffExceptions { + if match, _ := filepath.Match(exception, info.Name()); match { + return nil + } + } + + relPath, err := filepath.Rel(dir1, path) + if err != nil { + return err + } + marked[relPath] = struct{}{} + + file1, err := os.ReadFile(path) + if err != nil { + return err + } + str1 := string(file1) + + file2, err := os.ReadFile(filepath.Join(dir2, relPath)) + if !os.IsNotExist(err) && err != nil { + return err + } + str2 := string(file2) + + edits := myers.ComputeEdits(span.URIFromPath(relPath), str1, str2) + if len(edits) > 0 { + diffs = append(diffs, gotextdiff.ToUnified(strings.TrimPrefix(path, dirsLCP), strings.TrimPrefix(filepath.Join(dir2, relPath), dirsLCP), str1, edits)) + } + return nil + }) + if err != nil { + return diffs, err + } + + // Walk through all of the files in dir2 that were not compared with files in dir1. + err = filepath.Walk(dir2, func(path string, info os.FileInfo, err error) error { + if info.IsDir() { + return nil + } + + for _, exception := range diffExceptions { + if match, _ := filepath.Match(exception, info.Name()); match { + return nil + } + } + + relPath, err := filepath.Rel(dir2, path) + if err != nil { + return err + } + if _, ok := marked[relPath]; ok { + return nil + } + + str1 := "" + + file2, err := os.ReadFile(path) + if err != nil { + return err + } + str2 := string(file2) + + edits := myers.ComputeEdits(span.URIFromPath(relPath), str1, str2) + diffs = append(diffs, gotextdiff.ToUnified(strings.TrimPrefix(filepath.Join(dir1, relPath), dirsLCP), strings.TrimPrefix(path, dirsLCP), str1, edits)) + return nil + }) + return diffs, nil +} + +func longestCommonPrefix(strs ...string) string { + longest := strings.Split(strs[0], string(filepath.Separator)) + + cmp := func(a []string) { + if len(a) < len(longest) { + longest = longest[:len(a)] + } + for i := 0; i < len(longest); i++ { + if a[i] != longest[i] { + longest = longest[:i] + return + } + } + } + + for i := 1; i < len(strs); i++ { + r := strings.Split(strs[i], string(filepath.Separator)) + cmp(r) + } + return filepath.Join(longest...) +} diff --git a/ignite/internal/tools/gen-mig-docs/main.go b/ignite/internal/tools/gen-mig-docs/main.go new file mode 100644 index 0000000000..b3523c4c34 --- /dev/null +++ b/ignite/internal/tools/gen-mig-docs/main.go @@ -0,0 +1,199 @@ +package main + +import ( + "flag" + "fmt" + "io" + "log" + "os" + "os/exec" + "path/filepath" + "sort" + "strings" + + "github.com/Masterminds/semver/v3" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "github.com/pkg/errors" +) + +const ( + igniteCliRepository = "http://github.com/ignite/cli.git" + igniteBinaryPath = "dist/ignite" +) + +var scaffoldCommands = map[string][]string{ + "chain": {"chain example --no-module --skip-git"}, + "module": {"chain example --skip-git"}, + "list": { + "chain example --skip-git", + "list list1 field1:string field2:int --module example", + }, +} + +func main() { + var logger = log.New(os.Stdout, "", log.LstdFlags) + + fromFlag := flag.String("from", "", "Semver tag to generate migration document from") + toFlag := flag.String("to", "", "Semver tag to generate migration document to") + flag.Parse() + + var ( + fromVer, toVer *semver.Version + err error + ) + if fromFlag != nil && *fromFlag != "" { + fromVer, err = semver.NewVersion(*fromFlag) + if err != nil { + logger.Fatalf("Invalid semver tag: %s", *fromFlag) + } + } + if toFlag != nil && *toFlag != "" { + toVer, err = semver.NewVersion(*toFlag) + if err != nil { + logger.Fatalf("Invalid semver tag: %s", *toFlag) + } + } + + tmpdir, err := os.MkdirTemp("", "migdoc") + defer os.RemoveAll(tmpdir) + if err != nil { + logger.Fatalln(err) + } + logger.Println("Created temporary directory:", tmpdir) + + logger.Println("Cloning", igniteCliRepository) + repoDir := filepath.Join(tmpdir, "src/github.com/ignite/cli") + repo, err := git.PlainClone(repoDir, false, &git.CloneOptions{ + URL: igniteCliRepository, + Progress: os.Stdout, + }) + if err != nil { + logger.Fatalln(err) + } + + tags, err := repo.Tags() + if err != nil { + logger.Fatalln(err) + } + + var versions semver.Collection + err = tags.ForEach(func(ref *plumbing.Reference) error { + name := ref.Name() + if name.IsTag() { + ver, err := semver.NewVersion(name.Short()) + if err != nil { + // Do nothing as it's not a semver tag + return nil + } + versions = append(versions, ver) + } + return nil + }) + if err != nil { + logger.Fatalln(err) + } + + if versions.Len() < 2 { + logger.Fatalln("At least two semver tags are required") + } + + sort.Sort(versions) + + if fromVer == nil { + if toVer != nil { + sort.Search(versions.Len(), func(i int) bool { + if versions[i].LessThan(toVer) { + fromVer = versions[i] + return false + } + return true + }) + } else { + fromVer = versions[versions.Len()-2] + } + } + if toVer == nil { + toVer = versions[versions.Len()-1] + } + + logger.Printf("Generating migration document for %s->%s\n\n", fromVer, toVer) + + // Checkout to previous tag and build ignite cli with make build + logger.Printf("Checking out to %s\n", fromVer) + wt, err := repo.Worktree() + if err != nil { + logger.Fatalln(err) + } + err = wt.Checkout(&git.CheckoutOptions{ + Branch: plumbing.NewTagReferenceName(fromVer.Original()), + }) + if err != nil { + logger.Fatalln(err) + } + + logger.Println("Building ignite cli...") + err = runCommand(repoDir, "make", "build") + if err != nil { + logger.Fatalln(err) + } + + err = executeScaffoldCommands(logger, filepath.Join(repoDir, igniteBinaryPath), filepath.Join(tmpdir, fromVer.Original())) + if err != nil { + logger.Fatalln(err) + } + + // Checkout to latest tag and build ignite cli with make build + logger.Printf("Checking out to %s\n", toVer) + err = wt.Checkout(&git.CheckoutOptions{ + Branch: plumbing.NewTagReferenceName(toVer.Original()), + }) + if err != nil { + logger.Fatalln(err) + } + + logger.Println("Building ignite cli...") + err = runCommand(repoDir, "make", "build") + if err != nil { + logger.Fatalln(err) + } + + err = executeScaffoldCommands(logger, filepath.Join(repoDir, igniteBinaryPath), filepath.Join(tmpdir, toVer.Original())) + if err != nil { + logger.Fatalln(err) + } + + // Run diff between two directories + logger.Println("Generating diff...") + diffs, err := Diff(filepath.Join(tmpdir, fromVer.Original()), filepath.Join(tmpdir, toVer.Original())) + if err != nil { + logger.Fatalln(err) + } + for _, diff := range diffs { + fmt.Println(diff) + } +} + +func runCommand(dir, name string, args ...string) error { + cmd := exec.Command(name, args...) + cmd.Dir = dir + cmd.Stdout = io.Discard + cmd.Stderr = os.Stderr + return cmd.Run() +} + +func executeScaffoldCommands(logger *log.Logger, ignitePath string, outputDir string) error { + for name, cmds := range scaffoldCommands { + logger.Println("Scaffolding", name) + for _, cmd := range cmds { + args := []string{"scaffold"} + args = append(args, strings.Fields(cmd)...) + args = append(args, "--path", filepath.Join(outputDir, name)) + err := runCommand("", ignitePath, args...) + if err != nil { + return errors.Wrapf(err, "failed to execute ignite scaffold command: %s", cmd) + } + } + } + return nil +} From 0dc54bd7f71de404c56b35181b3682e848aec437 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Sat, 18 Nov 2023 20:45:55 +0330 Subject: [PATCH 04/69] Add exceptions and more test cases to migdoc --- ignite/internal/tools/gen-mig-docs/diff.go | 3 ++ ignite/internal/tools/gen-mig-docs/main.go | 53 ++++++++++++++++++++-- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/ignite/internal/tools/gen-mig-docs/diff.go b/ignite/internal/tools/gen-mig-docs/diff.go index 2d20aee68e..66877d9f11 100644 --- a/ignite/internal/tools/gen-mig-docs/diff.go +++ b/ignite/internal/tools/gen-mig-docs/diff.go @@ -13,6 +13,9 @@ import ( var diffExceptions = []string{ "*.md", "go.sum", + "*_test.go", + "*.pb.go", + "*.pb.gw.go", } // Diff returns unified diff between all files in two directories recursively. diff --git a/ignite/internal/tools/gen-mig-docs/main.go b/ignite/internal/tools/gen-mig-docs/main.go index b3523c4c34..a8ef03e242 100644 --- a/ignite/internal/tools/gen-mig-docs/main.go +++ b/ignite/internal/tools/gen-mig-docs/main.go @@ -3,7 +3,6 @@ package main import ( "flag" "fmt" - "io" "log" "os" "os/exec" @@ -27,7 +26,47 @@ var scaffoldCommands = map[string][]string{ "module": {"chain example --skip-git"}, "list": { "chain example --skip-git", - "list list1 field1:string field2:int --module example", + "list list1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", + "map map1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", + }, + "map": { + "chain example --skip-git", + "map map1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", + }, + "single": { + "chain example --skip-git", + "single single1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", + }, + "type": { + "chain example --skip-git", + "type type1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", + }, + "message": { + "chain example --skip-git", + "message message1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", + }, + // "query": { + // "chain example --skip-git", + // "query query1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", + // }, + "packet": { + "chain example --no-module --skip-git", + "module example --ibc", + "chain example --skip-git", + "packet packet1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", + }, + "band": { + "chain example --no-module --skip-git", + "module example --ibc", + "band band1 --module example --yes", + }, + "vue": { + "chain example --skip-git", + "vue", + }, + "react": { + "chain example --skip-git", + "react", }, } @@ -169,15 +208,21 @@ func main() { if err != nil { logger.Fatalln(err) } + outf, err := os.Create(fmt.Sprintf("migdoc-%s-%s.diff", fromVer, toVer)) + if err != nil { + logger.Fatalln(err) + } + defer outf.Close() for _, diff := range diffs { - fmt.Println(diff) + outf.WriteString(fmt.Sprint(diff)) + outf.WriteString("\n") } } func runCommand(dir, name string, args ...string) error { cmd := exec.Command(name, args...) cmd.Dir = dir - cmd.Stdout = io.Discard + cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return cmd.Run() } From 2cad27b1981252fa27d97978f0ddd2f42598b0a9 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Tue, 21 Nov 2023 18:48:14 +0330 Subject: [PATCH 05/69] Add diff subtraction and cleanup --- ignite/internal/tools/gen-mig-docs/diff.go | 125 ----- ignite/internal/tools/gen-mig-docs/main.go | 563 +++++++++++++++++---- 2 files changed, 476 insertions(+), 212 deletions(-) delete mode 100644 ignite/internal/tools/gen-mig-docs/diff.go diff --git a/ignite/internal/tools/gen-mig-docs/diff.go b/ignite/internal/tools/gen-mig-docs/diff.go deleted file mode 100644 index 66877d9f11..0000000000 --- a/ignite/internal/tools/gen-mig-docs/diff.go +++ /dev/null @@ -1,125 +0,0 @@ -package main - -import ( - "os" - "path/filepath" - "strings" - - "github.com/hexops/gotextdiff" - "github.com/hexops/gotextdiff/myers" - "github.com/hexops/gotextdiff/span" -) - -var diffExceptions = []string{ - "*.md", - "go.sum", - "*_test.go", - "*.pb.go", - "*.pb.gw.go", -} - -// Diff returns unified diff between all files in two directories recursively. -func Diff(dir1, dir2 string) ([]gotextdiff.Unified, error) { - var ( - diffs []gotextdiff.Unified - marked map[string]struct{} = make(map[string]struct{}) - ) - - dirsLCP := longestCommonPrefix(dir1, dir2) - - // Consider dir1 as reference and walk through all of the files comparing them with files in dir2. - err := filepath.Walk(dir1, func(path string, info os.FileInfo, err error) error { - if info.IsDir() { - return nil - } - - for _, exception := range diffExceptions { - if match, _ := filepath.Match(exception, info.Name()); match { - return nil - } - } - - relPath, err := filepath.Rel(dir1, path) - if err != nil { - return err - } - marked[relPath] = struct{}{} - - file1, err := os.ReadFile(path) - if err != nil { - return err - } - str1 := string(file1) - - file2, err := os.ReadFile(filepath.Join(dir2, relPath)) - if !os.IsNotExist(err) && err != nil { - return err - } - str2 := string(file2) - - edits := myers.ComputeEdits(span.URIFromPath(relPath), str1, str2) - if len(edits) > 0 { - diffs = append(diffs, gotextdiff.ToUnified(strings.TrimPrefix(path, dirsLCP), strings.TrimPrefix(filepath.Join(dir2, relPath), dirsLCP), str1, edits)) - } - return nil - }) - if err != nil { - return diffs, err - } - - // Walk through all of the files in dir2 that were not compared with files in dir1. - err = filepath.Walk(dir2, func(path string, info os.FileInfo, err error) error { - if info.IsDir() { - return nil - } - - for _, exception := range diffExceptions { - if match, _ := filepath.Match(exception, info.Name()); match { - return nil - } - } - - relPath, err := filepath.Rel(dir2, path) - if err != nil { - return err - } - if _, ok := marked[relPath]; ok { - return nil - } - - str1 := "" - - file2, err := os.ReadFile(path) - if err != nil { - return err - } - str2 := string(file2) - - edits := myers.ComputeEdits(span.URIFromPath(relPath), str1, str2) - diffs = append(diffs, gotextdiff.ToUnified(strings.TrimPrefix(filepath.Join(dir1, relPath), dirsLCP), strings.TrimPrefix(path, dirsLCP), str1, edits)) - return nil - }) - return diffs, nil -} - -func longestCommonPrefix(strs ...string) string { - longest := strings.Split(strs[0], string(filepath.Separator)) - - cmp := func(a []string) { - if len(a) < len(longest) { - longest = longest[:len(a)] - } - for i := 0; i < len(longest); i++ { - if a[i] != longest[i] { - longest = longest[:i] - return - } - } - } - - for i := 1; i < len(strs); i++ { - r := strings.Split(strs[i], string(filepath.Separator)) - cmp(r) - } - return filepath.Join(longest...) -} diff --git a/ignite/internal/tools/gen-mig-docs/main.go b/ignite/internal/tools/gen-mig-docs/main.go index a8ef03e242..b6f672de91 100644 --- a/ignite/internal/tools/gen-mig-docs/main.go +++ b/ignite/internal/tools/gen-mig-docs/main.go @@ -1,11 +1,12 @@ package main import ( + "context" "flag" "fmt" + "io/fs" "log" "os" - "os/exec" "path/filepath" "sort" "strings" @@ -13,63 +14,72 @@ import ( "github.com/Masterminds/semver/v3" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" + "github.com/hexops/gotextdiff" + "github.com/hexops/gotextdiff/myers" + "github.com/hexops/gotextdiff/span" + "github.com/ignite/cli/ignite/pkg/cmdrunner/exec" + "github.com/ignite/cli/ignite/pkg/cmdrunner/step" "github.com/pkg/errors" ) const ( igniteCliRepository = "http://github.com/ignite/cli.git" igniteBinaryPath = "dist/ignite" + igniteRepoPath = "src/github.com/ignite/cli" ) var scaffoldCommands = map[string][]string{ - "chain": {"chain example --no-module --skip-git"}, - "module": {"chain example --skip-git"}, + "chain": {"chain example --no-module"}, + "module": {"chain example"}, "list": { - "chain example --skip-git", - "list list1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", - "map map1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", + "chain example", + "list list1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, "map": { - "chain example --skip-git", - "map map1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", + "chain example", + "map map1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, "single": { - "chain example --skip-git", - "single single1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", + "chain example", + "single single1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, "type": { - "chain example --skip-git", - "type type1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", + "chain example", + "type type1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, "message": { - "chain example --skip-git", - "message message1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", + "chain example", + "message message1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, - // "query": { - // "chain example --skip-git", - // "query query1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", - // }, - "packet": { - "chain example --no-module --skip-git", - "module example --ibc", - "chain example --skip-git", - "packet packet1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example", + "query": { + "chain example", + "query query1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints --module example --yes", }, - "band": { - "chain example --no-module --skip-git", + "packet": { + "chain example --no-module", "module example --ibc", - "band band1 --module example --yes", + "chain example", + "packet packet1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, "vue": { - "chain example --skip-git", + "chain example", "vue", }, "react": { - "chain example --skip-git", + "chain example", "react", }, } +var diffExceptions = []string{ + "*.md", + "go.sum", + "*_test.go", + "*.pb.go", + "*.pb.gw.go", + "openapi.yml", // FIXME: For some reason removing this file from exceptions causes too much memory usage and OS kills the process +} + func main() { var logger = log.New(os.Stdout, "", log.LstdFlags) @@ -94,28 +104,89 @@ func main() { } } - tmpdir, err := os.MkdirTemp("", "migdoc") + err = run(fromVer, toVer, logger) + if err != nil { + logger.Fatal(err) + } +} + +func run(fromVer, toVer *semver.Version, logger *log.Logger) error { + // A temporary directory is created to clone ignite cli repository and build it + tmpdir, err := os.MkdirTemp("", ".migdoc") defer os.RemoveAll(tmpdir) if err != nil { - logger.Fatalln(err) + return err } logger.Println("Created temporary directory:", tmpdir) logger.Println("Cloning", igniteCliRepository) - repoDir := filepath.Join(tmpdir, "src/github.com/ignite/cli") + repoDir := filepath.Join(tmpdir, igniteRepoPath) repo, err := git.PlainClone(repoDir, false, &git.CloneOptions{ URL: igniteCliRepository, Progress: os.Stdout, }) if err != nil { - logger.Fatalln(err) + return err + } + + versions, err := getRepositoryVersionTags(repo) + if err != nil { + return err + } + + fromVer, toVer, err = validateVersionRange(fromVer, toVer, versions) + + logger.Printf("Generating migration document for %s->%s\n", fromVer, toVer) + + wt, err := repo.Worktree() + if err != nil { + return errors.Wrap(err, "failed to get worktree") + } + + // Run scaffolds for fromVer and toVer + fromVerDir := filepath.Join(tmpdir, fromVer.Original()) + err = runScaffoldsForVersion(wt, repoDir, fromVerDir, fromVer) + if err != nil { + return errors.Wrapf(err, "failed to run scaffolds for tag %s", fromVer) + } + toVerDir := filepath.Join(tmpdir, toVer.Original()) + err = runScaffoldsForVersion(wt, repoDir, toVerDir, toVer) + if err != nil { + return errors.Wrapf(err, "failed to run scaffolds for tag %s", toVer) + } + + // Run diff between two directories + logger.Println("Generating diff...") + diffMap, err := calculateDiff(fromVerDir, toVerDir) + if err != nil { + return err + } + err = subtractBaseDiffs(diffMap) + if err != nil { + return err } + outputDir := fmt.Sprintf("migdoc-%s-%s", fromVer, toVer) + err = os.MkdirAll(outputDir, os.ModePerm) + if err != nil { + return err + } + err = saveDiffMap(diffMap, outputDir) + if err != nil { + return err + } + logger.Println("Migration document generated successfully at", outputDir) + + return nil +} + +func getRepositoryVersionTags(repo *git.Repository) (semver.Collection, error) { tags, err := repo.Tags() if err != nil { - logger.Fatalln(err) + return nil, errors.Wrap(err, "failed to get tags") } + // Iterate over all tags in the repository and pick valid semver tags var versions semver.Collection err = tags.ForEach(func(ref *plumbing.Reference) error { name := ref.Name() @@ -130,15 +201,52 @@ func main() { return nil }) if err != nil { - logger.Fatalln(err) + return nil, errors.Wrap(err, "failed to iterate over tags") } + sort.Sort(versions) + + return versions, nil +} + +func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collection) (*semver.Version, *semver.Version, error) { + // Unable to generate migration document if there are less than two releases! if versions.Len() < 2 { - logger.Fatalln("At least two semver tags are required") + return nil, nil, errors.New("At least two semver tags are required") } - sort.Sort(versions) + // Replace fromVer and toVer with equivalent semver tags from versions + if fromVer != nil { + found := false + for _, ver := range versions { + if ver.Equal(fromVer) { + fromVer = ver + found = true + break + } + } + if !found { + return nil, nil, errors.Errorf("tag %s not found", fromVer) + } + } + if toVer != nil { + found := false + for _, ver := range versions { + if ver.Equal(toVer) { + toVer = ver + found = true + break + } + } + if !found { + return nil, nil, errors.Errorf("tag %s not found", toVer) + } + } + // Picking deafult values for fromVer and toVer such that: + // If both fromVer and toVer are not provided, then generate migration document for second last and last semver tags + // If only fromVer is not provided, then use the tag before toVer as fromVer + // If only toVer is not provided, then use the last tag as toVer if fromVer == nil { if toVer != nil { sort.Search(versions.Len(), func(i int) bool { @@ -156,89 +264,370 @@ func main() { toVer = versions[versions.Len()-1] } - logger.Printf("Generating migration document for %s->%s\n\n", fromVer, toVer) + // Unable to generate migration document if fromVer is greater or equal to toVer + if fromVer.GreaterThan(toVer) || fromVer.Equal(toVer) { + return nil, nil, errors.Errorf("from version %s should be less than to version %s", fromVer, toVer) + } + + return fromVer, toVer, nil +} - // Checkout to previous tag and build ignite cli with make build - logger.Printf("Checking out to %s\n", fromVer) - wt, err := repo.Worktree() +func runScaffoldsForVersion(wt *git.Worktree, repoDir, outputDir string, ver *semver.Version) error { + err := checkoutAndBuildIgniteCli(wt, ver.Original(), repoDir) if err != nil { - logger.Fatalln(err) + return err } - err = wt.Checkout(&git.CheckoutOptions{ - Branch: plumbing.NewTagReferenceName(fromVer.Original()), - }) + + binPath := filepath.Join(repoDir, igniteBinaryPath) + err = executeScaffoldCommands(binPath, outputDir, ver) if err != nil { - logger.Fatalln(err) + return err } - logger.Println("Building ignite cli...") - err = runCommand(repoDir, "make", "build") + err = removeGitDirectories(outputDir) if err != nil { - logger.Fatalln(err) + return err } - err = executeScaffoldCommands(logger, filepath.Join(repoDir, igniteBinaryPath), filepath.Join(tmpdir, fromVer.Original())) + err = applyVersionExceptions(outputDir, ver) if err != nil { - logger.Fatalln(err) + return err } - // Checkout to latest tag and build ignite cli with make build - logger.Printf("Checking out to %s\n", toVer) - err = wt.Checkout(&git.CheckoutOptions{ - Branch: plumbing.NewTagReferenceName(toVer.Original()), + return nil +} + +func checkoutAndBuildIgniteCli(wt *git.Worktree, tag, repoDir string) error { + err := wt.Checkout(&git.CheckoutOptions{ + Branch: plumbing.NewTagReferenceName(tag), }) if err != nil { - logger.Fatalln(err) + return errors.Wrapf(err, "failed to checkout tag %s", tag) } - logger.Println("Building ignite cli...") - err = runCommand(repoDir, "make", "build") + err = exec.Exec(context.Background(), []string{"make", "build"}, exec.StepOption(step.Workdir(repoDir))) if err != nil { - logger.Fatalln(err) + return errors.Wrap(err, "failed to build ignite cli using make build") } - err = executeScaffoldCommands(logger, filepath.Join(repoDir, igniteBinaryPath), filepath.Join(tmpdir, toVer.Original())) - if err != nil { - logger.Fatalln(err) + return nil +} + +func executeScaffoldCommands(ignitePath, outputDir string, ver *semver.Version) error { + for name, cmds := range scaffoldCommands { + for _, cmd := range cmds { + args := []string{ignitePath, "scaffold"} + args = append(args, strings.Fields(cmd)...) + pathFlag := filepath.Join(outputDir, name) + if !strings.HasPrefix(cmd, "chain") && ver.LessThan(semver.MustParse("v0.27.0")) { + pathFlag = filepath.Join(outputDir, name, "example") + } + args = append(args, "--path", pathFlag) + err := exec.Exec(context.Background(), args) + if err != nil { + return errors.Wrapf(err, "failed to execute ignite scaffold command: %s", cmd) + } + } + } + return nil +} - // Run diff between two directories - logger.Println("Generating diff...") - diffs, err := Diff(filepath.Join(tmpdir, fromVer.Original()), filepath.Join(tmpdir, toVer.Original())) +func removeGitDirectories(outputDir string) error { + paths := make([]string, 0) + err := filepath.WalkDir(outputDir, func(path string, d fs.DirEntry, err error) error { + if d.IsDir() && d.Name() == ".git" { + paths = append(paths, path) + } + return nil + }) if err != nil { - logger.Fatalln(err) + return errors.Wrap(err, "failed to walk through output directory") } - outf, err := os.Create(fmt.Sprintf("migdoc-%s-%s.diff", fromVer, toVer)) - if err != nil { - logger.Fatalln(err) + + for _, path := range paths { + err := os.RemoveAll(path) + if err != nil { + return errors.Wrapf(err, "failed to remove %s directory", path) + } } - defer outf.Close() - for _, diff := range diffs { - outf.WriteString(fmt.Sprint(diff)) - outf.WriteString("\n") + + return nil +} + +func applyVersionExceptions(outputDir string, ver *semver.Version) error { + if ver.LessThan(semver.MustParse("v0.27.0")) { + // Move files from the "example" directory to the parent directory for each scaffold directory + for name := range scaffoldCommands { + err := os.Rename(filepath.Join(outputDir, name, "example"), filepath.Join(outputDir, "example_tmp")) + if err != nil { + return errors.Wrapf(err, "failed to move %s directory to tmp directory", name) + } + + err = os.RemoveAll(filepath.Join(outputDir, name)) + if err != nil { + return errors.Wrapf(err, "failed to remove %s directory", name) + } + + err = os.Rename(filepath.Join(outputDir, "example_tmp"), filepath.Join(outputDir, name)) + if err != nil { + return errors.Wrapf(err, "failed to move tmp directory to %s directory", name) + } + } } + + return nil } -func runCommand(dir, name string, args ...string) error { - cmd := exec.Command(name, args...) - cmd.Dir = dir - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - return cmd.Run() +func calculateDiff(fromVerDir, toVerDir string) (map[string][]gotextdiff.Unified, error) { + diffMap := make(map[string][]gotextdiff.Unified) + for name := range scaffoldCommands { + diffs, err := diff(filepath.Join(fromVerDir, name), filepath.Join(toVerDir, name)) + if err != nil { + return nil, err + } + diffMap[name] = diffs + } + + return diffMap, nil } -func executeScaffoldCommands(logger *log.Logger, ignitePath string, outputDir string) error { - for name, cmds := range scaffoldCommands { - logger.Println("Scaffolding", name) - for _, cmd := range cmds { - args := []string{"scaffold"} - args = append(args, strings.Fields(cmd)...) - args = append(args, "--path", filepath.Join(outputDir, name)) - err := runCommand("", ignitePath, args...) +func diff(dir1, dir2 string) ([]gotextdiff.Unified, error) { + var ( + diffs []gotextdiff.Unified + marked map[string]struct{} = make(map[string]struct{}) + ) + + dirsLCP := longestCommonPrefix(dir1, dir2) + + // Consider dir1 as reference and walk through all of the files comparing them with files in dir2. + err := filepath.Walk(dir1, func(path string, info os.FileInfo, err error) error { + if info.IsDir() { + return nil + } + + for _, exception := range diffExceptions { + if match, _ := filepath.Match(exception, info.Name()); match { + return nil + } + } + + relPath, err := filepath.Rel(dir1, path) + if err != nil { + return err + } + marked[relPath] = struct{}{} + + file1, err := os.ReadFile(path) + if err != nil { + return err + } + str1 := string(file1) + + file2, err := os.ReadFile(filepath.Join(dir2, relPath)) + if !os.IsNotExist(err) && err != nil { + return err + } + str2 := string(file2) + + edits := myers.ComputeEdits(span.URIFromPath(relPath), str1, str2) + if len(edits) > 0 { + fromPath, err := filepath.Rel(dirsLCP, path) if err != nil { - return errors.Wrapf(err, "failed to execute ignite scaffold command: %s", cmd) + panic(err) + } + toPath, err := filepath.Rel(dirsLCP, filepath.Join(dir2, relPath)) + if err != nil { + panic(err) + } + diffs = append(diffs, gotextdiff.ToUnified(fromPath, toPath, str1, edits)) + } + return nil + }) + if err != nil { + return diffs, err + } + + // Walk through all of the files in dir2 that were not compared with files in dir1. + err = filepath.Walk(dir2, func(path string, info os.FileInfo, err error) error { + if info.IsDir() { + return nil + } + + for _, exception := range diffExceptions { + if match, _ := filepath.Match(exception, info.Name()); match { + return nil + } + } + + relPath, err := filepath.Rel(dir2, path) + if err != nil { + return err + } + if _, ok := marked[relPath]; ok { + return nil + } + + str1 := "" + + file2, err := os.ReadFile(path) + if err != nil { + return err + } + str2 := string(file2) + + edits := myers.ComputeEdits(span.URIFromPath(relPath), str1, str2) + fromPath, err := filepath.Rel(dirsLCP, filepath.Join(dir1, relPath)) + if err != nil { + panic(err) + } + toPath, err := filepath.Rel(dirsLCP, path) + if err != nil { + panic(err) + } + diffs = append(diffs, gotextdiff.ToUnified(fromPath, toPath, str1, edits)) + return nil + }) + return diffs, nil +} + +func longestCommonPrefix(strs ...string) string { + longest := strings.Split(strs[0], string(filepath.Separator)) + + cmp := func(a []string) { + if len(a) < len(longest) { + longest = longest[:len(a)] + } + for i := 0; i < len(longest); i++ { + if a[i] != longest[i] { + longest = longest[:i] + return + } + } + } + + for i := 1; i < len(strs); i++ { + r := strings.Split(strs[i], string(filepath.Separator)) + cmp(r) + } + return "/" + filepath.Join(longest...) +} + +func subtractBaseDiffs(diffMap map[string][]gotextdiff.Unified) error { + // Remove chain and module diffs from other diffs + chainDiffs := diffMap["chain"] + moduleDiffs := diffMap["module"] + for name, diffs := range diffMap { + if name == "module" { + diffs = subtractDiffs(diffs, chainDiffs) + } else if name != "chain" { + diffs = subtractDiffs(diffs, moduleDiffs) + } + diffMap[name] = diffs + } + + return nil +} + +func subtractDiffs(src []gotextdiff.Unified, base []gotextdiff.Unified) []gotextdiff.Unified { + dst := make([]gotextdiff.Unified, 0, len(src)) + for i := 0; i < len(src); i++ { + edited := false + for j := 0; j < len(base); j++ { + if equalScaffoldPaths(src[i].From, base[j].From) && equalScaffoldPaths(src[i].To, base[j].To) { + if hs := subtractHunks(src[i].Hunks, base[j].Hunks); len(hs) > 0 { + dst = append(dst, gotextdiff.Unified{ + From: src[i].From, + To: src[i].To, + Hunks: subtractHunks(src[i].Hunks, base[j].Hunks), + }) + } + edited = true + } + } + + if !edited { + dst = append(dst, src[i]) + } + } + + return dst +} + +func subtractHunks(src []*gotextdiff.Hunk, base []*gotextdiff.Hunk) []*gotextdiff.Hunk { + dst := make([]*gotextdiff.Hunk, 0, len(src)) + for i := 0; i < len(src); i++ { + edited := false + for j := 0; j < len(base); j++ { + if src[i].FromLine <= base[j].FromLine && src[i].ToLine >= base[j].ToLine { + if h := subtractHunk(src[i], base[j]); h != nil { + dst = append(dst, h) + } + edited = true + } + } + + if !edited { + dst = append(dst, src[i]) + } + } + + return dst +} + +func subtractHunk(src, base *gotextdiff.Hunk) *gotextdiff.Hunk { + newLines := make([]gotextdiff.Line, 0, len(src.Lines)) + equals := 0 + for i := 0; i < len(src.Lines); i++ { + rep := false + for j := 0; j < len(base.Lines); j++ { + if src.Lines[i].Kind != gotextdiff.Equal && src.Lines[i].Kind == base.Lines[j].Kind && src.Lines[i].Content == base.Lines[j].Content { + rep = true + break } } + + if !rep { + newLines = append(newLines, src.Lines[i]) + } + + if src.Lines[i].Kind == gotextdiff.Equal { + equals++ + } + } + + // If all the lines in the hunk are equal or there's no line left, then return nil + if equals == len(newLines) || len(newLines) == 0 { + return nil + } + + return &gotextdiff.Hunk{ + FromLine: src.FromLine, + ToLine: src.ToLine, + Lines: newLines, + } +} + +func equalScaffoldPaths(a, b string) bool { + // Remove the first two directories from the path (version/scaffold_type) and compare the rest + a = strings.Join(strings.Split(a, string(filepath.Separator))[2:], string(filepath.Separator)) + b = strings.Join(strings.Split(b, string(filepath.Separator))[2:], string(filepath.Separator)) + + return a == b +} + +func saveDiffMap(diffMap map[string][]gotextdiff.Unified, outputPath string) error { + for name, diffs := range diffMap { + outf, err := os.Create(filepath.Join(outputPath, name+".diff")) + if err != nil { + return err + } + defer outf.Close() + for _, diff := range diffs { + outf.WriteString(fmt.Sprint(diff)) + outf.WriteString("\n") + } } + return nil } From 8917a4729fc2b25de0f4156c2e70ec1e58d4dca1 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Mon, 27 Nov 2023 13:50:06 +0330 Subject: [PATCH 06/69] Minor improvements --- ignite/internal/tools/gen-mig-docs/main.go | 25 ++++++++++------------ 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/ignite/internal/tools/gen-mig-docs/main.go b/ignite/internal/tools/gen-mig-docs/main.go index b6f672de91..94905c031c 100644 --- a/ignite/internal/tools/gen-mig-docs/main.go +++ b/ignite/internal/tools/gen-mig-docs/main.go @@ -58,17 +58,8 @@ var scaffoldCommands = map[string][]string{ "packet": { "chain example --no-module", "module example --ibc", - "chain example", "packet packet1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, - "vue": { - "chain example", - "vue", - }, - "react": { - "chain example", - "react", - }, } var diffExceptions = []string{ @@ -78,6 +69,11 @@ var diffExceptions = []string{ "*.pb.go", "*.pb.gw.go", "openapi.yml", // FIXME: For some reason removing this file from exceptions causes too much memory usage and OS kills the process + ".gitignore", + "*.html", + "*.css", + "*.js", + "*.ts", } func main() { @@ -122,8 +118,7 @@ func run(fromVer, toVer *semver.Version, logger *log.Logger) error { logger.Println("Cloning", igniteCliRepository) repoDir := filepath.Join(tmpdir, igniteRepoPath) repo, err := git.PlainClone(repoDir, false, &git.CloneOptions{ - URL: igniteCliRepository, - Progress: os.Stdout, + URL: igniteCliRepository, }) if err != nil { return err @@ -243,7 +238,7 @@ func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collec } } - // Picking deafult values for fromVer and toVer such that: + // Picking default values for fromVer and toVer such that: // If both fromVer and toVer are not provided, then generate migration document for second last and last semver tags // If only fromVer is not provided, then use the tag before toVer as fromVer // If only toVer is not provided, then use the last tag as toVer @@ -336,8 +331,10 @@ func executeScaffoldCommands(ignitePath, outputDir string, ver *semver.Version) func removeGitDirectories(outputDir string) error { paths := make([]string, 0) err := filepath.WalkDir(outputDir, func(path string, d fs.DirEntry, err error) error { - if d.IsDir() && d.Name() == ".git" { - paths = append(paths, path) + if d.IsDir() { + if d.Name() == ".git" || d.Name() == ".github" { + paths = append(paths, path) + } } return nil }) From 0212ae7bd1ed586f601a1e470b2357050affb8c7 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Mon, 27 Nov 2023 13:50:59 +0330 Subject: [PATCH 07/69] Remove gen-migdoc bash script --- scripts/gen-migdoc | 72 ---------------------------------------------- 1 file changed, 72 deletions(-) delete mode 100755 scripts/gen-migdoc diff --git a/scripts/gen-migdoc b/scripts/gen-migdoc deleted file mode 100755 index 5ff94e3405..0000000000 --- a/scripts/gen-migdoc +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env bash - -set -e - -SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P) -IGNITE_REPO="https://github.com/ignite/cli.git" -SCAFFOLD_CMDS=( - "chain example --no-module --skip-git" - "module example --params param1:string,param2:bool --yes" - "list list1 field1:string field2:int --module example --yes" -) -DIFF_EXCLUDE=( - ".git" - "*.md" - "go.sum" -) - -# Cleans up temporary files and directories -clean_up() { - test -d "$1" && rm -fr "$1" -} - -# Checks out to the given version tag and builds the Ignite CLI -checkout_and_build_ignite() ( - local ignite_dir="$1" version="$2" - - cd "$ignite_dir" - git checkout --quiet "$version" && make build > /dev/null || exit 1 -) - -# Runs list of scaffold commands with the given ignite cli -scaffold_chain() { - local ignite_cmd="$1" scaffold_path="$2" - - for cmd in "${SCAFFOLD_CMDS[@]}"; do - $ignite_cmd scaffold $cmd --path $scaffold_path > /dev/null || (echo "Failed at scaffolding $cmd"; exit 1) - done -} - -# Generates diff between two directories -generate_diff() { - local first_path="$1" second_path="$2" - - exclude_flags=() - for exclude in "${DIFF_EXCLUDE[@]}"; do exclude_flags+=(-x "$exclude"); done - - diff -bur "$first_path" "$second_path" "${exclude_flags[@]}" -} - -main() { - tmp_dir=$(mktemp -d) - trap "clean_up $tmp_dir" SIGINT SIGTERM ERR EXIT - - git clone "$IGNITE_REPO" "$tmp_dir/ignite" --quiet - - # Gets the latest version and the previous version - versions=$(git tag --list --sort=version:refname 'v*') - new_version=$(echo "${versions}" | tail -n 1); mkdir -p "$tmp_dir/$new_version" - previous_version=$(echo "${versions}" | tail -n 2 | head -n 1); mkdir -p "$tmp_dir/$previous_version" - echo "Generating migration documentation: ${previous_version} -> ${new_version}" - - checkout_and_build_ignite "$tmp_dir/ignite" "$previous_version" - scaffold_chain "$tmp_dir/ignite/dist/ignite" "$tmp_dir/$previous_version" - - checkout_and_build_ignite "$tmp_dir/ignite" "$new_version" - scaffold_chain "$tmp_dir/ignite/dist/ignite" "$tmp_dir/$new_version" - - # Getting diff between the two chains - generate_diff "$tmp_dir/$previous_version" "$tmp_dir/$new_version" > "$SCRIPT_DIR"/"$previous_version"-"$new_version".diff -} - -main \ No newline at end of file From 6406bab86adc7cf8b1affd9f0a5867dad1e6cd7f Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Thu, 1 Feb 2024 14:58:47 +0330 Subject: [PATCH 08/69] Move exception files to different file --- .../tools/gen-mig-diffs/exceptions.go | 39 ++++++++ .../{gen-mig-docs => gen-mig-diffs}/main.go | 95 ++++++------------- 2 files changed, 70 insertions(+), 64 deletions(-) create mode 100644 ignite/internal/tools/gen-mig-diffs/exceptions.go rename ignite/internal/tools/{gen-mig-docs => gen-mig-diffs}/main.go (90%) diff --git a/ignite/internal/tools/gen-mig-diffs/exceptions.go b/ignite/internal/tools/gen-mig-diffs/exceptions.go new file mode 100644 index 0000000000..88671da9a0 --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/exceptions.go @@ -0,0 +1,39 @@ +package main + +import ( + "path/filepath" + + "github.com/gobwas/glob" +) + +// List of files that should be ignored when calculating diff of two directories +var exceptionFiles = []glob.Glob{ + mustCompilePathGlob("**/.git/**"), + mustCompilePathGlob("**.md"), + mustCompilePathGlob("**/go.sum"), + mustCompilePathGlob("**_test.go"), + mustCompilePathGlob("**.pb.go"), + mustCompilePathGlob("**.pb.gw.go"), + mustCompilePathGlob("**.pulsar.go"), + mustCompilePathGlob("**/node_modules/**"), + mustCompilePathGlob("**/openapi.yml"), + mustCompilePathGlob("**/.gitignore"), + mustCompilePathGlob("**.html"), + mustCompilePathGlob("**.css"), + mustCompilePathGlob("**.js"), + mustCompilePathGlob("**.ts"), +} + +func mustCompilePathGlob(pattern string) glob.Glob { + return glob.MustCompile(pattern, filepath.Separator) +} + +// Checks if the given path matches any of the exception file patterns +func isException(path string) bool { + for _, glob := range exceptionFiles { + if glob.Match(path) { + return true + } + } + return false +} diff --git a/ignite/internal/tools/gen-mig-docs/main.go b/ignite/internal/tools/gen-mig-diffs/main.go similarity index 90% rename from ignite/internal/tools/gen-mig-docs/main.go rename to ignite/internal/tools/gen-mig-diffs/main.go index f3eb9fc8ee..bbc33c24de 100644 --- a/ignite/internal/tools/gen-mig-docs/main.go +++ b/ignite/internal/tools/gen-mig-diffs/main.go @@ -4,7 +4,6 @@ import ( "context" "flag" "fmt" - "io/fs" "log" "os" "path/filepath" @@ -37,7 +36,7 @@ var scaffoldCommands = map[string][]string{ }, "map": { "chain example", - "map map1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", + "map map1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --index f10:string --module example --yes", }, "single": { "chain example", @@ -58,29 +57,16 @@ var scaffoldCommands = map[string][]string{ "packet": { "chain example --no-module", "module example --ibc", - "packet packet1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", + "packet packet1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --ack f1:string,f2:strings,f3:bool,f4:int,f5:ints,f6:uint,f7:uints,f8:coin,f9:coins --module example --yes", }, } -var diffExceptions = []string{ - "*.md", - "go.sum", - "*_test.go", - "*.pb.go", - "*.pb.gw.go", - "openapi.yml", // FIXME: For some reason removing this file from exceptions causes too much memory usage and OS kills the process - ".gitignore", - "*.html", - "*.css", - "*.js", - "*.ts", -} - func main() { var logger = log.New(os.Stdout, "", log.LstdFlags) fromFlag := flag.String("from", "", "Semver tag to generate migration document from") toFlag := flag.String("to", "", "Semver tag to generate migration document to") + sourceFlag := flag.String("source", "", "Source code directory of ignite cli repository (will be cloned if not provided)") flag.Parse() var ( @@ -100,13 +86,13 @@ func main() { } } - err = run(fromVer, toVer, logger) + err = run(fromVer, toVer, sourceFlag, logger) if err != nil { logger.Fatal(err) } } -func run(fromVer, toVer *semver.Version, logger *log.Logger) error { +func run(fromVer, toVer *semver.Version, source *string, logger *log.Logger) error { // A temporary directory is created to clone ignite cli repository and build it tmpdir, err := os.MkdirTemp("", ".migdoc") defer os.RemoveAll(tmpdir) @@ -115,13 +101,26 @@ func run(fromVer, toVer *semver.Version, logger *log.Logger) error { } logger.Println("Created temporary directory:", tmpdir) - logger.Println("Cloning", igniteCliRepository) - repoDir := filepath.Join(tmpdir, igniteRepoPath) - repo, err := git.PlainClone(repoDir, false, &git.CloneOptions{ - URL: igniteCliRepository, - }) - if err != nil { - return err + var ( + repoDir string + repo *git.Repository + ) + if source != nil && *source != "" { + logger.Println("Using source code directory:", *source) + repoDir = *source + repo, err = git.PlainOpen(*source) + if err != nil { + return err + } + } else { + logger.Println("Cloning", igniteCliRepository) + repoDir := filepath.Join(tmpdir, igniteRepoPath) + repo, err = git.PlainClone(repoDir, false, &git.CloneOptions{ + URL: igniteCliRepository, + }) + if err != nil { + return err + } } versions, err := getRepositoryVersionTags(repo) @@ -267,6 +266,7 @@ func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collec return fromVer, toVer, nil } +// Run scaffolds commands one by one with the given version of ignite cli and save the output in the output directory func runScaffoldsForVersion(wt *git.Worktree, repoDir, outputDir string, ver *semver.Version) error { err := checkoutAndBuildIgniteCli(wt, ver.Original(), repoDir) if err != nil { @@ -279,11 +279,6 @@ func runScaffoldsForVersion(wt *git.Worktree, repoDir, outputDir string, ver *se return err } - err = removeGitDirectories(outputDir) - if err != nil { - return err - } - err = applyVersionExceptions(outputDir, ver) if err != nil { return err @@ -318,7 +313,7 @@ func executeScaffoldCommands(ignitePath, outputDir string, ver *semver.Version) pathFlag = filepath.Join(outputDir, name, "example") } args = append(args, "--path", pathFlag) - err := exec.Exec(context.Background(), args) + err := exec.Exec(context.Background(), args, exec.StepOption(step.Stdout(os.Stdout)), exec.StepOption(step.Stderr(os.Stderr))) if err != nil { return errors.Wrapf(err, "failed to execute ignite scaffold command: %s", cmd) } @@ -328,30 +323,6 @@ func executeScaffoldCommands(ignitePath, outputDir string, ver *semver.Version) return nil } -func removeGitDirectories(outputDir string) error { - paths := make([]string, 0) - err := filepath.WalkDir(outputDir, func(path string, d fs.DirEntry, err error) error { - if d.IsDir() { - if d.Name() == ".git" || d.Name() == ".github" { - paths = append(paths, path) - } - } - return nil - }) - if err != nil { - return errors.Wrap(err, "failed to walk through output directory") - } - - for _, path := range paths { - err := os.RemoveAll(path) - if err != nil { - return errors.Wrapf(err, "failed to remove %s directory", path) - } - } - - return nil -} - func applyVersionExceptions(outputDir string, ver *semver.Version) error { if ver.LessThan(semver.MustParse("v0.27.0")) { // Move files from the "example" directory to the parent directory for each scaffold directory @@ -403,10 +374,8 @@ func diff(dir1, dir2 string) ([]gotextdiff.Unified, error) { return nil } - for _, exception := range diffExceptions { - if match, _ := filepath.Match(exception, info.Name()); match { - return nil - } + if isException(path) { + return nil } relPath, err := filepath.Rel(dir1, path) @@ -451,10 +420,8 @@ func diff(dir1, dir2 string) ([]gotextdiff.Unified, error) { return nil } - for _, exception := range diffExceptions { - if match, _ := filepath.Match(exception, info.Name()); match { - return nil - } + if isException(path) { + return nil } relPath, err := filepath.Rel(dir2, path) From c0151e886d894577aa528464fa9e6f1d0a432fde Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Mon, 5 Feb 2024 16:31:14 +0330 Subject: [PATCH 09/69] Change the diff subtraction algorithm --- .../internal/tools/gen-mig-diffs/cmd/root.go | 332 ++++++++++ .../internal/tools/gen-mig-diffs/diff/diff.go | 298 +++++++++ .../gen-mig-diffs/{ => diff}/exceptions.go | 2 +- ignite/internal/tools/gen-mig-diffs/main.go | 592 +----------------- .../tools/gen-mig-diffs/scaffold/scaffold.go | 191 ++++++ 5 files changed, 827 insertions(+), 588 deletions(-) create mode 100644 ignite/internal/tools/gen-mig-diffs/cmd/root.go create mode 100644 ignite/internal/tools/gen-mig-diffs/diff/diff.go rename ignite/internal/tools/gen-mig-diffs/{ => diff}/exceptions.go (98%) create mode 100644 ignite/internal/tools/gen-mig-diffs/scaffold/scaffold.go diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go new file mode 100644 index 0000000000..1e19e09411 --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -0,0 +1,332 @@ +package cmd + +import ( + "context" + "fmt" + "log" + "os" + "path/filepath" + "sort" + + semver "github.com/Masterminds/semver/v3" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "github.com/hexops/gotextdiff" + "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/diff" + "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/scaffold" + "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/exec" + "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/step" + "github.com/ignite/cli/v28/ignite/pkg/errors" + "github.com/spf13/cobra" +) + +const ( + fromFlag = "from" + toFlag = "to" + outputFlag = "output" + + igniteCliRepository = "http://github.com/ignite/cli.git" + igniteRepoPath = "src/github.com/ignite/cli" + igniteBinaryPath = "dist/ignite" +) + +// NewRootCmd creates a new root command +func NewRootCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "gen-mig-diffs", + Short: "Generate migration diffs", + Long: "This tool is used to generate migration diff files for each of ignites scaffold commands", + RunE: generateMigrationDiffs, + } + + cmd.Flags().StringP(fromFlag,"f", "", "Version of ignite or path to ignite source code to generate the diff from") + cmd.Flags().StringP(toFlag, "t", "", "Version of ignite or path to ignite source code to generate the diff to") + cmd.Flags().StringP(outputFlag, "o", ".", "Output directory to save the migration diff files") + + return cmd +} + +func generateMigrationDiffs(cmd *cobra.Command, args []string) error { + from, _ := cmd.Flags().GetString(fromFlag) + to, _ := cmd.Flags().GetString(toFlag) + output, _ := cmd.Flags().GetString(outputFlag) + + // A temporary directory is created to clone ignite cli repository and build it + tmpdir, err := os.MkdirTemp("", ".migdoc") + defer os.RemoveAll(tmpdir) + if err != nil { + return err + } + log.Println("Created temporary directory:", tmpdir) + + var fromVer, toVer *semver.Version + if ver, err := semver.NewVersion(from); err == nil { + fromVer = ver + } + if ver, err := semver.NewVersion(to); err == nil { + toVer = ver + } + + repoDir, err := cloneIgniteRepo(tmpdir) + if err != nil { + return err + } + + versions, err := getRepositoryVersionTags(repoDir) + if err != nil { + return err + } + + fromVer, toVer, err = validateVersionRange(fromVer, toVer, versions) + if err != nil { + return err + } + + log.Printf("Generating migration document for %s->%s\n", fromVer, toVer) + + // Run scaffolds for fromVer and toVer + fromVerDir := filepath.Join(tmpdir, fromVer.Original()) + err = runScaffoldsForVersion(repoDir, fromVerDir, fromVer) + if err != nil { + return errors.Wrapf(err, "failed to run scaffolds for tag %s", fromVer) + } + toVerDir := filepath.Join(tmpdir, toVer.Original()) + err = runScaffoldsForVersion(repoDir, toVerDir, toVer) + if err != nil { + return errors.Wrapf(err, "failed to run scaffolds for tag %s", toVer) + } + + // Run diff between two directories + log.Println("Generating diff...") + diffMap, err := calculateDiff(fromVerDir, toVerDir) + if err != nil { + return err + } + + outputDir := filepath.Join(output, fmt.Sprintf("migdoc-%s-%s", fromVer, toVer)) + err = os.MkdirAll(outputDir, os.ModePerm) + if err != nil { + return err + } + err = saveDiffMap(diffMap, outputDir) + if err != nil { + return err + } + log.Println("Migration document generated successfully at", outputDir) + + return nil +} + +func isStrVersion(s string) bool { + _, err := semver.NewVersion(s) + return err == nil +} + +func cloneIgniteRepo(tmpdir string) (string, error) { + log.Println("Cloning", igniteCliRepository) + + repoDir := filepath.Join(tmpdir, igniteRepoPath) + _, err := git.PlainClone(repoDir, false, &git.CloneOptions{ + URL: igniteCliRepository, + }) + return repoDir, err +} + +// getRepositoryVersionTags returns a sorted collection of semver tags from the ignite cli repository +func getRepositoryVersionTags(repoDir string) (semver.Collection, error) { + repo, err := git.PlainOpen(repoDir) + if err != nil { + return nil, err + } + + tags, err := repo.Tags() + if err != nil { + return nil, errors.Wrap(err, "failed to get tags") + } + + // Iterate over all tags in the repository and pick valid semver tags + var versions semver.Collection + err = tags.ForEach(func(ref *plumbing.Reference) error { + name := ref.Name() + if name.IsTag() { + ver, err := semver.NewVersion(name.Short()) + if err != nil { + // Do nothing as it's not a semver tag + return nil + } + versions = append(versions, ver) + } + return nil + }) + if err != nil { + return nil, errors.Wrap(err, "failed to iterate over tags") + } + + sort.Sort(versions) + + return versions, nil +} + +// validateVersionRange checks if the provided fromVer and toVer exist in the versions and if any of them is nil, then it picks default values. +func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collection) (*semver.Version, *semver.Version, error) { + // Unable to generate migration document if there are less than two releases! + if versions.Len() < 2 { + return nil, nil, errors.New("At least two semver tags are required") + } + + // Replace fromVer and toVer with equivalent semver tags from versions + if fromVer != nil { + found := false + for _, ver := range versions { + if ver.Equal(fromVer) { + fromVer = ver + found = true + break + } + } + if !found { + return nil, nil, errors.Errorf("tag %s not found", fromVer) + } + } + if toVer != nil { + found := false + for _, ver := range versions { + if ver.Equal(toVer) { + toVer = ver + found = true + break + } + } + if !found { + return nil, nil, errors.Errorf("tag %s not found", toVer) + } + } + + // Picking default values for fromVer and toVer such that: + // If both fromVer and toVer are not provided, then generate migration document for second last and last semver tags + // If only fromVer is not provided, then use the tag before toVer as fromVer + // If only toVer is not provided, then use the last tag as toVer + if fromVer == nil { + if toVer != nil { + sort.Search(versions.Len(), func(i int) bool { + if versions[i].LessThan(toVer) { + fromVer = versions[i] + return false + } + return true + }) + } else { + fromVer = versions[versions.Len()-2] + } + } + if toVer == nil { + toVer = versions[versions.Len()-1] + } + + // Unable to generate migration document if fromVer is greater or equal to toVer + if fromVer.GreaterThan(toVer) || fromVer.Equal(toVer) { + return nil, nil, errors.Errorf("from version %s should be less than to version %s", fromVer, toVer) + } + + return fromVer, toVer, nil +} + +// Run scaffolds commands one by one with the given version of ignite cli and save the output in the output directory +func runScaffoldsForVersion(repoDir, outputDir string, ver *semver.Version) error { + repo, err := git.PlainOpen(repoDir) + if err != nil { + return errors.Wrap(err, "failed to open git repository") + } + + wt, err := repo.Worktree() + if err != nil { + return errors.Wrap(err, "failed to get worktree") + } + + err = checkoutAndBuildIgniteCli(wt, ver.Original(), repoDir) + if err != nil { + return err + } + + binPath := filepath.Join(repoDir, igniteBinaryPath) + scaffolder := scaffold.NewScaffolder(binPath, scaffold.DefaultScaffoldCommands) + err = scaffolder.RunScaffolds(ver, outputDir) + if err != nil { + return errors.Wrapf(err, "failed to run scaffolds for tag %s", ver) + } + + return nil +} + +func checkoutAndBuildIgniteCli(wt *git.Worktree, tag, repoDir string) error { + err := wt.Checkout(&git.CheckoutOptions{ + Branch: plumbing.NewTagReferenceName(tag), + }) + if err != nil { + return errors.Wrapf(err, "failed to checkout tag %s", tag) + } + + err = exec.Exec(context.Background(), []string{"make", "build"}, exec.StepOption(step.Workdir(repoDir))) + if err != nil { + return errors.Wrap(err, "failed to build ignite cli using make build") + } + + return nil +} + +func calculateDiff(fromVerDir, toVerDir string) (map[string][]gotextdiff.Unified, error) { + diffMap := make(map[string]*diff.Diff) + for _, s := range scaffold.DefaultScaffoldCommands { + diff, err := diff.ComputeDiff(filepath.Join(fromVerDir, s.Name), filepath.Join(toVerDir, s.Name)) + if err != nil { + return nil, err + } + diffMap[s.Name] = diff + } + + subtractBaseDiffs(diffMap) + + unifiedDiffMap := make(map[string][]gotextdiff.Unified) + for name, diff := range diffMap { + unifiedDiffMap[name] = diff.ToUnified() + } + + return unifiedDiffMap, nil +} + +// subtractBaseDiffs removes chain and module diffs from other diffs +func subtractBaseDiffs(diffMap map[string]*diff.Diff) error { + chainDiff := diffMap["chain"] + moduleDiff := diffMap["module"] + for name, diff := range diffMap { + if name != "chain" && name != "module" { + err := diff.Subtract(moduleDiff) + if err != nil { + return errors.Wrapf(err, "failed to subtract module diff from %s diff", name) + } + } + diffMap[name] = diff + } + + if err := diffMap["module"].Subtract(chainDiff); err != nil { + return errors.Wrap(err, "failed to subtract chain diff from module diff") + } + + return nil +} + +func saveDiffMap(diffMap map[string][]gotextdiff.Unified, outputPath string) error { + for name, diffs := range diffMap { + outf, err := os.Create(filepath.Join(outputPath, name+".diff")) + if err != nil { + return err + } + defer outf.Close() + for _, diff := range diffs { + outf.WriteString(fmt.Sprint(diff)) + outf.WriteString("\n") + } + } + + return nil +} diff --git a/ignite/internal/tools/gen-mig-diffs/diff/diff.go b/ignite/internal/tools/gen-mig-diffs/diff/diff.go new file mode 100644 index 0000000000..5dd826d003 --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/diff/diff.go @@ -0,0 +1,298 @@ +package diff + +import ( + "os" + "path/filepath" + "strings" + + "github.com/hexops/gotextdiff" + "github.com/hexops/gotextdiff/myers" + "github.com/hexops/gotextdiff/span" + "github.com/ignite/cli/v28/ignite/pkg/errors" +) + +type Diff struct { + dir1, dir2 string + lcp string + files1, files2 map[string]string + edits []gotextdiff.TextEdit +} + +func ComputeDiff(dir1, dir2 string) (*Diff, error) { + marked := make(map[string]struct{}) + diff := &Diff{ + dir1: dir1, + dir2: dir2, + lcp: longestCommonPrefix(dir1, dir2), + files1: make(map[string]string), + files2: make(map[string]string), + edits: make([]gotextdiff.TextEdit, 0), + } + + // Consider dir1 as reference and walk through all of the files comparing them with files in dir2. + err := filepath.Walk(dir1, func(path string, info os.FileInfo, err error) error { + if info.IsDir() { + return nil + } + + if isException(path) { + return nil + } + + relPath, err := filepath.Rel(dir1, path) + if err != nil { + return err + } + marked[relPath] = struct{}{} + + b, err := os.ReadFile(path) + if err != nil { + return err + } + diff.files1[relPath] = string(b) + + b, err = os.ReadFile(filepath.Join(dir2, relPath)) + // If the file does not exist in dir2, we consider it as an empty file. + if !os.IsNotExist(err) && err != nil { + return err + } + diff.files2[relPath] = string(b) + + edits := myers.ComputeEdits(span.URIFromPath(path), diff.files1[relPath], diff.files2[relPath]) + conv := span.NewContentConverter(span.URIFromPath(path).Filename(), []byte(diff.files1[relPath])) + err = ensureEditsHavePositionAndOffset(edits, conv) + if err != nil { + return err + } + diff.edits = append(diff.edits, edits...) + return nil + }) + if err != nil { + return nil, err + } + + // Walk through all of the files in dir2 that were not compared with files in dir1. + err = filepath.Walk(dir2, func(path string, info os.FileInfo, err error) error { + if info.IsDir() { + return nil + } + + if isException(path) { + return nil + } + + relPath, err := filepath.Rel(dir2, path) + if err != nil { + return err + } + if _, ok := marked[relPath]; ok { + return nil + } + + diff.files1[relPath] = "" + + b, err := os.ReadFile(path) + if err != nil { + return err + } + diff.files2[relPath] = string(b) + + edits := myers.ComputeEdits(span.URIFromPath(filepath.Join(dir1, relPath)), diff.files1[relPath], diff.files2[relPath]) + diff.edits = append(diff.edits, edits...) + return nil + }) + if err != nil { + return nil, err + } + + diff.makeSureEditsAreSorted() + + return diff, err +} + +func longestCommonPrefix(strs ...string) string { + longest := strings.Split(strs[0], string(filepath.Separator)) + + cmp := func(a []string) { + if len(a) < len(longest) { + longest = longest[:len(a)] + } + for i := 0; i < len(longest); i++ { + if a[i] != longest[i] { + longest = longest[:i] + return + } + } + } + + for i := 1; i < len(strs); i++ { + r := strings.Split(strs[i], string(filepath.Separator)) + cmp(r) + } + return "/" + filepath.Join(longest...) +} + +func ensureEditsHavePositionAndOffset(edits []gotextdiff.TextEdit, conv span.Converter) error { + var err error + for i, e := range edits { + edits[i].Span, err = e.Span.WithAll(conv) + if err != nil { + return err + } + } + + return nil +} + +func (d *Diff) makeSureEditsAreSorted() { + gotextdiff.SortTextEdits(d.edits) +} + +// Subtract removes all the common changes of base and d from d. +// Note that this function only works for cases where all the changes of base is included in d. +func (d *Diff) Subtract(base *Diff) error { + baseFiles := base.groupEditsByFile() + + newEdits := make([]gotextdiff.TextEdit, 0, len(d.edits)) + for f, edits := range d.groupEditsByFile() { + if _, ok := baseFiles[f]; !ok { + newEdits = append(newEdits, edits...) + continue + } + + // Because both base and d are sorted, we use a merge sort like algorithm to subtract base from d. + var i, j, traverseOffset int + for i < len(edits) && j < len(baseFiles[f]) { + e := edits[i] + b := baseFiles[f][j] + + if e.Span.End().Offset() < b.Span.Start().Offset()+traverseOffset { + newEdits = append(newEdits, e) + i++ + traverseOffset += calculateOffsetChange(e) + continue + } + + // Ideally, this condition should never be met as we are assuming that all the changes of base is included in d. + if e.Span.Start().Offset() > b.Span.End().Offset()+traverseOffset { + j++ + continue + } + + if spansHaveConflict(e.Span, b.Span, traverseOffset) { + // If there is a conflict, we add the change of d and move to the next change. + newEdits = append(newEdits, e) + + if e.Span.Start().Offset() < b.Span.Start().Offset()+traverseOffset { + i++ + traverseOffset += len(e.NewText) - (b.Span.Start().Offset() - e.Span.Start().Offset()) + } else { + j++ + traverseOffset += len(e.NewText) - (e.Span.Start().Offset() - b.Span.End().Offset()) + } + } + + // Finally the two cases where either e is in the middle of b or b is in the middle of e. + if e.Span.Start().Offset() >= b.Span.Start().Offset()+traverseOffset { + aconv := span.NewContentConverter(e.Span.URI().Filename(), []byte(d.files1[f])) + editParts, err := subtractEdits(e, b, aconv) + if err != nil { + return err + } + newEdits = append(newEdits, editParts...) + traverseOffset += calculateOffsetChange(e) - calculateOffsetChange(b) + } + + i++ + j++ + } + } + + d.edits = newEdits + return nil +} + +func (d *Diff) groupEditsByFile() map[string][]gotextdiff.TextEdit { + d.makeSureEditsAreSorted() + + fileEdits := make(map[string][]gotextdiff.TextEdit) + for _, e := range d.edits { + path, err := filepath.Rel(d.dir1, e.Span.URI().Filename()) + if err != nil { + panic(err) + } + fileEdits[path] = append(fileEdits[path], e) + } + return fileEdits +} + +func calculateOffsetChange(e gotextdiff.TextEdit) int { + return len(e.NewText) - (e.Span.End().Offset() - e.Span.Start().Offset()) +} + +func areEditsEqual(a, b gotextdiff.TextEdit, offset int) bool { + if a.Span.Start().Offset() != b.Span.Start().Offset()+offset { + return false + } + if a.Span.End().Offset() != b.Span.End().Offset()+offset { + return false + } + if a.NewText != b.NewText { + return false + } + return true +} + +func spansHaveConflict(a, b span.Span, offset int) bool { + if isPointInSpan(a.Start(), b) && !isPointInSpan(a.End(), b) { + return true + } + if isPointInSpan(a.End(), b) && !isPointInSpan(a.Start(), b) { + return true + } + return false +} + +func isPointInSpan(p span.Point, s span.Span) bool { + return p.Offset() >= s.Start().Offset() && p.Offset() <= s.End().Offset() +} + +func subtractEdits(a, b gotextdiff.TextEdit, aconv span.Converter) ([]gotextdiff.TextEdit, error) { + edits := myers.ComputeEdits(a.Span.URI(), b.NewText, a.NewText) + bconv := span.NewContentConverter(b.Span.URI().Filename(), []byte(b.NewText)) + for i, e := range edits { + s, err := e.Span.WithOffset(bconv) + if err != nil { + return nil, err + } + edits[i].Span = moveSpan(s, a.Span.End().Offset()) + } + + err := ensureEditsHavePositionAndOffset(edits, aconv) + if err != nil { + return nil, errors.Wrap(err, "failed to ensure edits have position and offset") + } + + return edits, nil +} + +func moveSpan(s span.Span, offset int) span.Span { + return span.New(s.URI(), span.NewPoint(0, 0, s.Start().Offset()+offset), span.NewPoint(0, 0, s.End().Offset()+offset)) +} + +func (d *Diff) ToUnified() []gotextdiff.Unified { + unified := make([]gotextdiff.Unified, 0, len(d.edits)) + fileEdits := d.groupEditsByFile() + for path, edits := range fileEdits { + from, err := filepath.Rel(d.lcp, filepath.Join(d.dir1, path)) + if err != nil { + panic(err) + } + to, err := filepath.Rel(d.lcp, filepath.Join(d.dir2, path)) + if err != nil { + panic(err) + } + unified = append(unified, gotextdiff.ToUnified(from, to, d.files1[path], edits)) + } + return unified +} diff --git a/ignite/internal/tools/gen-mig-diffs/exceptions.go b/ignite/internal/tools/gen-mig-diffs/diff/exceptions.go similarity index 98% rename from ignite/internal/tools/gen-mig-diffs/exceptions.go rename to ignite/internal/tools/gen-mig-diffs/diff/exceptions.go index 88671da9a0..59707fd89d 100644 --- a/ignite/internal/tools/gen-mig-diffs/exceptions.go +++ b/ignite/internal/tools/gen-mig-diffs/diff/exceptions.go @@ -1,4 +1,4 @@ -package main +package diff import ( "path/filepath" diff --git a/ignite/internal/tools/gen-mig-diffs/main.go b/ignite/internal/tools/gen-mig-diffs/main.go index bbc33c24de..ad7dbd25ba 100644 --- a/ignite/internal/tools/gen-mig-diffs/main.go +++ b/ignite/internal/tools/gen-mig-diffs/main.go @@ -1,597 +1,15 @@ package main import ( - "context" - "flag" "fmt" - "log" "os" - "path/filepath" - "sort" - "strings" - "github.com/Masterminds/semver/v3" - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing" - "github.com/hexops/gotextdiff" - "github.com/hexops/gotextdiff/myers" - "github.com/hexops/gotextdiff/span" - "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/exec" - "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/step" - "github.com/pkg/errors" + "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/cmd" ) -const ( - igniteCliRepository = "http://github.com/ignite/cli.git" - igniteBinaryPath = "dist/ignite" - igniteRepoPath = "src/github.com/ignite/cli" -) - -var scaffoldCommands = map[string][]string{ - "chain": {"chain example --no-module"}, - "module": {"chain example"}, - "list": { - "chain example", - "list list1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", - }, - "map": { - "chain example", - "map map1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --index f10:string --module example --yes", - }, - "single": { - "chain example", - "single single1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", - }, - "type": { - "chain example", - "type type1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", - }, - "message": { - "chain example", - "message message1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", - }, - "query": { - "chain example", - "query query1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints --module example --yes", - }, - "packet": { - "chain example --no-module", - "module example --ibc", - "packet packet1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --ack f1:string,f2:strings,f3:bool,f4:int,f5:ints,f6:uint,f7:uints,f8:coin,f9:coins --module example --yes", - }, -} - func main() { - var logger = log.New(os.Stdout, "", log.LstdFlags) - - fromFlag := flag.String("from", "", "Semver tag to generate migration document from") - toFlag := flag.String("to", "", "Semver tag to generate migration document to") - sourceFlag := flag.String("source", "", "Source code directory of ignite cli repository (will be cloned if not provided)") - flag.Parse() - - var ( - fromVer, toVer *semver.Version - err error - ) - if fromFlag != nil && *fromFlag != "" { - fromVer, err = semver.NewVersion(*fromFlag) - if err != nil { - logger.Fatalf("Invalid semver tag: %s", *fromFlag) - } - } - if toFlag != nil && *toFlag != "" { - toVer, err = semver.NewVersion(*toFlag) - if err != nil { - logger.Fatalf("Invalid semver tag: %s", *toFlag) - } - } - - err = run(fromVer, toVer, sourceFlag, logger) - if err != nil { - logger.Fatal(err) - } -} - -func run(fromVer, toVer *semver.Version, source *string, logger *log.Logger) error { - // A temporary directory is created to clone ignite cli repository and build it - tmpdir, err := os.MkdirTemp("", ".migdoc") - defer os.RemoveAll(tmpdir) - if err != nil { - return err - } - logger.Println("Created temporary directory:", tmpdir) - - var ( - repoDir string - repo *git.Repository - ) - if source != nil && *source != "" { - logger.Println("Using source code directory:", *source) - repoDir = *source - repo, err = git.PlainOpen(*source) - if err != nil { - return err - } - } else { - logger.Println("Cloning", igniteCliRepository) - repoDir := filepath.Join(tmpdir, igniteRepoPath) - repo, err = git.PlainClone(repoDir, false, &git.CloneOptions{ - URL: igniteCliRepository, - }) - if err != nil { - return err - } - } - - versions, err := getRepositoryVersionTags(repo) - if err != nil { - return err - } - - fromVer, toVer, err = validateVersionRange(fromVer, toVer, versions) - - logger.Printf("Generating migration document for %s->%s\n", fromVer, toVer) - - wt, err := repo.Worktree() - if err != nil { - return errors.Wrap(err, "failed to get worktree") - } - - // Run scaffolds for fromVer and toVer - fromVerDir := filepath.Join(tmpdir, fromVer.Original()) - err = runScaffoldsForVersion(wt, repoDir, fromVerDir, fromVer) - if err != nil { - return errors.Wrapf(err, "failed to run scaffolds for tag %s", fromVer) - } - toVerDir := filepath.Join(tmpdir, toVer.Original()) - err = runScaffoldsForVersion(wt, repoDir, toVerDir, toVer) - if err != nil { - return errors.Wrapf(err, "failed to run scaffolds for tag %s", toVer) - } - - // Run diff between two directories - logger.Println("Generating diff...") - diffMap, err := calculateDiff(fromVerDir, toVerDir) - if err != nil { - return err - } - err = subtractBaseDiffs(diffMap) - if err != nil { - return err - } - - outputDir := fmt.Sprintf("migdoc-%s-%s", fromVer, toVer) - err = os.MkdirAll(outputDir, os.ModePerm) - if err != nil { - return err - } - err = saveDiffMap(diffMap, outputDir) - if err != nil { - return err - } - logger.Println("Migration document generated successfully at", outputDir) - - return nil -} - -func getRepositoryVersionTags(repo *git.Repository) (semver.Collection, error) { - tags, err := repo.Tags() - if err != nil { - return nil, errors.Wrap(err, "failed to get tags") - } - - // Iterate over all tags in the repository and pick valid semver tags - var versions semver.Collection - err = tags.ForEach(func(ref *plumbing.Reference) error { - name := ref.Name() - if name.IsTag() { - ver, err := semver.NewVersion(name.Short()) - if err != nil { - // Do nothing as it's not a semver tag - return nil - } - versions = append(versions, ver) - } - return nil - }) - if err != nil { - return nil, errors.Wrap(err, "failed to iterate over tags") - } - - sort.Sort(versions) - - return versions, nil -} - -func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collection) (*semver.Version, *semver.Version, error) { - // Unable to generate migration document if there are less than two releases! - if versions.Len() < 2 { - return nil, nil, errors.New("At least two semver tags are required") - } - - // Replace fromVer and toVer with equivalent semver tags from versions - if fromVer != nil { - found := false - for _, ver := range versions { - if ver.Equal(fromVer) { - fromVer = ver - found = true - break - } - } - if !found { - return nil, nil, errors.Errorf("tag %s not found", fromVer) - } - } - if toVer != nil { - found := false - for _, ver := range versions { - if ver.Equal(toVer) { - toVer = ver - found = true - break - } - } - if !found { - return nil, nil, errors.Errorf("tag %s not found", toVer) - } - } - - // Picking default values for fromVer and toVer such that: - // If both fromVer and toVer are not provided, then generate migration document for second last and last semver tags - // If only fromVer is not provided, then use the tag before toVer as fromVer - // If only toVer is not provided, then use the last tag as toVer - if fromVer == nil { - if toVer != nil { - sort.Search(versions.Len(), func(i int) bool { - if versions[i].LessThan(toVer) { - fromVer = versions[i] - return false - } - return true - }) - } else { - fromVer = versions[versions.Len()-2] - } - } - if toVer == nil { - toVer = versions[versions.Len()-1] - } - - // Unable to generate migration document if fromVer is greater or equal to toVer - if fromVer.GreaterThan(toVer) || fromVer.Equal(toVer) { - return nil, nil, errors.Errorf("from version %s should be less than to version %s", fromVer, toVer) - } - - return fromVer, toVer, nil -} - -// Run scaffolds commands one by one with the given version of ignite cli and save the output in the output directory -func runScaffoldsForVersion(wt *git.Worktree, repoDir, outputDir string, ver *semver.Version) error { - err := checkoutAndBuildIgniteCli(wt, ver.Original(), repoDir) - if err != nil { - return err - } - - binPath := filepath.Join(repoDir, igniteBinaryPath) - err = executeScaffoldCommands(binPath, outputDir, ver) - if err != nil { - return err - } - - err = applyVersionExceptions(outputDir, ver) - if err != nil { - return err - } - - return nil -} - -func checkoutAndBuildIgniteCli(wt *git.Worktree, tag, repoDir string) error { - err := wt.Checkout(&git.CheckoutOptions{ - Branch: plumbing.NewTagReferenceName(tag), - }) - if err != nil { - return errors.Wrapf(err, "failed to checkout tag %s", tag) - } - - err = exec.Exec(context.Background(), []string{"make", "build"}, exec.StepOption(step.Workdir(repoDir))) - if err != nil { - return errors.Wrap(err, "failed to build ignite cli using make build") + if err := cmd.NewRootCmd().Execute(); err != nil { + fmt.Println(err) + os.Exit(1) } - - return nil -} - -func executeScaffoldCommands(ignitePath, outputDir string, ver *semver.Version) error { - for name, cmds := range scaffoldCommands { - for _, cmd := range cmds { - args := []string{ignitePath, "scaffold"} - args = append(args, strings.Fields(cmd)...) - pathFlag := filepath.Join(outputDir, name) - if !strings.HasPrefix(cmd, "chain") && ver.LessThan(semver.MustParse("v0.27.0")) { - pathFlag = filepath.Join(outputDir, name, "example") - } - args = append(args, "--path", pathFlag) - err := exec.Exec(context.Background(), args, exec.StepOption(step.Stdout(os.Stdout)), exec.StepOption(step.Stderr(os.Stderr))) - if err != nil { - return errors.Wrapf(err, "failed to execute ignite scaffold command: %s", cmd) - } - } - - } - return nil -} - -func applyVersionExceptions(outputDir string, ver *semver.Version) error { - if ver.LessThan(semver.MustParse("v0.27.0")) { - // Move files from the "example" directory to the parent directory for each scaffold directory - for name := range scaffoldCommands { - err := os.Rename(filepath.Join(outputDir, name, "example"), filepath.Join(outputDir, "example_tmp")) - if err != nil { - return errors.Wrapf(err, "failed to move %s directory to tmp directory", name) - } - - err = os.RemoveAll(filepath.Join(outputDir, name)) - if err != nil { - return errors.Wrapf(err, "failed to remove %s directory", name) - } - - err = os.Rename(filepath.Join(outputDir, "example_tmp"), filepath.Join(outputDir, name)) - if err != nil { - return errors.Wrapf(err, "failed to move tmp directory to %s directory", name) - } - } - } - - return nil -} - -func calculateDiff(fromVerDir, toVerDir string) (map[string][]gotextdiff.Unified, error) { - diffMap := make(map[string][]gotextdiff.Unified) - for name := range scaffoldCommands { - diffs, err := diff(filepath.Join(fromVerDir, name), filepath.Join(toVerDir, name)) - if err != nil { - return nil, err - } - diffMap[name] = diffs - } - - return diffMap, nil -} - -func diff(dir1, dir2 string) ([]gotextdiff.Unified, error) { - var ( - diffs []gotextdiff.Unified - marked map[string]struct{} = make(map[string]struct{}) - ) - - dirsLCP := longestCommonPrefix(dir1, dir2) - - // Consider dir1 as reference and walk through all of the files comparing them with files in dir2. - err := filepath.Walk(dir1, func(path string, info os.FileInfo, err error) error { - if info.IsDir() { - return nil - } - - if isException(path) { - return nil - } - - relPath, err := filepath.Rel(dir1, path) - if err != nil { - return err - } - marked[relPath] = struct{}{} - - file1, err := os.ReadFile(path) - if err != nil { - return err - } - str1 := string(file1) - - file2, err := os.ReadFile(filepath.Join(dir2, relPath)) - if !os.IsNotExist(err) && err != nil { - return err - } - str2 := string(file2) - - edits := myers.ComputeEdits(span.URIFromPath(relPath), str1, str2) - if len(edits) > 0 { - fromPath, err := filepath.Rel(dirsLCP, path) - if err != nil { - panic(err) - } - toPath, err := filepath.Rel(dirsLCP, filepath.Join(dir2, relPath)) - if err != nil { - panic(err) - } - diffs = append(diffs, gotextdiff.ToUnified(fromPath, toPath, str1, edits)) - } - return nil - }) - if err != nil { - return diffs, err - } - - // Walk through all of the files in dir2 that were not compared with files in dir1. - err = filepath.Walk(dir2, func(path string, info os.FileInfo, err error) error { - if info.IsDir() { - return nil - } - - if isException(path) { - return nil - } - - relPath, err := filepath.Rel(dir2, path) - if err != nil { - return err - } - if _, ok := marked[relPath]; ok { - return nil - } - - str1 := "" - - file2, err := os.ReadFile(path) - if err != nil { - return err - } - str2 := string(file2) - - edits := myers.ComputeEdits(span.URIFromPath(relPath), str1, str2) - fromPath, err := filepath.Rel(dirsLCP, filepath.Join(dir1, relPath)) - if err != nil { - panic(err) - } - toPath, err := filepath.Rel(dirsLCP, path) - if err != nil { - panic(err) - } - diffs = append(diffs, gotextdiff.ToUnified(fromPath, toPath, str1, edits)) - return nil - }) - return diffs, nil -} - -func longestCommonPrefix(strs ...string) string { - longest := strings.Split(strs[0], string(filepath.Separator)) - - cmp := func(a []string) { - if len(a) < len(longest) { - longest = longest[:len(a)] - } - for i := 0; i < len(longest); i++ { - if a[i] != longest[i] { - longest = longest[:i] - return - } - } - } - - for i := 1; i < len(strs); i++ { - r := strings.Split(strs[i], string(filepath.Separator)) - cmp(r) - } - return "/" + filepath.Join(longest...) -} - -func subtractBaseDiffs(diffMap map[string][]gotextdiff.Unified) error { - // Remove chain and module diffs from other diffs - chainDiffs := diffMap["chain"] - moduleDiffs := diffMap["module"] - for name, diffs := range diffMap { - if name == "module" { - diffs = subtractDiffs(diffs, chainDiffs) - } else if name != "chain" { - diffs = subtractDiffs(diffs, moduleDiffs) - } - diffMap[name] = diffs - } - - return nil -} - -func subtractDiffs(src []gotextdiff.Unified, base []gotextdiff.Unified) []gotextdiff.Unified { - dst := make([]gotextdiff.Unified, 0, len(src)) - for i := 0; i < len(src); i++ { - edited := false - for j := 0; j < len(base); j++ { - if equalScaffoldPaths(src[i].From, base[j].From) && equalScaffoldPaths(src[i].To, base[j].To) { - if hs := subtractHunks(src[i].Hunks, base[j].Hunks); len(hs) > 0 { - dst = append(dst, gotextdiff.Unified{ - From: src[i].From, - To: src[i].To, - Hunks: subtractHunks(src[i].Hunks, base[j].Hunks), - }) - } - edited = true - } - } - - if !edited { - dst = append(dst, src[i]) - } - } - - return dst -} - -func subtractHunks(src []*gotextdiff.Hunk, base []*gotextdiff.Hunk) []*gotextdiff.Hunk { - dst := make([]*gotextdiff.Hunk, 0, len(src)) - for i := 0; i < len(src); i++ { - edited := false - for j := 0; j < len(base); j++ { - if src[i].FromLine <= base[j].FromLine && src[i].ToLine >= base[j].ToLine { - if h := subtractHunk(src[i], base[j]); h != nil { - dst = append(dst, h) - } - edited = true - } - } - - if !edited { - dst = append(dst, src[i]) - } - } - - return dst -} - -func subtractHunk(src, base *gotextdiff.Hunk) *gotextdiff.Hunk { - newLines := make([]gotextdiff.Line, 0, len(src.Lines)) - equals := 0 - for i := 0; i < len(src.Lines); i++ { - rep := false - for j := 0; j < len(base.Lines); j++ { - if src.Lines[i].Kind != gotextdiff.Equal && src.Lines[i].Kind == base.Lines[j].Kind && src.Lines[i].Content == base.Lines[j].Content { - rep = true - break - } - } - - if !rep { - newLines = append(newLines, src.Lines[i]) - } - - if src.Lines[i].Kind == gotextdiff.Equal { - equals++ - } - } - - // If all the lines in the hunk are equal or there's no line left, then return nil - if equals == len(newLines) || len(newLines) == 0 { - return nil - } - - return &gotextdiff.Hunk{ - FromLine: src.FromLine, - ToLine: src.ToLine, - Lines: newLines, - } -} - -func equalScaffoldPaths(a, b string) bool { - // Remove the first two directories from the path (version/scaffold_type) and compare the rest - a = strings.Join(strings.Split(a, string(filepath.Separator))[2:], string(filepath.Separator)) - b = strings.Join(strings.Split(b, string(filepath.Separator))[2:], string(filepath.Separator)) - - return a == b -} - -func saveDiffMap(diffMap map[string][]gotextdiff.Unified, outputPath string) error { - for name, diffs := range diffMap { - outf, err := os.Create(filepath.Join(outputPath, name+".diff")) - if err != nil { - return err - } - defer outf.Close() - for _, diff := range diffs { - outf.WriteString(fmt.Sprint(diff)) - outf.WriteString("\n") - } - } - - return nil -} +} \ No newline at end of file diff --git a/ignite/internal/tools/gen-mig-diffs/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/scaffold/scaffold.go new file mode 100644 index 0000000000..3077450360 --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/scaffold/scaffold.go @@ -0,0 +1,191 @@ +package scaffold + +import ( + "context" + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/Masterminds/semver/v3" + "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/exec" + "github.com/ignite/cli/v28/ignite/pkg/errors" +) + +var DefaultScaffoldCommands = []ScaffoldCommand{ + { + Name: "chain", + Commands: []string{ + "chain example --no-module", + }, + }, + { + Name: "module", + Prerequisites: []string{"chain"}, + Commands: []string{ + "module example --ibc", + }, + }, + { + Name: "list", + Prerequisites: []string{"module"}, + Commands: []string{ + "list list1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", + }, + }, + { + Name: "map", + Prerequisites: []string{"module"}, + Commands: []string{ + "map map1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --index i1:string --module example --yes", + }, + }, + { + Name: "single", + Prerequisites: []string{"module"}, + Commands: []string{ + "single single1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", + }, + }, + { + Name: "type", + Prerequisites: []string{"module"}, + Commands: []string{ + "type type1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", + }, + }, + { + Name: "message", + Prerequisites: []string{"module"}, + Commands: []string{ + "message message1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", + }, + }, + { + Name: "query", + Prerequisites: []string{"module"}, + Commands: []string{ + "query query1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints --module example --yes", + }, + }, + { + Name: "packet", + Prerequisites: []string{"module"}, + Commands: []string{ + "packet packet1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --ack f1:string,f2:strings,f3:bool,f4:int,f5:ints,f6:uint,f7:uints,f8:coin,f9:coins --module example --yes", + }, + }, +} + +// ScaffoldCommand represents a set of commands and prerequisites scaffold commands that are required to run before them +type ScaffoldCommand struct { + // Name is the unique identifier of the command + Name string + // Prerequisites is the names of commands that need to be run before this command set + Prerequisites []string + // Commands is the list of scaffold commands that are going to be run + // The commands will be prefixed with "ignite scaffold" and executed in order + Commands []string +} + +type Scaffolder struct { + ignitePath string + commands []ScaffoldCommand +} + +func NewScaffolder(ignitePath string, commands []ScaffoldCommand) *Scaffolder { + return &Scaffolder{ + ignitePath: ignitePath, + commands: commands, + } +} + +func (s *Scaffolder) RunScaffolds(ver *semver.Version, out string) error { + for _, command := range s.commands { + if err := s.runCommand(command, ver, out); err != nil { + return err + } + } + return nil +} + +func (s *Scaffolder) runCommand(command ScaffoldCommand, ver *semver.Version, out string) error { + for _, pr := range command.Prerequisites { + c, err := s.findCommand(pr) + if err != nil { + return err + } + if err := s.runCommand(c, ver, out); err != nil { + return err + } + } + + for _, cmd := range command.Commands { + if err := s.executeScaffold(command.Name, cmd, ver, out); err != nil { + return err + } + } + return nil +} + +func (s *Scaffolder) findCommand(name string) (ScaffoldCommand, error) { + for _, c := range s.commands { + if c.Name == name { + return c, nil + } + } + + return ScaffoldCommand{}, fmt.Errorf("command %s not found", name) +} + +func (s *Scaffolder) executeScaffold(name, cmd string, ver *semver.Version, out string) error { + args := []string{s.ignitePath, "scaffold"} + args = append(args, strings.Fields(cmd)...) + args = append(args, "--path", filepath.Join(out, name)) + args = applyPreScaffoldExceptions(ver, args) + + if err := exec.Exec(context.Background(), args); err != nil { + return errors.Wrapf(err, "failed to execute ignite scaffold command: %s", cmd) + } + + if err := applyPostScaffoldExceptions(ver, name, out); err != nil { + return err + } + + return nil +} + +// In this function we can manipulate command arguments before executing it in order to compensate for differences in versions. +func applyPreScaffoldExceptions(ver *semver.Version, args []string) []string { + // In versions <0.27.0, "scaffold chain" command always creates a new directory with the name of chain at the given --path + // so we need to append "example" to the path if the command is not "chain" + if ver.LessThan(semver.MustParse("v0.27.0")) && args[2] != "chain" { + (args)[len(args)-1] = filepath.Join(args[len(args)-1], "example") + } + + return args +} + +// In this function we can manipulate the output of scaffold commands after they have been executed in order to compensate for differences in versions. +func applyPostScaffoldExceptions(ver *semver.Version, name string, out string) error { + // In versions <0.27.0, "scaffold chain" command always creates a new directory with the name of chain at the given --path + // so we need to move the directory to the parent directory. + if ver.LessThan(semver.MustParse("v0.27.0")) { + err := os.Rename(filepath.Join(out, name, "example"), filepath.Join(out, "example_tmp")) + if err != nil { + return errors.Wrapf(err, "failed to move %s directory to tmp directory", name) + } + + err = os.RemoveAll(filepath.Join(out, name)) + if err != nil { + return errors.Wrapf(err, "failed to remove %s directory", name) + } + + err = os.Rename(filepath.Join(out, "example_tmp"), filepath.Join(out, name)) + if err != nil { + return errors.Wrapf(err, "failed to move tmp directory to %s directory", name) + } + } + + return nil +} From 90b2d304a46eb082e5f4e879c536937a5b9a07d8 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Tue, 6 Feb 2024 11:18:14 +0330 Subject: [PATCH 10/69] Clean up error handling --- ignite/internal/tools/gen-mig-diffs/cmd/root.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 1e19e09411..b322a714dc 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -252,7 +252,7 @@ func runScaffoldsForVersion(repoDir, outputDir string, ver *semver.Version) erro scaffolder := scaffold.NewScaffolder(binPath, scaffold.DefaultScaffoldCommands) err = scaffolder.RunScaffolds(ver, outputDir) if err != nil { - return errors.Wrapf(err, "failed to run scaffolds for tag %s", ver) + return err } return nil From eaeceee28dbaf7810c70ef20d9d426f48a37e6b7 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Wed, 7 Feb 2024 15:47:24 +0330 Subject: [PATCH 11/69] Add diff package --- ignite/pkg/diff/compute.go | 109 ++++++++++++++++++++++++++++++++ ignite/pkg/diff/compute_test.go | 56 ++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 ignite/pkg/diff/compute.go create mode 100644 ignite/pkg/diff/compute_test.go diff --git a/ignite/pkg/diff/compute.go b/ignite/pkg/diff/compute.go new file mode 100644 index 0000000000..0f31fea6a1 --- /dev/null +++ b/ignite/pkg/diff/compute.go @@ -0,0 +1,109 @@ +package diff + +import ( + "fmt" + "io/fs" + "os" + "path/filepath" + + "github.com/gobwas/glob" + "github.com/hexops/gotextdiff" + "github.com/hexops/gotextdiff/myers" + "github.com/hexops/gotextdiff/span" +) + +// ComputeFS computes the unified diffs between the origin and modified filesystems. +// but ignores files that match the given globs. +func ComputeFS(origin, modified fs.FS, ignoreGlobs ...string) ([]gotextdiff.Unified, error) { + compiledGlobs, err := compileGlobs(ignoreGlobs) + if err != nil { + return nil, err + } + + marked := make(map[string]struct{}) + unified := make([]gotextdiff.Unified, 0) + err = fs.WalkDir(origin, ".", func(path string, d fs.DirEntry, err error) error { + if d.IsDir() { + return nil + } + + if matchGlobs(compiledGlobs, path) { + return nil + } + + marked[path] = struct{}{} + data, err := fs.ReadFile(origin, path) + if err != nil { + return fmt.Errorf("failed to read file %q from origin: %w", path, err) + } + originFile := string(data) + + data, err = fs.ReadFile(modified, path) + if !os.IsNotExist(err) && err != nil { + return fmt.Errorf("failed to read file %q from modified: %w", path, err) + } + modifiedFile := string(data) + + edits := myers.ComputeEdits(span.URIFromURI(fmt.Sprintf("file://%s", path)), originFile, modifiedFile) + if len(edits) > 0 { + unified = append(unified, gotextdiff.ToUnified(path, path, originFile, edits)) + } + return nil + }) + if err != nil { + return nil, err + } + + err = fs.WalkDir(modified, ".", func(path string, d fs.DirEntry, err error) error { + if d.IsDir() { + return nil + } + + if matchGlobs(compiledGlobs, path) { + return nil + } + + if _, ok := marked[path]; ok { + return nil + } + + originFile := "" + data, err := fs.ReadFile(modified, path) + if err != nil { + return fmt.Errorf("failed to read file %q from modified: %w", path, err) + } + modifiedFile := string(data) + + edits := myers.ComputeEdits(span.URIFromURI(fmt.Sprintf("file://%s", path)), originFile, modifiedFile) + if len(edits) > 0 { + unified = append(unified, gotextdiff.ToUnified(path, path, originFile, edits)) + } + return nil + }) + if err != nil { + return nil, err + } + + return unified, nil +} + +func compileGlobs(globs []string) ([]glob.Glob, error) { + var compiledGlobs []glob.Glob + for _, g := range globs { + compiledGlob, err := glob.Compile(g, filepath.Separator) + if err != nil { + return nil, fmt.Errorf("failed to compile glob %q: %w", g, err) + } + compiledGlobs = append(compiledGlobs, compiledGlob) + } + return compiledGlobs, nil +} + +func matchGlobs(globs []glob.Glob, path string) bool { + for _, g := range globs { + if g.Match(path) { + return true + } + } + return false +} diff --git a/ignite/pkg/diff/compute_test.go b/ignite/pkg/diff/compute_test.go new file mode 100644 index 0000000000..73d86db468 --- /dev/null +++ b/ignite/pkg/diff/compute_test.go @@ -0,0 +1,56 @@ +package diff_test + +import ( + "testing" + "testing/fstest" + + "github.com/ignite/cli/v28/ignite/pkg/diff" + "github.com/stretchr/testify/require" +) + +func TestComputeFS(t *testing.T) { + require := require.New(t) + + origin := fstest.MapFS{ + "foo.txt": &fstest.MapFile{ + Data: []byte("hello"), + }, + "bar.txt": &fstest.MapFile{ + Data: []byte("unmodified"), + }, + "pkg/main.go": &fstest.MapFile{ + Data: []byte("package main"), + }, + } + modified := fstest.MapFS{ + "foo.txt": &fstest.MapFile{ + Data: []byte("world"), + }, + "bar.txt": &fstest.MapFile{ + Data: []byte("unmodified"), + }, + "new.txt": &fstest.MapFile{ + Data: []byte("new file"), + }, + "pkg/main.go": &fstest.MapFile{ + Data: []byte("package main\nfunc main() {}"), + }, + } + + unified, err := diff.ComputeFS(origin, modified) + require.NoError(err) + require.Len(unified, 3) + expectedFiles := []string{"foo.txt", "new.txt", "pkg/main.go"} + for _, u := range unified { + require.Contains(expectedFiles, u.From, "unexpected file in diff: %s", u.From) + } + + // Test ignoring files + unified, err = diff.ComputeFS(origin, modified, "**.go") + require.NoError(err) + require.Len(unified, 2) + expectedFiles = []string{"foo.txt", "new.txt"} + for _, u := range unified { + require.Contains(expectedFiles, u.From, "unexpected file in diff: %s", u.From) + } +} From acabaaae3bd7d3f025a622d18bae2b18af3e9f70 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Wed, 7 Feb 2024 17:23:49 +0330 Subject: [PATCH 12/69] Add Subtract to diff package --- ignite/pkg/diff/subtract.go | 168 +++++++++++++++++++++++++++++++ ignite/pkg/diff/subtract_test.go | 65 ++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 ignite/pkg/diff/subtract.go create mode 100644 ignite/pkg/diff/subtract_test.go diff --git a/ignite/pkg/diff/subtract.go b/ignite/pkg/diff/subtract.go new file mode 100644 index 0000000000..46b1b408a3 --- /dev/null +++ b/ignite/pkg/diff/subtract.go @@ -0,0 +1,168 @@ +package diff + +import ( + "sort" + + "github.com/hexops/gotextdiff" +) + +// Sutract two unified diffs from each other. +func Subtract(a, b gotextdiff.Unified) gotextdiff.Unified { + return gotextdiff.Unified{ + From: a.From, + To: a.To, + Hunks: subtractHunks(a.Hunks, b.Hunks), + } +} + +func subtractHunks(src, base []*gotextdiff.Hunk) []*gotextdiff.Hunk { + sortHunks(src) + sortHunks(base) + + res := make([]*gotextdiff.Hunk, 0, len(src)) + offset := 0 + for i, j := 0, 0; i < len(src) && j < len(base); { + s := src[i] + b := base[j] + + switch { + case beforeHunk(s, b, offset): + res = append(res, s) + offset += calculateHunkOffsetChange(s.Lines) + i++ + case beforeHunk(b, s, -offset): + j++ + case hunksOverlap(s, b, offset): + if s.FromLine < b.FromLine { + res = append(res, s) + offset += calculateHunkOffsetChange(s.Lines) - calculateHunkOffsetChange(b.Lines) + i++ + } else { + offset += calculateHunkOffsetChange(s.Lines) - calculateHunkOffsetChange(b.Lines) + j++ + } + default: + h := subtractHunk(s, b) + if !isHunkEmpty(h) { + res = append(res, subtractHunk(s, b)) + } + offset += calculateHunkOffsetChange(s.Lines) - calculateHunkOffsetChange(b.Lines) + i++ + j++ + } + + } + + return res +} + +func sortHunks(hunks []*gotextdiff.Hunk) { + sort.Slice(hunks, func(i, j int) bool { + return hunks[i].FromLine < hunks[j].FromLine + }) +} + +// beforeHunk returns true if a comes before b. +func beforeHunk(a, b *gotextdiff.Hunk, offset int) bool { + return a.ToLine-calculateEndEqualLines(a) < b.FromLine-calculateStartEqualLines(b)+offset +} + +func calculateStartEqualLines(h *gotextdiff.Hunk) int { + lines := 0 + for _, l := range h.Lines { + switch l.Kind { + case gotextdiff.Equal: + lines++ + default: + break + } + } + return lines +} + +func calculateEndEqualLines(h *gotextdiff.Hunk) int { + lines := 0 + for i := len(h.Lines) - 1; i >= 0; i-- { + switch h.Lines[i].Kind { + case gotextdiff.Equal: + lines++ + default: + break + } + } + return lines +} + +func calculateHunkOffsetChange(lines []gotextdiff.Line) int { + offset := 0 + for _, l := range lines { + switch l.Kind { + case gotextdiff.Delete: + offset-- + case gotextdiff.Insert: + offset++ + } + } + return offset +} + +func hunksOverlap(a, b *gotextdiff.Hunk, offset int) bool { + if !isLineInHunk(a.FromLine, b, offset) && isLineInHunk(a.ToLine, b, offset) { + return true + } + if isLineInHunk(a.FromLine, b, offset) && !isLineInHunk(a.ToLine, b, offset) { + return true + } + return false +} + +func isLineInHunk(line int, h *gotextdiff.Hunk, offset int) bool { + return line-calculateStartEqualLines(h) >= h.FromLine+offset && line+calculateEndEqualLines(h) <= h.ToLine+offset +} + +func subtractHunk(a, b *gotextdiff.Hunk) *gotextdiff.Hunk { + lines := subtractLines(a.Lines, b.Lines) + return &gotextdiff.Hunk{ + FromLine: a.FromLine, + ToLine: a.ToLine + calculateHunkOffsetChange(a.Lines) - calculateHunkOffsetChange(lines), + Lines: lines, + } +} + +func subtractLines(a, b []gotextdiff.Line) []gotextdiff.Line { + res := make([]gotextdiff.Line, 0, len(a)) + for i, j := 0, 0; i < len(a) && j < len(b); { + la := a[i] + lb := b[j] + + if la == lb { + if la.Kind == gotextdiff.Equal { + res = append(res, la) + } + i++ + j++ + continue + } + + if i < len(a) { + res = append(res, la) + i++ + continue + } + if j < len(b) { + j++ + } + } + + return res +} + +func isHunkEmpty(h *gotextdiff.Hunk) bool { + effectiveLines := 0 + for _, l := range h.Lines { + if l.Kind != gotextdiff.Equal { + effectiveLines++ + } + } + return effectiveLines == 0 +} diff --git a/ignite/pkg/diff/subtract_test.go b/ignite/pkg/diff/subtract_test.go new file mode 100644 index 0000000000..a0b4a37ba5 --- /dev/null +++ b/ignite/pkg/diff/subtract_test.go @@ -0,0 +1,65 @@ +package diff_test + +import ( + "reflect" + "testing" + + "github.com/hexops/gotextdiff" + "github.com/ignite/cli/v28/ignite/pkg/diff" +) + +func TestSubtract(t *testing.T) { + type args struct { + a gotextdiff.Unified + b gotextdiff.Unified + } + tests := []struct { + name string + args args + want gotextdiff.Unified + }{ + { + name: "Equal diffs", + args: args{ + a: gotextdiff.Unified{ + Hunks: []*gotextdiff.Hunk{ + { + FromLine: 1, + ToLine: 3, + Lines: []gotextdiff.Line{ + {Kind: gotextdiff.Equal, Content: "equal1"}, + {Kind: gotextdiff.Insert, Content: "insert1"}, + {Kind: gotextdiff.Equal, Content: "equal2"}, + {Kind: gotextdiff.Delete, Content: "delete1"}, + }, + }, + }, + }, + b: gotextdiff.Unified{ + Hunks: []*gotextdiff.Hunk{ + { + FromLine: 1, + ToLine: 3, + Lines: []gotextdiff.Line{ + {Kind: gotextdiff.Equal, Content: "equal1"}, + {Kind: gotextdiff.Insert, Content: "insert1"}, + {Kind: gotextdiff.Equal, Content: "equal2"}, + {Kind: gotextdiff.Delete, Content: "delete1"}, + }, + }, + }, + }, + }, + want: gotextdiff.Unified{ + Hunks: []*gotextdiff.Hunk{}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := diff.Subtract(tt.args.a, tt.args.b); !reflect.DeepEqual(got, tt.want) { + t.Errorf("Subtract() = %v, want %v", got, tt.want) + } + }) + } +} From 7ba7ecebb91fac06293cf09f50b0ad622a790ffa Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Thu, 8 Feb 2024 14:55:55 +0330 Subject: [PATCH 13/69] Cleanup gen-mig-diffs --- .../internal/tools/gen-mig-diffs/cmd/root.go | 322 ++--------------- .../internal/tools/gen-mig-diffs/diff/diff.go | 298 --------------- .../tools/gen-mig-diffs/diff/exceptions.go | 39 -- .../tools/gen-mig-diffs/migdiff/migdiff.go | 341 ++++++++++++++++++ .../{scaffold => migdiff}/scaffold.go | 6 +- 5 files changed, 366 insertions(+), 640 deletions(-) delete mode 100644 ignite/internal/tools/gen-mig-diffs/diff/diff.go delete mode 100644 ignite/internal/tools/gen-mig-diffs/diff/exceptions.go create mode 100644 ignite/internal/tools/gen-mig-diffs/migdiff/migdiff.go rename ignite/internal/tools/gen-mig-diffs/{scaffold => migdiff}/scaffold.go (97%) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index b322a714dc..715aaadeb5 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -1,28 +1,15 @@ package cmd import ( - "context" - "fmt" - "log" - "os" - "path/filepath" - "sort" - semver "github.com/Masterminds/semver/v3" - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing" - "github.com/hexops/gotextdiff" - "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/diff" - "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/scaffold" - "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/exec" - "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/step" + "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/migdiff" "github.com/ignite/cli/v28/ignite/pkg/errors" "github.com/spf13/cobra" ) const ( - fromFlag = "from" - toFlag = "to" + fromFlag = "from" + toFlag = "to" outputFlag = "output" igniteCliRepository = "http://github.com/ignite/cli.git" @@ -36,297 +23,32 @@ func NewRootCmd() *cobra.Command { Use: "gen-mig-diffs", Short: "Generate migration diffs", Long: "This tool is used to generate migration diff files for each of ignites scaffold commands", - RunE: generateMigrationDiffs, - } - - cmd.Flags().StringP(fromFlag,"f", "", "Version of ignite or path to ignite source code to generate the diff from") - cmd.Flags().StringP(toFlag, "t", "", "Version of ignite or path to ignite source code to generate the diff to") - cmd.Flags().StringP(outputFlag, "o", ".", "Output directory to save the migration diff files") - - return cmd -} - -func generateMigrationDiffs(cmd *cobra.Command, args []string) error { - from, _ := cmd.Flags().GetString(fromFlag) - to, _ := cmd.Flags().GetString(toFlag) - output, _ := cmd.Flags().GetString(outputFlag) - - // A temporary directory is created to clone ignite cli repository and build it - tmpdir, err := os.MkdirTemp("", ".migdoc") - defer os.RemoveAll(tmpdir) - if err != nil { - return err - } - log.Println("Created temporary directory:", tmpdir) - - var fromVer, toVer *semver.Version - if ver, err := semver.NewVersion(from); err == nil { - fromVer = ver - } - if ver, err := semver.NewVersion(to); err == nil { - toVer = ver - } - - repoDir, err := cloneIgniteRepo(tmpdir) - if err != nil { - return err - } - - versions, err := getRepositoryVersionTags(repoDir) - if err != nil { - return err - } - - fromVer, toVer, err = validateVersionRange(fromVer, toVer, versions) - if err != nil { - return err - } - - log.Printf("Generating migration document for %s->%s\n", fromVer, toVer) - - // Run scaffolds for fromVer and toVer - fromVerDir := filepath.Join(tmpdir, fromVer.Original()) - err = runScaffoldsForVersion(repoDir, fromVerDir, fromVer) - if err != nil { - return errors.Wrapf(err, "failed to run scaffolds for tag %s", fromVer) - } - toVerDir := filepath.Join(tmpdir, toVer.Original()) - err = runScaffoldsForVersion(repoDir, toVerDir, toVer) - if err != nil { - return errors.Wrapf(err, "failed to run scaffolds for tag %s", toVer) - } - - // Run diff between two directories - log.Println("Generating diff...") - diffMap, err := calculateDiff(fromVerDir, toVerDir) - if err != nil { - return err - } - - outputDir := filepath.Join(output, fmt.Sprintf("migdoc-%s-%s", fromVer, toVer)) - err = os.MkdirAll(outputDir, os.ModePerm) - if err != nil { - return err - } - err = saveDiffMap(diffMap, outputDir) - if err != nil { - return err - } - log.Println("Migration document generated successfully at", outputDir) - - return nil -} - -func isStrVersion(s string) bool { - _, err := semver.NewVersion(s) - return err == nil -} - -func cloneIgniteRepo(tmpdir string) (string, error) { - log.Println("Cloning", igniteCliRepository) - - repoDir := filepath.Join(tmpdir, igniteRepoPath) - _, err := git.PlainClone(repoDir, false, &git.CloneOptions{ - URL: igniteCliRepository, - }) - return repoDir, err -} - -// getRepositoryVersionTags returns a sorted collection of semver tags from the ignite cli repository -func getRepositoryVersionTags(repoDir string) (semver.Collection, error) { - repo, err := git.PlainOpen(repoDir) - if err != nil { - return nil, err - } - - tags, err := repo.Tags() - if err != nil { - return nil, errors.Wrap(err, "failed to get tags") - } - - // Iterate over all tags in the repository and pick valid semver tags - var versions semver.Collection - err = tags.ForEach(func(ref *plumbing.Reference) error { - name := ref.Name() - if name.IsTag() { - ver, err := semver.NewVersion(name.Short()) - if err != nil { - // Do nothing as it's not a semver tag - return nil + RunE: func(cmd *cobra.Command, args []string) error { + from, _ := cmd.Flags().GetString(fromFlag) + to, _ := cmd.Flags().GetString(toFlag) + output, _ := cmd.Flags().GetString(outputFlag) + + fromVer, err := semver.NewVersion(from) + if err != nil && from != "" { + return errors.Wrapf(err, "failed to parse from version %s", from) } - versions = append(versions, ver) - } - return nil - }) - if err != nil { - return nil, errors.Wrap(err, "failed to iterate over tags") - } - - sort.Sort(versions) - - return versions, nil -} - -// validateVersionRange checks if the provided fromVer and toVer exist in the versions and if any of them is nil, then it picks default values. -func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collection) (*semver.Version, *semver.Version, error) { - // Unable to generate migration document if there are less than two releases! - if versions.Len() < 2 { - return nil, nil, errors.New("At least two semver tags are required") - } - - // Replace fromVer and toVer with equivalent semver tags from versions - if fromVer != nil { - found := false - for _, ver := range versions { - if ver.Equal(fromVer) { - fromVer = ver - found = true - break - } - } - if !found { - return nil, nil, errors.Errorf("tag %s not found", fromVer) - } - } - if toVer != nil { - found := false - for _, ver := range versions { - if ver.Equal(toVer) { - toVer = ver - found = true - break + toVer, err := semver.NewVersion(to) + if err != nil && to != "" { + return errors.Wrapf(err, "failed to parse to version %s", to) } - } - if !found { - return nil, nil, errors.Errorf("tag %s not found", toVer) - } - } - - // Picking default values for fromVer and toVer such that: - // If both fromVer and toVer are not provided, then generate migration document for second last and last semver tags - // If only fromVer is not provided, then use the tag before toVer as fromVer - // If only toVer is not provided, then use the last tag as toVer - if fromVer == nil { - if toVer != nil { - sort.Search(versions.Len(), func(i int) bool { - if versions[i].LessThan(toVer) { - fromVer = versions[i] - return false - } - return true - }) - } else { - fromVer = versions[versions.Len()-2] - } - } - if toVer == nil { - toVer = versions[versions.Len()-1] - } - - // Unable to generate migration document if fromVer is greater or equal to toVer - if fromVer.GreaterThan(toVer) || fromVer.Equal(toVer) { - return nil, nil, errors.Errorf("from version %s should be less than to version %s", fromVer, toVer) - } - - return fromVer, toVer, nil -} - -// Run scaffolds commands one by one with the given version of ignite cli and save the output in the output directory -func runScaffoldsForVersion(repoDir, outputDir string, ver *semver.Version) error { - repo, err := git.PlainOpen(repoDir) - if err != nil { - return errors.Wrap(err, "failed to open git repository") - } - - wt, err := repo.Worktree() - if err != nil { - return errors.Wrap(err, "failed to get worktree") - } - - err = checkoutAndBuildIgniteCli(wt, ver.Original(), repoDir) - if err != nil { - return err - } - - binPath := filepath.Join(repoDir, igniteBinaryPath) - scaffolder := scaffold.NewScaffolder(binPath, scaffold.DefaultScaffoldCommands) - err = scaffolder.RunScaffolds(ver, outputDir) - if err != nil { - return err - } - return nil -} - -func checkoutAndBuildIgniteCli(wt *git.Worktree, tag, repoDir string) error { - err := wt.Checkout(&git.CheckoutOptions{ - Branch: plumbing.NewTagReferenceName(tag), - }) - if err != nil { - return errors.Wrapf(err, "failed to checkout tag %s", tag) - } - - err = exec.Exec(context.Background(), []string{"make", "build"}, exec.StepOption(step.Workdir(repoDir))) - if err != nil { - return errors.Wrap(err, "failed to build ignite cli using make build") - } - - return nil -} - -func calculateDiff(fromVerDir, toVerDir string) (map[string][]gotextdiff.Unified, error) { - diffMap := make(map[string]*diff.Diff) - for _, s := range scaffold.DefaultScaffoldCommands { - diff, err := diff.ComputeDiff(filepath.Join(fromVerDir, s.Name), filepath.Join(toVerDir, s.Name)) - if err != nil { - return nil, err - } - diffMap[s.Name] = diff - } - - subtractBaseDiffs(diffMap) - - unifiedDiffMap := make(map[string][]gotextdiff.Unified) - for name, diff := range diffMap { - unifiedDiffMap[name] = diff.ToUnified() - } - - return unifiedDiffMap, nil -} - -// subtractBaseDiffs removes chain and module diffs from other diffs -func subtractBaseDiffs(diffMap map[string]*diff.Diff) error { - chainDiff := diffMap["chain"] - moduleDiff := diffMap["module"] - for name, diff := range diffMap { - if name != "chain" && name != "module" { - err := diff.Subtract(moduleDiff) + mdg, err := migdiff.NewMigDiffGenerator(fromVer, toVer) if err != nil { - return errors.Wrapf(err, "failed to subtract module diff from %s diff", name) + return err } - } - diffMap[name] = diff - } - if err := diffMap["module"].Subtract(chainDiff); err != nil { - return errors.Wrap(err, "failed to subtract chain diff from module diff") + return mdg.Generate(output) + }, } - return nil -} - -func saveDiffMap(diffMap map[string][]gotextdiff.Unified, outputPath string) error { - for name, diffs := range diffMap { - outf, err := os.Create(filepath.Join(outputPath, name+".diff")) - if err != nil { - return err - } - defer outf.Close() - for _, diff := range diffs { - outf.WriteString(fmt.Sprint(diff)) - outf.WriteString("\n") - } - } + cmd.Flags().StringP(fromFlag, "f", "", "Version of ignite or path to ignite source code to generate the diff from") + cmd.Flags().StringP(toFlag, "t", "", "Version of ignite or path to ignite source code to generate the diff to") + cmd.Flags().StringP(outputFlag, "o", ".", "Output directory to save the migration diff files") - return nil + return cmd } diff --git a/ignite/internal/tools/gen-mig-diffs/diff/diff.go b/ignite/internal/tools/gen-mig-diffs/diff/diff.go deleted file mode 100644 index 5dd826d003..0000000000 --- a/ignite/internal/tools/gen-mig-diffs/diff/diff.go +++ /dev/null @@ -1,298 +0,0 @@ -package diff - -import ( - "os" - "path/filepath" - "strings" - - "github.com/hexops/gotextdiff" - "github.com/hexops/gotextdiff/myers" - "github.com/hexops/gotextdiff/span" - "github.com/ignite/cli/v28/ignite/pkg/errors" -) - -type Diff struct { - dir1, dir2 string - lcp string - files1, files2 map[string]string - edits []gotextdiff.TextEdit -} - -func ComputeDiff(dir1, dir2 string) (*Diff, error) { - marked := make(map[string]struct{}) - diff := &Diff{ - dir1: dir1, - dir2: dir2, - lcp: longestCommonPrefix(dir1, dir2), - files1: make(map[string]string), - files2: make(map[string]string), - edits: make([]gotextdiff.TextEdit, 0), - } - - // Consider dir1 as reference and walk through all of the files comparing them with files in dir2. - err := filepath.Walk(dir1, func(path string, info os.FileInfo, err error) error { - if info.IsDir() { - return nil - } - - if isException(path) { - return nil - } - - relPath, err := filepath.Rel(dir1, path) - if err != nil { - return err - } - marked[relPath] = struct{}{} - - b, err := os.ReadFile(path) - if err != nil { - return err - } - diff.files1[relPath] = string(b) - - b, err = os.ReadFile(filepath.Join(dir2, relPath)) - // If the file does not exist in dir2, we consider it as an empty file. - if !os.IsNotExist(err) && err != nil { - return err - } - diff.files2[relPath] = string(b) - - edits := myers.ComputeEdits(span.URIFromPath(path), diff.files1[relPath], diff.files2[relPath]) - conv := span.NewContentConverter(span.URIFromPath(path).Filename(), []byte(diff.files1[relPath])) - err = ensureEditsHavePositionAndOffset(edits, conv) - if err != nil { - return err - } - diff.edits = append(diff.edits, edits...) - return nil - }) - if err != nil { - return nil, err - } - - // Walk through all of the files in dir2 that were not compared with files in dir1. - err = filepath.Walk(dir2, func(path string, info os.FileInfo, err error) error { - if info.IsDir() { - return nil - } - - if isException(path) { - return nil - } - - relPath, err := filepath.Rel(dir2, path) - if err != nil { - return err - } - if _, ok := marked[relPath]; ok { - return nil - } - - diff.files1[relPath] = "" - - b, err := os.ReadFile(path) - if err != nil { - return err - } - diff.files2[relPath] = string(b) - - edits := myers.ComputeEdits(span.URIFromPath(filepath.Join(dir1, relPath)), diff.files1[relPath], diff.files2[relPath]) - diff.edits = append(diff.edits, edits...) - return nil - }) - if err != nil { - return nil, err - } - - diff.makeSureEditsAreSorted() - - return diff, err -} - -func longestCommonPrefix(strs ...string) string { - longest := strings.Split(strs[0], string(filepath.Separator)) - - cmp := func(a []string) { - if len(a) < len(longest) { - longest = longest[:len(a)] - } - for i := 0; i < len(longest); i++ { - if a[i] != longest[i] { - longest = longest[:i] - return - } - } - } - - for i := 1; i < len(strs); i++ { - r := strings.Split(strs[i], string(filepath.Separator)) - cmp(r) - } - return "/" + filepath.Join(longest...) -} - -func ensureEditsHavePositionAndOffset(edits []gotextdiff.TextEdit, conv span.Converter) error { - var err error - for i, e := range edits { - edits[i].Span, err = e.Span.WithAll(conv) - if err != nil { - return err - } - } - - return nil -} - -func (d *Diff) makeSureEditsAreSorted() { - gotextdiff.SortTextEdits(d.edits) -} - -// Subtract removes all the common changes of base and d from d. -// Note that this function only works for cases where all the changes of base is included in d. -func (d *Diff) Subtract(base *Diff) error { - baseFiles := base.groupEditsByFile() - - newEdits := make([]gotextdiff.TextEdit, 0, len(d.edits)) - for f, edits := range d.groupEditsByFile() { - if _, ok := baseFiles[f]; !ok { - newEdits = append(newEdits, edits...) - continue - } - - // Because both base and d are sorted, we use a merge sort like algorithm to subtract base from d. - var i, j, traverseOffset int - for i < len(edits) && j < len(baseFiles[f]) { - e := edits[i] - b := baseFiles[f][j] - - if e.Span.End().Offset() < b.Span.Start().Offset()+traverseOffset { - newEdits = append(newEdits, e) - i++ - traverseOffset += calculateOffsetChange(e) - continue - } - - // Ideally, this condition should never be met as we are assuming that all the changes of base is included in d. - if e.Span.Start().Offset() > b.Span.End().Offset()+traverseOffset { - j++ - continue - } - - if spansHaveConflict(e.Span, b.Span, traverseOffset) { - // If there is a conflict, we add the change of d and move to the next change. - newEdits = append(newEdits, e) - - if e.Span.Start().Offset() < b.Span.Start().Offset()+traverseOffset { - i++ - traverseOffset += len(e.NewText) - (b.Span.Start().Offset() - e.Span.Start().Offset()) - } else { - j++ - traverseOffset += len(e.NewText) - (e.Span.Start().Offset() - b.Span.End().Offset()) - } - } - - // Finally the two cases where either e is in the middle of b or b is in the middle of e. - if e.Span.Start().Offset() >= b.Span.Start().Offset()+traverseOffset { - aconv := span.NewContentConverter(e.Span.URI().Filename(), []byte(d.files1[f])) - editParts, err := subtractEdits(e, b, aconv) - if err != nil { - return err - } - newEdits = append(newEdits, editParts...) - traverseOffset += calculateOffsetChange(e) - calculateOffsetChange(b) - } - - i++ - j++ - } - } - - d.edits = newEdits - return nil -} - -func (d *Diff) groupEditsByFile() map[string][]gotextdiff.TextEdit { - d.makeSureEditsAreSorted() - - fileEdits := make(map[string][]gotextdiff.TextEdit) - for _, e := range d.edits { - path, err := filepath.Rel(d.dir1, e.Span.URI().Filename()) - if err != nil { - panic(err) - } - fileEdits[path] = append(fileEdits[path], e) - } - return fileEdits -} - -func calculateOffsetChange(e gotextdiff.TextEdit) int { - return len(e.NewText) - (e.Span.End().Offset() - e.Span.Start().Offset()) -} - -func areEditsEqual(a, b gotextdiff.TextEdit, offset int) bool { - if a.Span.Start().Offset() != b.Span.Start().Offset()+offset { - return false - } - if a.Span.End().Offset() != b.Span.End().Offset()+offset { - return false - } - if a.NewText != b.NewText { - return false - } - return true -} - -func spansHaveConflict(a, b span.Span, offset int) bool { - if isPointInSpan(a.Start(), b) && !isPointInSpan(a.End(), b) { - return true - } - if isPointInSpan(a.End(), b) && !isPointInSpan(a.Start(), b) { - return true - } - return false -} - -func isPointInSpan(p span.Point, s span.Span) bool { - return p.Offset() >= s.Start().Offset() && p.Offset() <= s.End().Offset() -} - -func subtractEdits(a, b gotextdiff.TextEdit, aconv span.Converter) ([]gotextdiff.TextEdit, error) { - edits := myers.ComputeEdits(a.Span.URI(), b.NewText, a.NewText) - bconv := span.NewContentConverter(b.Span.URI().Filename(), []byte(b.NewText)) - for i, e := range edits { - s, err := e.Span.WithOffset(bconv) - if err != nil { - return nil, err - } - edits[i].Span = moveSpan(s, a.Span.End().Offset()) - } - - err := ensureEditsHavePositionAndOffset(edits, aconv) - if err != nil { - return nil, errors.Wrap(err, "failed to ensure edits have position and offset") - } - - return edits, nil -} - -func moveSpan(s span.Span, offset int) span.Span { - return span.New(s.URI(), span.NewPoint(0, 0, s.Start().Offset()+offset), span.NewPoint(0, 0, s.End().Offset()+offset)) -} - -func (d *Diff) ToUnified() []gotextdiff.Unified { - unified := make([]gotextdiff.Unified, 0, len(d.edits)) - fileEdits := d.groupEditsByFile() - for path, edits := range fileEdits { - from, err := filepath.Rel(d.lcp, filepath.Join(d.dir1, path)) - if err != nil { - panic(err) - } - to, err := filepath.Rel(d.lcp, filepath.Join(d.dir2, path)) - if err != nil { - panic(err) - } - unified = append(unified, gotextdiff.ToUnified(from, to, d.files1[path], edits)) - } - return unified -} diff --git a/ignite/internal/tools/gen-mig-diffs/diff/exceptions.go b/ignite/internal/tools/gen-mig-diffs/diff/exceptions.go deleted file mode 100644 index 59707fd89d..0000000000 --- a/ignite/internal/tools/gen-mig-diffs/diff/exceptions.go +++ /dev/null @@ -1,39 +0,0 @@ -package diff - -import ( - "path/filepath" - - "github.com/gobwas/glob" -) - -// List of files that should be ignored when calculating diff of two directories -var exceptionFiles = []glob.Glob{ - mustCompilePathGlob("**/.git/**"), - mustCompilePathGlob("**.md"), - mustCompilePathGlob("**/go.sum"), - mustCompilePathGlob("**_test.go"), - mustCompilePathGlob("**.pb.go"), - mustCompilePathGlob("**.pb.gw.go"), - mustCompilePathGlob("**.pulsar.go"), - mustCompilePathGlob("**/node_modules/**"), - mustCompilePathGlob("**/openapi.yml"), - mustCompilePathGlob("**/.gitignore"), - mustCompilePathGlob("**.html"), - mustCompilePathGlob("**.css"), - mustCompilePathGlob("**.js"), - mustCompilePathGlob("**.ts"), -} - -func mustCompilePathGlob(pattern string) glob.Glob { - return glob.MustCompile(pattern, filepath.Separator) -} - -// Checks if the given path matches any of the exception file patterns -func isException(path string) bool { - for _, glob := range exceptionFiles { - if glob.Match(path) { - return true - } - } - return false -} diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/migdiff.go b/ignite/internal/tools/gen-mig-diffs/migdiff/migdiff.go new file mode 100644 index 0000000000..d41c3cae3b --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/migdiff.go @@ -0,0 +1,341 @@ +package migdiff + +import ( + "context" + "fmt" + "log" + "os" + "path/filepath" + "sort" + + "github.com/Masterminds/semver/v3" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "github.com/hexops/gotextdiff" + "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/exec" + "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/step" + "github.com/ignite/cli/v28/ignite/pkg/diff" + "github.com/ignite/cli/v28/ignite/pkg/errors" +) + +const ( + igniteCliRepository = "http://github.com/ignite/cli.git" + igniteRepoPath = "src/github.com/ignite/cli" + igniteBinaryPath = "dist/ignite" +) + +var diffIgnoreGlobs = []string{ + "**/.git/**", + "**.md", + "**/go.sum", + "**_test.go", + "**.pb.go", + "**.pb.gw.go", + "**.pulsar.go", + "**/node_modules/**", + "**/openapi.yml", + "**/.gitignore", + "**.html", + "**.css", + "**.js", + "**.ts", +} + +type MigDiffGenerator struct { + from, to *semver.Version + tempDir, repoDir string + repo *git.Repository + logger *log.Logger +} + +func NewMigDiffGenerator(from, to *semver.Version) (*MigDiffGenerator, error) { + logger := log.New(os.Stdout, "", log.LstdFlags) + + tempDir, err := createTempDir() + if err != nil { + return nil, errors.Wrap(err, "failed to create temporary directory") + } + logger.Println("Created temporary directory:", tempDir) + + logger.Println("Cloning ignite repository...") + repoDir := filepath.Join(tempDir, igniteRepoPath) + repo, err := cloneIgniteRepo(repoDir) + if err != nil { + return nil, errors.Wrap(err, "failed to clone ignite repository") + } + + versions, err := getRepoVersionTags(repoDir) + if err != nil { + return nil, err + } + + from, to, err = validateVersionRange(from, to, versions) + if err != nil { + return nil, err + } + + return &MigDiffGenerator{ + from: from, + to: to, + tempDir: tempDir, + repoDir: repoDir, + repo: repo, + logger: logger, + }, nil +} + +func createTempDir() (string, error) { + tmpdir, err := os.MkdirTemp("", ".migdoc") + defer os.RemoveAll(tmpdir) + if err != nil { + return "", err + } + + return tmpdir, nil +} + +func cloneIgniteRepo(path string) (*git.Repository, error) { + repo, err := git.PlainClone(path, false, &git.CloneOptions{ + URL: igniteCliRepository, + }) + return repo, err +} + +// getRepoVersionTags returns a sorted collection of semver tags from the ignite cli repository +func getRepoVersionTags(repoDir string) (semver.Collection, error) { + repo, err := git.PlainOpen(repoDir) + if err != nil { + return nil, err + } + + tags, err := repo.Tags() + if err != nil { + return nil, errors.Wrap(err, "failed to get tags") + } + + // Iterate over all tags in the repository and pick valid semver tags + var versions semver.Collection + err = tags.ForEach(func(ref *plumbing.Reference) error { + name := ref.Name() + if name.IsTag() { + ver, err := semver.NewVersion(name.Short()) + if err != nil { + // Do nothing as it's not a semver tag + return nil + } + versions = append(versions, ver) + } + return nil + }) + if err != nil { + return nil, errors.Wrap(err, "failed to iterate over tags") + } + + sort.Sort(versions) + + return versions, nil +} + +// validateVersionRange checks if the provided fromVer and toVer exist in the versions and if any of them is nil, then it picks default values. +func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collection) (*semver.Version, *semver.Version, error) { + // Unable to generate migration document if there are less than two releases! + if versions.Len() < 2 { + return nil, nil, errors.New("At least two semver tags are required") + } + + // Replace fromVer and toVer with equivalent semver tags from versions + if fromVer != nil { + found := false + for _, ver := range versions { + if ver.Equal(fromVer) { + fromVer = ver + found = true + break + } + } + if !found { + return nil, nil, errors.Errorf("tag %s not found", fromVer) + } + } + if toVer != nil { + found := false + for _, ver := range versions { + if ver.Equal(toVer) { + toVer = ver + found = true + break + } + } + if !found { + return nil, nil, errors.Errorf("tag %s not found", toVer) + } + } + + // Picking default values for fromVer and toVer such that: + // If both fromVer and toVer are not provided, then generate migration document for second last and last semver tags + // If only fromVer is not provided, then use the tag before toVer as fromVer + // If only toVer is not provided, then use the last tag as toVer + if fromVer == nil { + if toVer != nil { + sort.Search(versions.Len(), func(i int) bool { + if versions[i].LessThan(toVer) { + fromVer = versions[i] + return false + } + return true + }) + } else { + fromVer = versions[versions.Len()-2] + } + } + if toVer == nil { + toVer = versions[versions.Len()-1] + } + + // Unable to generate migration document if fromVer is greater or equal to toVer + if fromVer.GreaterThan(toVer) || fromVer.Equal(toVer) { + return nil, nil, errors.Errorf("from version %s should be less than to version %s", fromVer, toVer) + } + + return fromVer, toVer, nil +} + +func (mdg *MigDiffGenerator) Cleanup() error { + mdg.logger.Println("Cleaning up temporary directory:", mdg.tempDir) + return os.RemoveAll(mdg.tempDir) +} + +func (mdg *MigDiffGenerator) Generate(outputPath string) error { + mdg.logger.Printf("Generating migration diffs for %s->%s\n", mdg.from, mdg.to) + + fromDir := filepath.Join(mdg.tempDir, mdg.from.Original()) + err := mdg.runScaffoldsForVersion(mdg.from, fromDir) + if err != nil { + return errors.Wrapf(err, "failed to run scaffolds for version %s", mdg.from) + } + toDir := filepath.Join(mdg.tempDir, mdg.to.Original()) + err = mdg.runScaffoldsForVersion(mdg.to, toDir) + if err != nil { + return errors.Wrapf(err, "failed to run scaffolds for version %s", mdg.to) + } + + mdg.logger.Println("Calculating diff...") + diffs, err := calculateDiffs(fromDir, toDir) + if err != nil { + return errors.Wrap(err, "failed to calculate diff") + } + + err = saveDiffs(diffs, outputPath) + if err != nil { + return errors.Wrap(err, "failed to save diff map") + } + log.Println("Migration diffs generated successfully at", outputPath) + + return nil +} + +// Run scaffolds commands one by one with the given version of ignite cli and save the output in the output directory +func (mdg *MigDiffGenerator) runScaffoldsForVersion(ver *semver.Version, outputDir string) error { + err := mdg.checkoutToTag(ver.Original()) + if err != nil { + return err + } + + err = mdg.buildIgniteCli() + if err != nil { + return err + } + + binPath := filepath.Join(mdg.repoDir, igniteBinaryPath) + scaffolder := NewScaffolder(binPath, defaultScaffoldCommands) + err = scaffolder.Run(ver, outputDir) + if err != nil { + return err + } + + return nil +} + +func (mdg *MigDiffGenerator) checkoutToTag(tag string) error { + wt, err := mdg.repo.Worktree() + if err != nil { + return err + } + + err = wt.Checkout(&git.CheckoutOptions{ + Branch: plumbing.NewTagReferenceName(tag), + }) + if err != nil { + return errors.Wrapf(err, "failed to checkout tag %s", tag) + } + + return nil +} + +func (mdg *MigDiffGenerator) buildIgniteCli() error { + err := exec.Exec(context.Background(), []string{"make", "build"}, exec.StepOption(step.Workdir(mdg.repoDir))) + if err != nil { + return errors.Wrap(err, "failed to build ignite cli using make build") + } + + return nil +} + +func calculateDiffs(fromDir, toDir string) (map[string][]gotextdiff.Unified, error) { + diffs := make(map[string][]gotextdiff.Unified) + for _, s := range defaultScaffoldCommands { + diff, err := diff.ComputeFS( + os.DirFS(filepath.Join(fromDir, s.Name)), + os.DirFS(filepath.Join(toDir, s.Name)), + diffIgnoreGlobs..., + ) + if err != nil { + return nil, err + } + diffs[s.Name] = diff + } + + subtractBaseDiffs(diffs) + + return diffs, nil +} + +// subtractBaseDiffs removes chain and module diffs from other diffs +func subtractBaseDiffs(diffs map[string][]gotextdiff.Unified) { + chainDiff := diffs["chain"] + moduleDiff := diffs["module"] + for name, d := range diffs { + if name != "chain" && name != "module" { + diffs[name] = subtractUnifieds(d, moduleDiff) + } + } + + diffs["module"] = subtractUnifieds(moduleDiff, chainDiff) +} + +func subtractUnifieds(a, b []gotextdiff.Unified) []gotextdiff.Unified { + for i, ad := range a { + for _, bd := range b { + if ad.From == bd.From && ad.To == bd.To { + a[i] = diff.Subtract(ad, bd) + } + } + } + return a +} + +func saveDiffs(diffs map[string][]gotextdiff.Unified, outputPath string) error { + for name, diffs := range diffs { + outf, err := os.Create(filepath.Join(outputPath, name+".diff")) + if err != nil { + return err + } + defer outf.Close() + for _, diff := range diffs { + outf.WriteString(fmt.Sprint(diff)) + outf.WriteString("\n") + } + } + + return nil +} diff --git a/ignite/internal/tools/gen-mig-diffs/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go similarity index 97% rename from ignite/internal/tools/gen-mig-diffs/scaffold/scaffold.go rename to ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go index 3077450360..e3191eb84c 100644 --- a/ignite/internal/tools/gen-mig-diffs/scaffold/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go @@ -1,4 +1,4 @@ -package scaffold +package migdiff import ( "context" @@ -12,7 +12,7 @@ import ( "github.com/ignite/cli/v28/ignite/pkg/errors" ) -var DefaultScaffoldCommands = []ScaffoldCommand{ +var defaultScaffoldCommands = []ScaffoldCommand{ { Name: "chain", Commands: []string{ @@ -100,7 +100,7 @@ func NewScaffolder(ignitePath string, commands []ScaffoldCommand) *Scaffolder { } } -func (s *Scaffolder) RunScaffolds(ver *semver.Version, out string) error { +func (s *Scaffolder) Run(ver *semver.Version, out string) error { for _, command := range s.commands { if err := s.runCommand(command, ver, out); err != nil { return err From 23f7aad88677b472c31f613253af613d5b252ea4 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Thu, 8 Feb 2024 16:25:59 +0330 Subject: [PATCH 14/69] Fix bugs --- .../internal/tools/gen-mig-diffs/cmd/root.go | 12 +-- .../migdiff/{migdiff.go => gen.go} | 81 ++++++++++++------- .../tools/gen-mig-diffs/migdiff/scaffold.go | 46 +++++++++-- 3 files changed, 94 insertions(+), 45 deletions(-) rename ignite/internal/tools/gen-mig-diffs/migdiff/{migdiff.go => gen.go} (79%) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 715aaadeb5..7cc18c5c47 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -10,11 +10,8 @@ import ( const ( fromFlag = "from" toFlag = "to" + sourceFlag = "source" outputFlag = "output" - - igniteCliRepository = "http://github.com/ignite/cli.git" - igniteRepoPath = "src/github.com/ignite/cli" - igniteBinaryPath = "dist/ignite" ) // NewRootCmd creates a new root command @@ -26,6 +23,7 @@ func NewRootCmd() *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { from, _ := cmd.Flags().GetString(fromFlag) to, _ := cmd.Flags().GetString(toFlag) + source := cmd.Flag(sourceFlag).Value.String() output, _ := cmd.Flags().GetString(outputFlag) fromVer, err := semver.NewVersion(from) @@ -37,10 +35,11 @@ func NewRootCmd() *cobra.Command { return errors.Wrapf(err, "failed to parse to version %s", to) } - mdg, err := migdiff.NewMigDiffGenerator(fromVer, toVer) + mdg, err := migdiff.NewGenerator(fromVer, toVer, source) if err != nil { return err } + defer mdg.Cleanup() return mdg.Generate(output) }, @@ -48,7 +47,8 @@ func NewRootCmd() *cobra.Command { cmd.Flags().StringP(fromFlag, "f", "", "Version of ignite or path to ignite source code to generate the diff from") cmd.Flags().StringP(toFlag, "t", "", "Version of ignite or path to ignite source code to generate the diff to") - cmd.Flags().StringP(outputFlag, "o", ".", "Output directory to save the migration diff files") + cmd.Flags().StringP(sourceFlag, "s", "", "Path to ignite source code repository (optional)") + cmd.Flags().StringP(outputFlag, "o", "./diffs", "Output directory to save the migration diff files") return cmd } diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/migdiff.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go similarity index 79% rename from ignite/internal/tools/gen-mig-diffs/migdiff/migdiff.go rename to ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index d41c3cae3b..cde7d23253 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/migdiff.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -25,7 +25,7 @@ const ( ) var diffIgnoreGlobs = []string{ - "**/.git/**", + ".git/**", "**.md", "**/go.sum", "**_test.go", @@ -41,14 +41,17 @@ var diffIgnoreGlobs = []string{ "**.ts", } -type MigDiffGenerator struct { +// Generator is used to generate migration diffs +type Generator struct { from, to *semver.Version tempDir, repoDir string repo *git.Repository logger *log.Logger } -func NewMigDiffGenerator(from, to *semver.Version) (*MigDiffGenerator, error) { +// NewGenerator creates a new generator for migration diffs between from and to versions of ignite cli +// If source is empty, then it clones the ignite cli repository to a temporary directory and uses it as the source. +func NewGenerator(from, to *semver.Version, source string) (*Generator, error) { logger := log.New(os.Stdout, "", log.LstdFlags) tempDir, err := createTempDir() @@ -57,11 +60,22 @@ func NewMigDiffGenerator(from, to *semver.Version) (*MigDiffGenerator, error) { } logger.Println("Created temporary directory:", tempDir) - logger.Println("Cloning ignite repository...") - repoDir := filepath.Join(tempDir, igniteRepoPath) - repo, err := cloneIgniteRepo(repoDir) - if err != nil { - return nil, errors.Wrap(err, "failed to clone ignite repository") + var ( + repoDir = source + repo *git.Repository + ) + if source == "" { + logger.Println("Cloning ignite repository...") + repoDir = filepath.Join(tempDir, igniteRepoPath) + repo, err = cloneIgniteRepo(repoDir) + if err != nil { + return nil, errors.Wrap(err, "failed to clone ignite repository") + } + } else { + repo, err = git.PlainOpen(source) + if err != nil { + return nil, errors.Wrap(err, "failed to open ignite repository") + } } versions, err := getRepoVersionTags(repoDir) @@ -74,7 +88,7 @@ func NewMigDiffGenerator(from, to *semver.Version) (*MigDiffGenerator, error) { return nil, err } - return &MigDiffGenerator{ + return &Generator{ from: from, to: to, tempDir: tempDir, @@ -200,26 +214,26 @@ func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collec return fromVer, toVer, nil } -func (mdg *MigDiffGenerator) Cleanup() error { - mdg.logger.Println("Cleaning up temporary directory:", mdg.tempDir) - return os.RemoveAll(mdg.tempDir) +func (g *Generator) Cleanup() error { + g.logger.Println("Cleaning up temporary directory:", g.tempDir) + return os.RemoveAll(g.tempDir) } -func (mdg *MigDiffGenerator) Generate(outputPath string) error { - mdg.logger.Printf("Generating migration diffs for %s->%s\n", mdg.from, mdg.to) +func (g *Generator) Generate(outputPath string) error { + g.logger.Printf("Generating migration diffs for %s->%s\n", g.from, g.to) - fromDir := filepath.Join(mdg.tempDir, mdg.from.Original()) - err := mdg.runScaffoldsForVersion(mdg.from, fromDir) + fromDir := filepath.Join(g.tempDir, g.from.Original()) + err := g.runScaffoldsForVersion(g.from, fromDir) if err != nil { - return errors.Wrapf(err, "failed to run scaffolds for version %s", mdg.from) + return errors.Wrapf(err, "failed to run scaffolds for version %s", g.from) } - toDir := filepath.Join(mdg.tempDir, mdg.to.Original()) - err = mdg.runScaffoldsForVersion(mdg.to, toDir) + toDir := filepath.Join(g.tempDir, g.to.Original()) + err = g.runScaffoldsForVersion(g.to, toDir) if err != nil { - return errors.Wrapf(err, "failed to run scaffolds for version %s", mdg.to) + return errors.Wrapf(err, "failed to run scaffolds for version %s", g.to) } - mdg.logger.Println("Calculating diff...") + g.logger.Println("Calculating diff...") diffs, err := calculateDiffs(fromDir, toDir) if err != nil { return errors.Wrap(err, "failed to calculate diff") @@ -235,18 +249,18 @@ func (mdg *MigDiffGenerator) Generate(outputPath string) error { } // Run scaffolds commands one by one with the given version of ignite cli and save the output in the output directory -func (mdg *MigDiffGenerator) runScaffoldsForVersion(ver *semver.Version, outputDir string) error { - err := mdg.checkoutToTag(ver.Original()) +func (g *Generator) runScaffoldsForVersion(ver *semver.Version, outputDir string) error { + err := g.checkoutToTag(ver.Original()) if err != nil { return err } - err = mdg.buildIgniteCli() + err = g.buildIgniteCli() if err != nil { return err } - binPath := filepath.Join(mdg.repoDir, igniteBinaryPath) + binPath := filepath.Join(g.repoDir, igniteBinaryPath) scaffolder := NewScaffolder(binPath, defaultScaffoldCommands) err = scaffolder.Run(ver, outputDir) if err != nil { @@ -256,8 +270,8 @@ func (mdg *MigDiffGenerator) runScaffoldsForVersion(ver *semver.Version, outputD return nil } -func (mdg *MigDiffGenerator) checkoutToTag(tag string) error { - wt, err := mdg.repo.Worktree() +func (g *Generator) checkoutToTag(tag string) error { + wt, err := g.repo.Worktree() if err != nil { return err } @@ -272,8 +286,8 @@ func (mdg *MigDiffGenerator) checkoutToTag(tag string) error { return nil } -func (mdg *MigDiffGenerator) buildIgniteCli() error { - err := exec.Exec(context.Background(), []string{"make", "build"}, exec.StepOption(step.Workdir(mdg.repoDir))) +func (g *Generator) buildIgniteCli() error { + err := exec.Exec(context.Background(), []string{"make", "build"}, exec.StepOption(step.Workdir(g.repoDir))) if err != nil { return errors.Wrap(err, "failed to build ignite cli using make build") } @@ -325,14 +339,19 @@ func subtractUnifieds(a, b []gotextdiff.Unified) []gotextdiff.Unified { } func saveDiffs(diffs map[string][]gotextdiff.Unified, outputPath string) error { + err := os.MkdirAll(outputPath, os.ModePerm) + if err != nil { + return err + } + for name, diffs := range diffs { outf, err := os.Create(filepath.Join(outputPath, name+".diff")) if err != nil { return err } defer outf.Close() - for _, diff := range diffs { - outf.WriteString(fmt.Sprint(diff)) + for _, d := range diffs { + outf.WriteString(fmt.Sprint(d)) outf.WriteString("\n") } } diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go b/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go index e3191eb84c..a57a364b75 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go @@ -101,33 +101,63 @@ func NewScaffolder(ignitePath string, commands []ScaffoldCommand) *Scaffolder { } func (s *Scaffolder) Run(ver *semver.Version, out string) error { - for _, command := range s.commands { - if err := s.runCommand(command, ver, out); err != nil { + for _, c := range s.commands { + if err := s.runCommand(c.Name, c.Prerequisites, c.Commands, ver, out); err != nil { return err } } return nil } -func (s *Scaffolder) runCommand(command ScaffoldCommand, ver *semver.Version, out string) error { - for _, pr := range command.Prerequisites { - c, err := s.findCommand(pr) +func (s *Scaffolder) runCommand( + name string, + prerequisites []string, + cmds []string, + ver *semver.Version, + out string, +) error { + for _, p := range prerequisites { + c, err := s.findCommand(p) if err != nil { return err } - if err := s.runCommand(c, ver, out); err != nil { + + err = s.runCommand(name, c.Prerequisites, c.Commands, ver, out) + if err != nil { return err } } - for _, cmd := range command.Commands { - if err := s.executeScaffold(command.Name, cmd, ver, out); err != nil { + for _, cmd := range cmds { + if err := s.executeScaffold(name, cmd, ver, out); err != nil { return err } } return nil } +func (s *Scaffolder) runPrerequisites(name string, prerequisites []string, ver *semver.Version, out string) error { + for _, p := range prerequisites { + c, err := s.findCommand(p) + if err != nil { + return err + } + + err = s.runPrerequisites(name, c.Prerequisites, ver, out) + if err != nil { + return err + } + + for _, cmd := range c.Commands { + if err := s.executeScaffold(name, cmd, ver, out); err != nil { + return err + } + } + } + + return nil +} + func (s *Scaffolder) findCommand(name string) (ScaffoldCommand, error) { for _, c := range s.commands { if c.Name == name { From 49a86897fa5b36d734f27547af142c9bac2d8b5c Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Thu, 8 Feb 2024 23:34:43 +0330 Subject: [PATCH 15/69] Fix bugs --- .../tools/gen-mig-diffs/migdiff/gen.go | 2 +- .../tools/gen-mig-diffs/migdiff/scaffold.go | 25 ++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index cde7d23253..7988380f56 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -34,7 +34,7 @@ var diffIgnoreGlobs = []string{ "**.pulsar.go", "**/node_modules/**", "**/openapi.yml", - "**/.gitignore", + ".gitignore", "**.html", "**.css", "**.js", diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go b/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go index a57a364b75..f79bb9c39d 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go @@ -105,6 +105,10 @@ func (s *Scaffolder) Run(ver *semver.Version, out string) error { if err := s.runCommand(c.Name, c.Prerequisites, c.Commands, ver, out); err != nil { return err } + + if err := applyPostScaffoldExceptions(ver, c.Name, out); err != nil { + return err + } } return nil } @@ -129,27 +133,28 @@ func (s *Scaffolder) runCommand( } for _, cmd := range cmds { - if err := s.executeScaffold(name, cmd, ver, out); err != nil { + if err := s.executeScaffold(ver, name, cmd, out); err != nil { return err } } + return nil } -func (s *Scaffolder) runPrerequisites(name string, prerequisites []string, ver *semver.Version, out string) error { +func (s *Scaffolder) runPrerequisites(ver *semver.Version, name string, prerequisites []string, out string) error { for _, p := range prerequisites { c, err := s.findCommand(p) if err != nil { return err } - err = s.runPrerequisites(name, c.Prerequisites, ver, out) + err = s.runPrerequisites(ver, name, c.Prerequisites, out) if err != nil { return err } for _, cmd := range c.Commands { - if err := s.executeScaffold(name, cmd, ver, out); err != nil { + if err := s.executeScaffold(ver, name, cmd, out); err != nil { return err } } @@ -168,29 +173,25 @@ func (s *Scaffolder) findCommand(name string) (ScaffoldCommand, error) { return ScaffoldCommand{}, fmt.Errorf("command %s not found", name) } -func (s *Scaffolder) executeScaffold(name, cmd string, ver *semver.Version, out string) error { +func (s *Scaffolder) executeScaffold(ver *semver.Version, name, cmd string, out string) error { args := []string{s.ignitePath, "scaffold"} args = append(args, strings.Fields(cmd)...) args = append(args, "--path", filepath.Join(out, name)) - args = applyPreScaffoldExceptions(ver, args) + args = applyPreExecuteExceptions(ver, args) if err := exec.Exec(context.Background(), args); err != nil { return errors.Wrapf(err, "failed to execute ignite scaffold command: %s", cmd) } - if err := applyPostScaffoldExceptions(ver, name, out); err != nil { - return err - } - return nil } // In this function we can manipulate command arguments before executing it in order to compensate for differences in versions. -func applyPreScaffoldExceptions(ver *semver.Version, args []string) []string { +func applyPreExecuteExceptions(ver *semver.Version, args []string) []string { // In versions <0.27.0, "scaffold chain" command always creates a new directory with the name of chain at the given --path // so we need to append "example" to the path if the command is not "chain" if ver.LessThan(semver.MustParse("v0.27.0")) && args[2] != "chain" { - (args)[len(args)-1] = filepath.Join(args[len(args)-1], "example") + args[len(args)-1] = filepath.Join(args[len(args)-1], "example") } return args From ad123b420b38a49996207e0675ae3469fa28c838 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Fri, 9 Feb 2024 06:13:12 +0330 Subject: [PATCH 16/69] Add more test to subtract test cases --- .../tools/gen-mig-diffs/migdiff/gen.go | 1 + ignite/pkg/diff/subtract.go | 13 +- ignite/pkg/diff/subtract_test.go | 114 ++++++++++++++++++ 3 files changed, 126 insertions(+), 2 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index 7988380f56..8f02cd071b 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -35,6 +35,7 @@ var diffIgnoreGlobs = []string{ "**/node_modules/**", "**/openapi.yml", ".gitignore", + ".github/**", "**.html", "**.css", "**.js", diff --git a/ignite/pkg/diff/subtract.go b/ignite/pkg/diff/subtract.go index 46b1b408a3..69dcddd205 100644 --- a/ignite/pkg/diff/subtract.go +++ b/ignite/pkg/diff/subtract.go @@ -6,7 +6,7 @@ import ( "github.com/hexops/gotextdiff" ) -// Sutract two unified diffs from each other. +// Subtract two unified diffs from each other. func Subtract(a, b gotextdiff.Unified) gotextdiff.Unified { return gotextdiff.Unified{ From: a.From, @@ -21,7 +21,16 @@ func subtractHunks(src, base []*gotextdiff.Hunk) []*gotextdiff.Hunk { res := make([]*gotextdiff.Hunk, 0, len(src)) offset := 0 - for i, j := 0, 0; i < len(src) && j < len(base); { + for i, j := 0, 0; i < len(src) || j < len(base); { + if i >= len(src) { + break + } + if j >= len(base) { + res = append(res, src[i]) + i++ + continue + } + s := src[i] b := base[j] diff --git a/ignite/pkg/diff/subtract_test.go b/ignite/pkg/diff/subtract_test.go index a0b4a37ba5..6b49cc2ee1 100644 --- a/ignite/pkg/diff/subtract_test.go +++ b/ignite/pkg/diff/subtract_test.go @@ -54,6 +54,120 @@ func TestSubtract(t *testing.T) { Hunks: []*gotextdiff.Hunk{}, }, }, + { + name: "Add hunk at the beginning", + args: args{ + a: gotextdiff.Unified{ + Hunks: []*gotextdiff.Hunk{ + { + FromLine: 1, + ToLine: 3, + Lines: []gotextdiff.Line{ + {Kind: gotextdiff.Equal, Content: "equal1"}, + {Kind: gotextdiff.Insert, Content: "insert1"}, + {Kind: gotextdiff.Equal, Content: "equal2"}, + {Kind: gotextdiff.Delete, Content: "delete1"}, + }, + }, + { + FromLine: 4, + ToLine: 6, + Lines: []gotextdiff.Line{ + {Kind: gotextdiff.Equal, Content: "equal3"}, + {Kind: gotextdiff.Insert, Content: "insert2"}, + {Kind: gotextdiff.Equal, Content: "equal4"}, + {Kind: gotextdiff.Delete, Content: "delete2"}, + }, + }, + }, + }, + b: gotextdiff.Unified{ + Hunks: []*gotextdiff.Hunk{ + { + FromLine: 4, + ToLine: 6, + Lines: []gotextdiff.Line{ + {Kind: gotextdiff.Equal, Content: "equal3"}, + {Kind: gotextdiff.Insert, Content: "insert2"}, + {Kind: gotextdiff.Equal, Content: "equal4"}, + {Kind: gotextdiff.Delete, Content: "delete2"}, + }, + }, + }, + }, + }, + want: gotextdiff.Unified{ + Hunks: []*gotextdiff.Hunk{ + { + FromLine: 1, + ToLine: 3, + Lines: []gotextdiff.Line{ + {Kind: gotextdiff.Equal, Content: "equal1"}, + {Kind: gotextdiff.Insert, Content: "insert1"}, + {Kind: gotextdiff.Equal, Content: "equal2"}, + {Kind: gotextdiff.Delete, Content: "delete1"}, + }, + }, + }, + }, + }, + { + name: "Add hunk at the end", + args: args{ + a: gotextdiff.Unified{ + Hunks: []*gotextdiff.Hunk{ + { + FromLine: 1, + ToLine: 3, + Lines: []gotextdiff.Line{ + {Kind: gotextdiff.Equal, Content: "equal1"}, + {Kind: gotextdiff.Insert, Content: "insert1"}, + {Kind: gotextdiff.Equal, Content: "equal2"}, + {Kind: gotextdiff.Delete, Content: "delete1"}, + }, + }, + { + FromLine: 4, + ToLine: 6, + Lines: []gotextdiff.Line{ + {Kind: gotextdiff.Equal, Content: "equal3"}, + {Kind: gotextdiff.Insert, Content: "insert2"}, + {Kind: gotextdiff.Equal, Content: "equal4"}, + {Kind: gotextdiff.Delete, Content: "delete2"}, + }, + }, + }, + }, + b: gotextdiff.Unified{ + Hunks: []*gotextdiff.Hunk{ + { + FromLine: 1, + ToLine: 3, + Lines: []gotextdiff.Line{ + {Kind: gotextdiff.Equal, Content: "equal1"}, + {Kind: gotextdiff.Insert, Content: "insert1"}, + {Kind: gotextdiff.Equal, Content: "equal2"}, + {Kind: gotextdiff.Delete, Content: "delete1"}, + }, + }, + }, + }, + }, + want: gotextdiff.Unified{ + Hunks: []*gotextdiff.Hunk{ + { + FromLine: 4, + ToLine: 6, + Lines: []gotextdiff.Line{ + {Kind: gotextdiff.Equal, Content: "equal3"}, + {Kind: gotextdiff.Insert, Content: "insert2"}, + {Kind: gotextdiff.Equal, Content: "equal4"}, + {Kind: gotextdiff.Delete, Content: "delete2"}, + }, + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From 6bdad4d8f6b6be32d486fd917670435d68e2b40a Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Fri, 9 Feb 2024 15:03:03 +0330 Subject: [PATCH 17/69] Update the subtract lines algorithm --- ignite/pkg/diff/subtract.go | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/ignite/pkg/diff/subtract.go b/ignite/pkg/diff/subtract.go index 69dcddd205..1ac7606989 100644 --- a/ignite/pkg/diff/subtract.go +++ b/ignite/pkg/diff/subtract.go @@ -140,26 +140,17 @@ func subtractHunk(a, b *gotextdiff.Hunk) *gotextdiff.Hunk { func subtractLines(a, b []gotextdiff.Line) []gotextdiff.Line { res := make([]gotextdiff.Line, 0, len(a)) - for i, j := 0, 0; i < len(a) && j < len(b); { - la := a[i] - lb := b[j] - - if la == lb { - if la.Kind == gotextdiff.Equal { - res = append(res, la) + for _, la := range a { + rep := false + for _, lb := range b { + if la.Kind != gotextdiff.Equal && la.Kind == lb.Kind && la.Content == lb.Content { + rep = true + break } - i++ - j++ - continue } - if i < len(a) { + if !rep { res = append(res, la) - i++ - continue - } - if j < len(b) { - j++ } } From 8c3e6613b0a3b7106b3ec170eb976ade36ae65d0 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Fri, 9 Feb 2024 15:06:38 +0330 Subject: [PATCH 18/69] go mod tidy --- go.mod | 4 ++-- go.sum | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 3396b81a8b..f16ab17f29 100644 --- a/go.mod +++ b/go.mod @@ -47,6 +47,7 @@ require ( github.com/gobuffalo/logger v1.0.7 github.com/gobuffalo/packd v1.0.2 github.com/gobuffalo/plush/v4 v4.1.19 + github.com/gobwas/glob v0.2.3 github.com/goccy/go-yaml v1.11.2 github.com/golangci/golangci-lint v1.55.2 github.com/google/go-github/v48 v48.2.0 @@ -70,7 +71,6 @@ require ( github.com/nqd/flat v0.2.0 github.com/otiai10/copy v1.14.0 github.com/pelletier/go-toml v1.9.5 - github.com/pkg/errors v0.9.1 github.com/radovskyb/watcher v1.0.7 github.com/rogpeppe/go-internal v1.11.0 github.com/rs/cors v1.10.1 @@ -240,7 +240,6 @@ require ( github.com/gobuffalo/helpers v0.6.7 // indirect github.com/gobuffalo/tags/v3 v3.1.4 // indirect github.com/gobuffalo/validate/v3 v3.3.3 // indirect - github.com/gobwas/glob v0.2.3 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect @@ -367,6 +366,7 @@ require ( github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pkg/profile v1.7.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/polyfloyd/go-errorlint v1.4.5 // indirect diff --git a/go.sum b/go.sum index c32312642f..f6212f016e 100644 --- a/go.sum +++ b/go.sum @@ -1551,9 +1551,8 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4 h1:QlVATYS7JBoZMVaf+cNjb90WD/beKVHnIxFKT4QaHVI= golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= -golang.org/x/arch v0.1.0 h1:oMxhUYsO9VsR1dcoVUjJjIGhx1LXol3989T/yZ59Xsw= -golang.org/x/arch v0.1.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= From 075e46f7ed3762a9a361a2f48f8e1776311131db Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Fri, 9 Feb 2024 15:10:10 +0330 Subject: [PATCH 19/69] Add changelog --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 5a5e3e8ced..9e2b0a8aec 100644 --- a/changelog.md +++ b/changelog.md @@ -15,6 +15,7 @@ - [#3835](https://github.com/ignite/cli/pull/3835) Add `--minimal` flag to `scaffold chain` to scaffold a chain with the least amount of sdk modules - [#3820](https://github.com/ignite/cli/pull/3820) Add integration tests for IBC chains - [#3956](https://github.com/ignite/cli/pull/3956) Prepare for wasm app +- [#3718](https://github.com/ignite/cli/pull/3718) Add `gen-mig-diffs` tool app to compare scaffold output of two versions of ignite ### Changes From 8106e37293233f88b52a25b3ff165833c66b178a Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Fri, 9 Feb 2024 15:56:17 +0330 Subject: [PATCH 20/69] Fix lint errors --- .../internal/tools/gen-mig-diffs/cmd/root.go | 2 +- ignite/internal/tools/gen-mig-diffs/main.go | 2 +- .../tools/gen-mig-diffs/migdiff/gen.go | 8 +++--- .../tools/gen-mig-diffs/migdiff/scaffold.go | 27 ++----------------- ignite/pkg/diff/compute.go | 21 ++++++++++----- ignite/pkg/diff/subtract.go | 17 +++++------- 6 files changed, 30 insertions(+), 47 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 7cc18c5c47..a482eb80c0 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -14,7 +14,7 @@ const ( outputFlag = "output" ) -// NewRootCmd creates a new root command +// NewRootCmd creates a new root command. func NewRootCmd() *cobra.Command { cmd := &cobra.Command{ Use: "gen-mig-diffs", diff --git a/ignite/internal/tools/gen-mig-diffs/main.go b/ignite/internal/tools/gen-mig-diffs/main.go index ad7dbd25ba..4b549f7df9 100644 --- a/ignite/internal/tools/gen-mig-diffs/main.go +++ b/ignite/internal/tools/gen-mig-diffs/main.go @@ -12,4 +12,4 @@ func main() { fmt.Println(err) os.Exit(1) } -} \ No newline at end of file +} diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index 8f02cd071b..7a6aea9bb6 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -42,7 +42,7 @@ var diffIgnoreGlobs = []string{ "**.ts", } -// Generator is used to generate migration diffs +// Generator is used to generate migration diffs. type Generator struct { from, to *semver.Version tempDir, repoDir string @@ -116,7 +116,7 @@ func cloneIgniteRepo(path string) (*git.Repository, error) { return repo, err } -// getRepoVersionTags returns a sorted collection of semver tags from the ignite cli repository +// getRepoVersionTags returns a sorted collection of semver tags from the ignite cli repository. func getRepoVersionTags(repoDir string) (semver.Collection, error) { repo, err := git.PlainOpen(repoDir) if err != nil { @@ -249,7 +249,7 @@ func (g *Generator) Generate(outputPath string) error { return nil } -// Run scaffolds commands one by one with the given version of ignite cli and save the output in the output directory +// Run scaffolds commands one by one with the given version of ignite cli and save the output in the output directory. func (g *Generator) runScaffoldsForVersion(ver *semver.Version, outputDir string) error { err := g.checkoutToTag(ver.Original()) if err != nil { @@ -315,7 +315,7 @@ func calculateDiffs(fromDir, toDir string) (map[string][]gotextdiff.Unified, err return diffs, nil } -// subtractBaseDiffs removes chain and module diffs from other diffs +// subtractBaseDiffs removes chain and module diffs from other diffs. func subtractBaseDiffs(diffs map[string][]gotextdiff.Unified) { chainDiff := diffs["chain"] moduleDiff := diffs["module"] diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go b/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go index f79bb9c39d..4a0b5b64d5 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go @@ -2,7 +2,6 @@ package migdiff import ( "context" - "fmt" "os" "path/filepath" "strings" @@ -77,7 +76,7 @@ var defaultScaffoldCommands = []ScaffoldCommand{ }, } -// ScaffoldCommand represents a set of commands and prerequisites scaffold commands that are required to run before them +// ScaffoldCommand represents a set of commands and prerequisites scaffold commands that are required to run before them. type ScaffoldCommand struct { // Name is the unique identifier of the command Name string @@ -141,28 +140,6 @@ func (s *Scaffolder) runCommand( return nil } -func (s *Scaffolder) runPrerequisites(ver *semver.Version, name string, prerequisites []string, out string) error { - for _, p := range prerequisites { - c, err := s.findCommand(p) - if err != nil { - return err - } - - err = s.runPrerequisites(ver, name, c.Prerequisites, out) - if err != nil { - return err - } - - for _, cmd := range c.Commands { - if err := s.executeScaffold(ver, name, cmd, out); err != nil { - return err - } - } - } - - return nil -} - func (s *Scaffolder) findCommand(name string) (ScaffoldCommand, error) { for _, c := range s.commands { if c.Name == name { @@ -170,7 +147,7 @@ func (s *Scaffolder) findCommand(name string) (ScaffoldCommand, error) { } } - return ScaffoldCommand{}, fmt.Errorf("command %s not found", name) + return ScaffoldCommand{}, errors.Errorf("command %s not found", name) } func (s *Scaffolder) executeScaffold(ver *semver.Version, name, cmd string, out string) error { diff --git a/ignite/pkg/diff/compute.go b/ignite/pkg/diff/compute.go index 0f31fea6a1..86bf7a717e 100644 --- a/ignite/pkg/diff/compute.go +++ b/ignite/pkg/diff/compute.go @@ -10,6 +10,7 @@ import ( "github.com/hexops/gotextdiff" "github.com/hexops/gotextdiff/myers" "github.com/hexops/gotextdiff/span" + "github.com/ignite/cli/v28/ignite/pkg/errors" ) // ComputeFS computes the unified diffs between the origin and modified filesystems. @@ -23,6 +24,10 @@ func ComputeFS(origin, modified fs.FS, ignoreGlobs ...string) ([]gotextdiff.Unif marked := make(map[string]struct{}) unified := make([]gotextdiff.Unified, 0) err = fs.WalkDir(origin, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return errors.Errorf("failed to walk origin: %w", err) + } + if d.IsDir() { return nil } @@ -34,13 +39,13 @@ func ComputeFS(origin, modified fs.FS, ignoreGlobs ...string) ([]gotextdiff.Unif marked[path] = struct{}{} data, err := fs.ReadFile(origin, path) if err != nil { - return fmt.Errorf("failed to read file %q from origin: %w", path, err) + return errors.Errorf("failed to read file %q from origin: %w", path, err) } originFile := string(data) data, err = fs.ReadFile(modified, path) if !os.IsNotExist(err) && err != nil { - return fmt.Errorf("failed to read file %q from modified: %w", path, err) + return errors.Errorf("failed to read file %q from modified: %w", path, err) } modifiedFile := string(data) @@ -55,22 +60,26 @@ func ComputeFS(origin, modified fs.FS, ignoreGlobs ...string) ([]gotextdiff.Unif } err = fs.WalkDir(modified, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return errors.Errorf("failed to walk modified: %w", err) + } + if d.IsDir() { return nil } - if matchGlobs(compiledGlobs, path) { + if _, ok := marked[path]; ok { return nil } - if _, ok := marked[path]; ok { + if matchGlobs(compiledGlobs, path) { return nil } originFile := "" data, err := fs.ReadFile(modified, path) if err != nil { - return fmt.Errorf("failed to read file %q from modified: %w", path, err) + return errors.Errorf("failed to read file %q from modified: %w", path, err) } modifiedFile := string(data) @@ -92,7 +101,7 @@ func compileGlobs(globs []string) ([]glob.Glob, error) { for _, g := range globs { compiledGlob, err := glob.Compile(g, filepath.Separator) if err != nil { - return nil, fmt.Errorf("failed to compile glob %q: %w", g, err) + return nil, errors.Errorf("failed to compile glob %q: %w", g, err) } compiledGlobs = append(compiledGlobs, compiledGlob) } diff --git a/ignite/pkg/diff/subtract.go b/ignite/pkg/diff/subtract.go index 1ac7606989..8c1f6c7182 100644 --- a/ignite/pkg/diff/subtract.go +++ b/ignite/pkg/diff/subtract.go @@ -79,10 +79,9 @@ func beforeHunk(a, b *gotextdiff.Hunk, offset int) bool { func calculateStartEqualLines(h *gotextdiff.Hunk) int { lines := 0 for _, l := range h.Lines { - switch l.Kind { - case gotextdiff.Equal: + if l.Kind == gotextdiff.Equal { lines++ - default: + } else { break } } @@ -92,10 +91,9 @@ func calculateStartEqualLines(h *gotextdiff.Hunk) int { func calculateEndEqualLines(h *gotextdiff.Hunk) int { lines := 0 for i := len(h.Lines) - 1; i >= 0; i-- { - switch h.Lines[i].Kind { - case gotextdiff.Equal: + if h.Lines[i].Kind == gotextdiff.Equal { lines++ - default: + } else { break } } @@ -105,11 +103,10 @@ func calculateEndEqualLines(h *gotextdiff.Hunk) int { func calculateHunkOffsetChange(lines []gotextdiff.Line) int { offset := 0 for _, l := range lines { - switch l.Kind { - case gotextdiff.Delete: - offset-- - case gotextdiff.Insert: + if l.Kind == gotextdiff.Insert { offset++ + } else if l.Kind == gotextdiff.Delete { + offset-- } } return offset From f4368f47f503cb15d89ee942a7d3e758b93878a4 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Fri, 9 Feb 2024 16:58:46 +0330 Subject: [PATCH 21/69] Fix bugs --- .../tools/gen-mig-diffs/migdiff/gen.go | 3 +- ignite/pkg/diff/subtract.go | 11 +++-- ignite/pkg/diff/subtract_test.go | 48 +++++++++---------- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index 7a6aea9bb6..7c4bec9d63 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -27,7 +27,7 @@ const ( var diffIgnoreGlobs = []string{ ".git/**", "**.md", - "**/go.sum", + "go.sum", "**_test.go", "**.pb.go", "**.pb.gw.go", @@ -40,6 +40,7 @@ var diffIgnoreGlobs = []string{ "**.css", "**.js", "**.ts", + "**.json", } // Generator is used to generate migration diffs. diff --git a/ignite/pkg/diff/subtract.go b/ignite/pkg/diff/subtract.go index 8c1f6c7182..37bb1d503d 100644 --- a/ignite/pkg/diff/subtract.go +++ b/ignite/pkg/diff/subtract.go @@ -73,7 +73,7 @@ func sortHunks(hunks []*gotextdiff.Hunk) { // beforeHunk returns true if a comes before b. func beforeHunk(a, b *gotextdiff.Hunk, offset int) bool { - return a.ToLine-calculateEndEqualLines(a) < b.FromLine-calculateStartEqualLines(b)+offset + return a.ToLine-calculateEndEqualLines(a) < b.FromLine+calculateStartEqualLines(b)+offset } func calculateStartEqualLines(h *gotextdiff.Hunk) int { @@ -103,10 +103,11 @@ func calculateEndEqualLines(h *gotextdiff.Hunk) int { func calculateHunkOffsetChange(lines []gotextdiff.Line) int { offset := 0 for _, l := range lines { - if l.Kind == gotextdiff.Insert { - offset++ - } else if l.Kind == gotextdiff.Delete { + switch l.Kind { + case gotextdiff.Delete: offset-- + case gotextdiff.Insert: + offset++ } } return offset @@ -123,7 +124,7 @@ func hunksOverlap(a, b *gotextdiff.Hunk, offset int) bool { } func isLineInHunk(line int, h *gotextdiff.Hunk, offset int) bool { - return line-calculateStartEqualLines(h) >= h.FromLine+offset && line+calculateEndEqualLines(h) <= h.ToLine+offset + return line-calculateStartEqualLines(h) > h.FromLine+offset && line+calculateEndEqualLines(h) < h.ToLine+offset } func subtractHunk(a, b *gotextdiff.Hunk) *gotextdiff.Hunk { diff --git a/ignite/pkg/diff/subtract_test.go b/ignite/pkg/diff/subtract_test.go index 6b49cc2ee1..a795260c2e 100644 --- a/ignite/pkg/diff/subtract_test.go +++ b/ignite/pkg/diff/subtract_test.go @@ -27,10 +27,10 @@ func TestSubtract(t *testing.T) { FromLine: 1, ToLine: 3, Lines: []gotextdiff.Line{ - {Kind: gotextdiff.Equal, Content: "equal1"}, - {Kind: gotextdiff.Insert, Content: "insert1"}, - {Kind: gotextdiff.Equal, Content: "equal2"}, - {Kind: gotextdiff.Delete, Content: "delete1"}, + {Kind: gotextdiff.Equal, Content: "equal1\n"}, + {Kind: gotextdiff.Insert, Content: "insert1\n"}, + {Kind: gotextdiff.Equal, Content: "equal2\n"}, + {Kind: gotextdiff.Delete, Content: "delete1\n"}, }, }, }, @@ -41,10 +41,10 @@ func TestSubtract(t *testing.T) { FromLine: 1, ToLine: 3, Lines: []gotextdiff.Line{ - {Kind: gotextdiff.Equal, Content: "equal1"}, - {Kind: gotextdiff.Insert, Content: "insert1"}, - {Kind: gotextdiff.Equal, Content: "equal2"}, - {Kind: gotextdiff.Delete, Content: "delete1"}, + {Kind: gotextdiff.Equal, Content: "equal1\n"}, + {Kind: gotextdiff.Insert, Content: "insert1\n"}, + {Kind: gotextdiff.Equal, Content: "equal2\n"}, + {Kind: gotextdiff.Delete, Content: "delete1\n"}, }, }, }, @@ -63,20 +63,20 @@ func TestSubtract(t *testing.T) { FromLine: 1, ToLine: 3, Lines: []gotextdiff.Line{ - {Kind: gotextdiff.Equal, Content: "equal1"}, - {Kind: gotextdiff.Insert, Content: "insert1"}, - {Kind: gotextdiff.Equal, Content: "equal2"}, - {Kind: gotextdiff.Delete, Content: "delete1"}, + {Kind: gotextdiff.Equal, Content: "equal1\n"}, + {Kind: gotextdiff.Insert, Content: "insert1\n"}, + {Kind: gotextdiff.Equal, Content: "equal2\n"}, + {Kind: gotextdiff.Delete, Content: "delete1\n"}, }, }, { FromLine: 4, ToLine: 6, Lines: []gotextdiff.Line{ - {Kind: gotextdiff.Equal, Content: "equal3"}, - {Kind: gotextdiff.Insert, Content: "insert2"}, - {Kind: gotextdiff.Equal, Content: "equal4"}, - {Kind: gotextdiff.Delete, Content: "delete2"}, + {Kind: gotextdiff.Equal, Content: "equal3\n"}, + {Kind: gotextdiff.Insert, Content: "insert2\n"}, + {Kind: gotextdiff.Equal, Content: "equal4\n"}, + {Kind: gotextdiff.Delete, Content: "delete2\n"}, }, }, }, @@ -87,10 +87,10 @@ func TestSubtract(t *testing.T) { FromLine: 4, ToLine: 6, Lines: []gotextdiff.Line{ - {Kind: gotextdiff.Equal, Content: "equal3"}, - {Kind: gotextdiff.Insert, Content: "insert2"}, - {Kind: gotextdiff.Equal, Content: "equal4"}, - {Kind: gotextdiff.Delete, Content: "delete2"}, + {Kind: gotextdiff.Equal, Content: "equal3\n"}, + {Kind: gotextdiff.Insert, Content: "insert2\n"}, + {Kind: gotextdiff.Equal, Content: "equal4\n"}, + {Kind: gotextdiff.Delete, Content: "delete2\n"}, }, }, }, @@ -102,10 +102,10 @@ func TestSubtract(t *testing.T) { FromLine: 1, ToLine: 3, Lines: []gotextdiff.Line{ - {Kind: gotextdiff.Equal, Content: "equal1"}, - {Kind: gotextdiff.Insert, Content: "insert1"}, - {Kind: gotextdiff.Equal, Content: "equal2"}, - {Kind: gotextdiff.Delete, Content: "delete1"}, + {Kind: gotextdiff.Equal, Content: "equal1\n"}, + {Kind: gotextdiff.Insert, Content: "insert1\n"}, + {Kind: gotextdiff.Equal, Content: "equal2\n"}, + {Kind: gotextdiff.Delete, Content: "delete1\n"}, }, }, }, From 79258750430bf69a612b1e6416a237f4856491ec Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Fri, 9 Feb 2024 17:05:27 +0330 Subject: [PATCH 22/69] Fix lint --- ignite/pkg/diff/subtract.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ignite/pkg/diff/subtract.go b/ignite/pkg/diff/subtract.go index 37bb1d503d..23da396b15 100644 --- a/ignite/pkg/diff/subtract.go +++ b/ignite/pkg/diff/subtract.go @@ -103,11 +103,10 @@ func calculateEndEqualLines(h *gotextdiff.Hunk) int { func calculateHunkOffsetChange(lines []gotextdiff.Line) int { offset := 0 for _, l := range lines { - switch l.Kind { - case gotextdiff.Delete: - offset-- - case gotextdiff.Insert: + if l.Kind == gotextdiff.Insert { offset++ + } else if l.Kind == gotextdiff.Delete { + offset-- } } return offset From e8e96c375478a0a6a55790c2128175459e5a7cd4 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Wed, 14 Feb 2024 16:31:03 +0330 Subject: [PATCH 23/69] make format --- ignite/internal/tools/gen-mig-diffs/cmd/root.go | 3 ++- ignite/internal/tools/gen-mig-diffs/migdiff/gen.go | 1 + ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go | 1 + ignite/pkg/diff/compute.go | 1 + ignite/pkg/diff/compute_test.go | 3 ++- ignite/pkg/diff/subtract_test.go | 1 + 6 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index a482eb80c0..142e08f492 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -2,9 +2,10 @@ package cmd import ( semver "github.com/Masterminds/semver/v3" + "github.com/spf13/cobra" + "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/migdiff" "github.com/ignite/cli/v28/ignite/pkg/errors" - "github.com/spf13/cobra" ) const ( diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index 7c4bec9d63..7993ed72f6 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -12,6 +12,7 @@ import ( "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/hexops/gotextdiff" + "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/exec" "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/step" "github.com/ignite/cli/v28/ignite/pkg/diff" diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go b/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go index 4a0b5b64d5..ebd3759f57 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/Masterminds/semver/v3" + "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/exec" "github.com/ignite/cli/v28/ignite/pkg/errors" ) diff --git a/ignite/pkg/diff/compute.go b/ignite/pkg/diff/compute.go index 86bf7a717e..ca24775267 100644 --- a/ignite/pkg/diff/compute.go +++ b/ignite/pkg/diff/compute.go @@ -10,6 +10,7 @@ import ( "github.com/hexops/gotextdiff" "github.com/hexops/gotextdiff/myers" "github.com/hexops/gotextdiff/span" + "github.com/ignite/cli/v28/ignite/pkg/errors" ) diff --git a/ignite/pkg/diff/compute_test.go b/ignite/pkg/diff/compute_test.go index 73d86db468..32fe7f5b75 100644 --- a/ignite/pkg/diff/compute_test.go +++ b/ignite/pkg/diff/compute_test.go @@ -4,8 +4,9 @@ import ( "testing" "testing/fstest" - "github.com/ignite/cli/v28/ignite/pkg/diff" "github.com/stretchr/testify/require" + + "github.com/ignite/cli/v28/ignite/pkg/diff" ) func TestComputeFS(t *testing.T) { diff --git a/ignite/pkg/diff/subtract_test.go b/ignite/pkg/diff/subtract_test.go index a795260c2e..8e072e5ee1 100644 --- a/ignite/pkg/diff/subtract_test.go +++ b/ignite/pkg/diff/subtract_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/hexops/gotextdiff" + "github.com/ignite/cli/v28/ignite/pkg/diff" ) From 6b9cb95577199b293de75136184774a5ada2d932 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Wed, 14 Feb 2024 16:34:23 +0330 Subject: [PATCH 24/69] Fix cleanup --- ignite/internal/tools/gen-mig-diffs/migdiff/gen.go | 1 - 1 file changed, 1 deletion(-) diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index 7993ed72f6..88ea8e7210 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -103,7 +103,6 @@ func NewGenerator(from, to *semver.Version, source string) (*Generator, error) { func createTempDir() (string, error) { tmpdir, err := os.MkdirTemp("", ".migdoc") - defer os.RemoveAll(tmpdir) if err != nil { return "", err } From a25072fc38a39064de00a188ee762c11b2d749df Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Wed, 14 Feb 2024 16:38:46 +0330 Subject: [PATCH 25/69] Update ignite/internal/tools/gen-mig-diffs/migdiff/gen.go Co-authored-by: Danilo Pantani --- ignite/internal/tools/gen-mig-diffs/migdiff/gen.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index 88ea8e7210..b8f3d2d669 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -111,10 +111,9 @@ func createTempDir() (string, error) { } func cloneIgniteRepo(path string) (*git.Repository, error) { - repo, err := git.PlainClone(path, false, &git.CloneOptions{ + return git.PlainClone(path, false, &git.CloneOptions{ URL: igniteCliRepository, }) - return repo, err } // getRepoVersionTags returns a sorted collection of semver tags from the ignite cli repository. From dda1437235122cb607d970f7fc78ee842832d959 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Wed, 14 Feb 2024 16:49:26 +0330 Subject: [PATCH 26/69] Update ignite/internal/tools/gen-mig-diffs/migdiff/gen.go Co-authored-by: Danilo Pantani --- .../tools/gen-mig-diffs/migdiff/gen.go | 61 +++++++------------ 1 file changed, 22 insertions(+), 39 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index b8f3d2d669..6af74ab865 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -158,54 +158,37 @@ func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collec return nil, nil, errors.New("At least two semver tags are required") } - // Replace fromVer and toVer with equivalent semver tags from versions - if fromVer != nil { - found := false - for _, ver := range versions { - if ver.Equal(fromVer) { - fromVer = ver - found = true - break - } - } - if !found { - return nil, nil, errors.Errorf("tag %s not found", fromVer) - } - } - if toVer != nil { - found := false - for _, ver := range versions { - if ver.Equal(toVer) { - toVer = ver - found = true - break - } - } - if !found { - return nil, nil, errors.Errorf("tag %s not found", toVer) - } +versionMap := make(map[string]*semver.Version) + for _, ver := range versions { + versionMap[ver.String()] = ver } // Picking default values for fromVer and toVer such that: // If both fromVer and toVer are not provided, then generate migration document for second last and last semver tags // If only fromVer is not provided, then use the tag before toVer as fromVer // If only toVer is not provided, then use the last tag as toVer - if fromVer == nil { - if toVer != nil { - sort.Search(versions.Len(), func(i int) bool { - if versions[i].LessThan(toVer) { - fromVer = versions[i] - return false - } - return true - }) - } else { - fromVer = versions[versions.Len()-2] + if toVer != nil { + if _, found := versionMap[toVer.String()]; !found { + return nil, nil, errors.Errorf("tag %s not found", toVer) } - } - if toVer == nil { + } else { toVer = versions[versions.Len()-1] } + + // Replace fromVer and toVer with equivalent semver tags from versions + if fromVer != nil { + if _, found := versionMap[fromVer.String()]; !found { + return nil, nil, errors.Errorf("tag %s not found", fromVer) + } + } else { + sort.Search(versions.Len(), func(i int) bool { + if versions[i].LessThan(toVer) { + fromVer = versions[i] + return false + } + return true + }) + } // Unable to generate migration document if fromVer is greater or equal to toVer if fromVer.GreaterThan(toVer) || fromVer.Equal(toVer) { From 1aac568a50dc242fc6d8ff0bf3a11d25f9b99815 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Wed, 14 Feb 2024 17:28:07 +0330 Subject: [PATCH 27/69] Fix lint --- ignite/internal/tools/gen-mig-diffs/migdiff/gen.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index 6af74ab865..92d976b7d8 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -158,7 +158,7 @@ func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collec return nil, nil, errors.New("At least two semver tags are required") } -versionMap := make(map[string]*semver.Version) + versionMap := make(map[string]*semver.Version) for _, ver := range versions { versionMap[ver.String()] = ver } @@ -174,7 +174,7 @@ versionMap := make(map[string]*semver.Version) } else { toVer = versions[versions.Len()-1] } - + // Replace fromVer and toVer with equivalent semver tags from versions if fromVer != nil { if _, found := versionMap[fromVer.String()]; !found { From 08276afd003b8b9994c58024a980e6fbf92725d1 Mon Sep 17 00:00:00 2001 From: Ehsan-saradar Date: Thu, 15 Feb 2024 14:00:22 +0330 Subject: [PATCH 28/69] Use cliui instead of log package --- .../internal/tools/gen-mig-diffs/cmd/root.go | 5 +- .../tools/gen-mig-diffs/migdiff/gen.go | 49 +++++++++++++------ 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 142e08f492..cbe31a8404 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -5,6 +5,7 @@ import ( "github.com/spf13/cobra" "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/migdiff" + "github.com/ignite/cli/v28/ignite/pkg/cliui" "github.com/ignite/cli/v28/ignite/pkg/errors" ) @@ -36,7 +37,9 @@ func NewRootCmd() *cobra.Command { return errors.Wrapf(err, "failed to parse to version %s", to) } - mdg, err := migdiff.NewGenerator(fromVer, toVer, source) + session := cliui.New() + defer session.End() + mdg, err := migdiff.NewGenerator(fromVer, toVer, source, session) if err != nil { return err } diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index 92d976b7d8..2bfcc5b95a 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -3,7 +3,6 @@ package migdiff import ( "context" "fmt" - "log" "os" "path/filepath" "sort" @@ -13,6 +12,7 @@ import ( "github.com/go-git/go-git/v5/plumbing" "github.com/hexops/gotextdiff" + "github.com/ignite/cli/v28/ignite/pkg/cliui" "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/exec" "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/step" "github.com/ignite/cli/v28/ignite/pkg/diff" @@ -49,36 +49,40 @@ type Generator struct { from, to *semver.Version tempDir, repoDir string repo *git.Repository - logger *log.Logger + session *cliui.Session } // NewGenerator creates a new generator for migration diffs between from and to versions of ignite cli // If source is empty, then it clones the ignite cli repository to a temporary directory and uses it as the source. -func NewGenerator(from, to *semver.Version, source string) (*Generator, error) { - logger := log.New(os.Stdout, "", log.LstdFlags) - +func NewGenerator(from, to *semver.Version, source string, session *cliui.Session) (*Generator, error) { tempDir, err := createTempDir() if err != nil { return nil, errors.Wrap(err, "failed to create temporary directory") } - logger.Println("Created temporary directory:", tempDir) + session.EventBus().SendInfo(fmt.Sprintf("Created temporary directory: %s", tempDir)) var ( repoDir = source repo *git.Repository ) if source == "" { - logger.Println("Cloning ignite repository...") + session.StartSpinner("Cloning ignite repository...") + repoDir = filepath.Join(tempDir, igniteRepoPath) repo, err = cloneIgniteRepo(repoDir) if err != nil { return nil, errors.Wrap(err, "failed to clone ignite repository") } + + session.StopSpinner() + session.EventBus().SendInfo(fmt.Sprintf("Cloned ignite repository to: %s", repoDir)) } else { repo, err = git.PlainOpen(source) if err != nil { return nil, errors.Wrap(err, "failed to open ignite repository") } + + session.EventBus().SendInfo(fmt.Sprintf("Using ignite repository at: %s", repoDir)) } versions, err := getRepoVersionTags(repoDir) @@ -97,7 +101,7 @@ func NewGenerator(from, to *semver.Version, source string) (*Generator, error) { tempDir: tempDir, repoDir: repoDir, repo: repo, - logger: logger, + session: session, }, nil } @@ -198,13 +202,18 @@ func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collec return fromVer, toVer, nil } -func (g *Generator) Cleanup() error { - g.logger.Println("Cleaning up temporary directory:", g.tempDir) - return os.RemoveAll(g.tempDir) +func (g *Generator) Cleanup() { + err := os.RemoveAll(g.tempDir) + if err != nil { + g.session.EventBus().SendError(err) + return + } + + g.session.EventBus().SendInfo(fmt.Sprintf("Removed temporary directory: %s", g.tempDir)) } func (g *Generator) Generate(outputPath string) error { - g.logger.Printf("Generating migration diffs for %s->%s\n", g.from, g.to) + g.session.Printf("Generating migration diffs for v%s -> v%s\n", g.from, g.to) fromDir := filepath.Join(g.tempDir, g.from.Original()) err := g.runScaffoldsForVersion(g.from, fromDir) @@ -217,23 +226,27 @@ func (g *Generator) Generate(outputPath string) error { return errors.Wrapf(err, "failed to run scaffolds for version %s", g.to) } - g.logger.Println("Calculating diff...") + g.session.StartSpinner("Calculating diff...") diffs, err := calculateDiffs(fromDir, toDir) if err != nil { return errors.Wrap(err, "failed to calculate diff") } + g.session.StopSpinner() + g.session.EventBus().SendInfo("Diff calculated successfully") err = saveDiffs(diffs, outputPath) if err != nil { return errors.Wrap(err, "failed to save diff map") } - log.Println("Migration diffs generated successfully at", outputPath) + g.session.Println("Migration diffs generated successfully at", outputPath) return nil } // Run scaffolds commands one by one with the given version of ignite cli and save the output in the output directory. func (g *Generator) runScaffoldsForVersion(ver *semver.Version, outputDir string) error { + g.session.StartSpinner(fmt.Sprintf("Building ignite cli for v%s...", ver)) + err := g.checkoutToTag(ver.Original()) if err != nil { return err @@ -244,6 +257,11 @@ func (g *Generator) runScaffoldsForVersion(ver *semver.Version, outputDir string return err } + g.session.StopSpinner() + g.session.EventBus().SendInfo(fmt.Sprintf("Built ignite cli for v%s", ver)) + + g.session.StartSpinner(fmt.Sprintf("Running scaffold commands for v%s...", ver)) + binPath := filepath.Join(g.repoDir, igniteBinaryPath) scaffolder := NewScaffolder(binPath, defaultScaffoldCommands) err = scaffolder.Run(ver, outputDir) @@ -251,6 +269,9 @@ func (g *Generator) runScaffoldsForVersion(ver *semver.Version, outputDir string return err } + g.session.StopSpinner() + g.session.EventBus().SendInfo(fmt.Sprintf("Scaffolded code for commands at %s", outputDir)) + return nil } From 963634629e9be05e7b2a1200154478908c6fbe78 Mon Sep 17 00:00:00 2001 From: Pantani Date: Fri, 23 Feb 2024 20:18:10 -0300 Subject: [PATCH 29/69] add gen options --- .../internal/tools/gen-mig-diffs/cmd/root.go | 12 +- .../tools/gen-mig-diffs/migdiff/gen.go | 107 +++++++++++------- 2 files changed, 76 insertions(+), 43 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index cbe31a8404..80c3871b05 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -23,10 +23,12 @@ func NewRootCmd() *cobra.Command { Short: "Generate migration diffs", Long: "This tool is used to generate migration diff files for each of ignites scaffold commands", RunE: func(cmd *cobra.Command, args []string) error { - from, _ := cmd.Flags().GetString(fromFlag) - to, _ := cmd.Flags().GetString(toFlag) - source := cmd.Flag(sourceFlag).Value.String() - output, _ := cmd.Flags().GetString(outputFlag) + var ( + from, _ = cmd.Flags().GetString(fromFlag) + to, _ = cmd.Flags().GetString(toFlag) + source, _ = cmd.Flags().GetString(sourceFlag) + output, _ = cmd.Flags().GetString(outputFlag) + ) fromVer, err := semver.NewVersion(from) if err != nil && from != "" { @@ -39,7 +41,7 @@ func NewRootCmd() *cobra.Command { session := cliui.New() defer session.End() - mdg, err := migdiff.NewGenerator(fromVer, toVer, source, session) + mdg, err := migdiff.NewGenerator(fromVer, toVer, session, migdiff.WithSource(source)) if err != nil { return err } diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index 2bfcc5b95a..5fa5b3f848 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -20,9 +20,9 @@ import ( ) const ( - igniteCliRepository = "http://github.com/ignite/cli.git" - igniteRepoPath = "src/github.com/ignite/cli" - igniteBinaryPath = "dist/ignite" + defaultRepoURL = "http://github.com/ignite/cli.git" + defaultRepoPath = "src/github.com/ignite/cli" + defaultBinaryPath = "dist/ignite" ) var diffIgnoreGlobs = []string{ @@ -44,45 +44,91 @@ var diffIgnoreGlobs = []string{ "**.json", } -// Generator is used to generate migration diffs. -type Generator struct { - from, to *semver.Version - tempDir, repoDir string - repo *git.Repository - session *cliui.Session +type ( + // Generator is used to generate migration diffs. + Generator struct { + from, to *semver.Version + tempDir, repoDir string + repo *git.Repository + session *cliui.Session + } + + // genOptions represents configuration for the generator. + genOptions struct { + source string + repoPath string + repoURL string + } + // GenOptions configures the generator. + GenOptions func(*genOptions) +) + +// newGenOptions returns a genOptions with default options. +func newGenOptions() genOptions { + return genOptions{ + source: "", + repoPath: defaultRepoPath, + repoURL: defaultRepoURL, + } +} + +// WithSource set the repo source GenOptions. +func WithSource(source string) GenOptions { + return func(m *genOptions) { + m.source = source + } +} + +// WithRepoPath set the repo path GenOptions. +func WithRepoPath(repoPath string) GenOptions { + return func(m *genOptions) { + m.repoPath = repoPath + } +} + +// WithRepoURL set the repo URL GenOptions. +func WithRepoURL(repoURL string) GenOptions { + return func(m *genOptions) { + m.repoURL = repoURL + } } // NewGenerator creates a new generator for migration diffs between from and to versions of ignite cli // If source is empty, then it clones the ignite cli repository to a temporary directory and uses it as the source. -func NewGenerator(from, to *semver.Version, source string, session *cliui.Session) (*Generator, error) { - tempDir, err := createTempDir() +func NewGenerator(from, to *semver.Version, session *cliui.Session, options ...GenOptions) (*Generator, error) { + opts := newGenOptions() + for _, apply := range options { + apply(&opts) + } + + tempDir, err := os.MkdirTemp("", ".migdoc") if err != nil { return nil, errors.Wrap(err, "failed to create temporary directory") } session.EventBus().SendInfo(fmt.Sprintf("Created temporary directory: %s", tempDir)) var ( - repoDir = source + repoDir = opts.source repo *git.Repository ) - if source == "" { + if repoDir != "" { + repo, err = git.PlainOpen(repoDir) + if err != nil { + return nil, errors.Wrap(err, "failed to open ignite repository") + } + + session.EventBus().SendInfo(fmt.Sprintf("Using ignite repository at: %s", repoDir)) + } else { session.StartSpinner("Cloning ignite repository...") - repoDir = filepath.Join(tempDir, igniteRepoPath) - repo, err = cloneIgniteRepo(repoDir) + repoDir = filepath.Join(tempDir, opts.repoPath) + repo, err = git.PlainClone(repoDir, false, &git.CloneOptions{URL: opts.repoURL}) if err != nil { return nil, errors.Wrap(err, "failed to clone ignite repository") } session.StopSpinner() session.EventBus().SendInfo(fmt.Sprintf("Cloned ignite repository to: %s", repoDir)) - } else { - repo, err = git.PlainOpen(source) - if err != nil { - return nil, errors.Wrap(err, "failed to open ignite repository") - } - - session.EventBus().SendInfo(fmt.Sprintf("Using ignite repository at: %s", repoDir)) } versions, err := getRepoVersionTags(repoDir) @@ -105,21 +151,6 @@ func NewGenerator(from, to *semver.Version, source string, session *cliui.Sessio }, nil } -func createTempDir() (string, error) { - tmpdir, err := os.MkdirTemp("", ".migdoc") - if err != nil { - return "", err - } - - return tmpdir, nil -} - -func cloneIgniteRepo(path string) (*git.Repository, error) { - return git.PlainClone(path, false, &git.CloneOptions{ - URL: igniteCliRepository, - }) -} - // getRepoVersionTags returns a sorted collection of semver tags from the ignite cli repository. func getRepoVersionTags(repoDir string) (semver.Collection, error) { repo, err := git.PlainOpen(repoDir) @@ -262,7 +293,7 @@ func (g *Generator) runScaffoldsForVersion(ver *semver.Version, outputDir string g.session.StartSpinner(fmt.Sprintf("Running scaffold commands for v%s...", ver)) - binPath := filepath.Join(g.repoDir, igniteBinaryPath) + binPath := filepath.Join(g.repoDir, defaultBinaryPath) scaffolder := NewScaffolder(binPath, defaultScaffoldCommands) err = scaffolder.Run(ver, outputDir) if err != nil { From f9df2d3309aeed8706e03a11beed033fb9f11ca8 Mon Sep 17 00:00:00 2001 From: Pantani Date: Mon, 26 Feb 2024 21:51:23 -0300 Subject: [PATCH 30/69] code clean --- .../tools/gen-mig-diffs/migdiff/gen.go | 37 ++++++++----------- .../tools/gen-mig-diffs/migdiff/scaffold.go | 3 +- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index 5fa5b3f848..7627a91483 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -247,13 +247,11 @@ func (g *Generator) Generate(outputPath string) error { g.session.Printf("Generating migration diffs for v%s -> v%s\n", g.from, g.to) fromDir := filepath.Join(g.tempDir, g.from.Original()) - err := g.runScaffoldsForVersion(g.from, fromDir) - if err != nil { + if err := g.runScaffoldsForVersion(g.from, fromDir); err != nil { return errors.Wrapf(err, "failed to run scaffolds for version %s", g.from) } toDir := filepath.Join(g.tempDir, g.to.Original()) - err = g.runScaffoldsForVersion(g.to, toDir) - if err != nil { + if err := g.runScaffoldsForVersion(g.to, toDir); err != nil { return errors.Wrapf(err, "failed to run scaffolds for version %s", g.to) } @@ -265,8 +263,7 @@ func (g *Generator) Generate(outputPath string) error { g.session.StopSpinner() g.session.EventBus().SendInfo("Diff calculated successfully") - err = saveDiffs(diffs, outputPath) - if err != nil { + if err = saveDiffs(diffs, outputPath); err != nil { return errors.Wrap(err, "failed to save diff map") } g.session.Println("Migration diffs generated successfully at", outputPath) @@ -278,13 +275,11 @@ func (g *Generator) Generate(outputPath string) error { func (g *Generator) runScaffoldsForVersion(ver *semver.Version, outputDir string) error { g.session.StartSpinner(fmt.Sprintf("Building ignite cli for v%s...", ver)) - err := g.checkoutToTag(ver.Original()) - if err != nil { + if err := g.checkoutToTag(ver.Original()); err != nil { return err } - err = g.buildIgniteCli() - if err != nil { + if err := g.buildIgniteCli(); err != nil { return err } @@ -294,9 +289,8 @@ func (g *Generator) runScaffoldsForVersion(ver *semver.Version, outputDir string g.session.StartSpinner(fmt.Sprintf("Running scaffold commands for v%s...", ver)) binPath := filepath.Join(g.repoDir, defaultBinaryPath) - scaffolder := NewScaffolder(binPath, defaultScaffoldCommands) - err = scaffolder.Run(ver, outputDir) - if err != nil { + s := NewScaffolder(binPath, defaultScaffoldCommands) + if err := s.Run(ver, outputDir); err != nil { return err } @@ -312,9 +306,7 @@ func (g *Generator) checkoutToTag(tag string) error { return err } - err = wt.Checkout(&git.CheckoutOptions{ - Branch: plumbing.NewTagReferenceName(tag), - }) + err = wt.Checkout(&git.CheckoutOptions{Branch: plumbing.NewTagReferenceName(tag)}) if err != nil { return errors.Wrapf(err, "failed to checkout tag %s", tag) } @@ -375,20 +367,21 @@ func subtractUnifieds(a, b []gotextdiff.Unified) []gotextdiff.Unified { } func saveDiffs(diffs map[string][]gotextdiff.Unified, outputPath string) error { - err := os.MkdirAll(outputPath, os.ModePerm) - if err != nil { + if err := os.MkdirAll(outputPath, os.ModePerm); err != nil { return err } for name, diffs := range diffs { - outf, err := os.Create(filepath.Join(outputPath, name+".diff")) + output, err := os.Create(filepath.Join(outputPath, name+".diff")) if err != nil { return err } - defer outf.Close() for _, d := range diffs { - outf.WriteString(fmt.Sprint(d)) - outf.WriteString("\n") + output.WriteString(fmt.Sprint(d)) + output.WriteString("\n") + } + if err := output.Close(); err != nil { + return err } } diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go b/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go index ebd3759f57..7e5cdcea46 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go @@ -126,8 +126,7 @@ func (s *Scaffolder) runCommand( return err } - err = s.runCommand(name, c.Prerequisites, c.Commands, ver, out) - if err != nil { + if err := s.runCommand(name, c.Prerequisites, c.Commands, ver, out); err != nil { return err } } From 9c13c15732b51e9b60f6d41c5e94649ce1750499 Mon Sep 17 00:00:00 2001 From: Pantani Date: Mon, 26 Feb 2024 22:48:20 -0300 Subject: [PATCH 31/69] improve error log --- ignite/internal/tools/gen-mig-diffs/migdiff/gen.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index 7627a91483..887c7a151e 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -248,11 +248,11 @@ func (g *Generator) Generate(outputPath string) error { fromDir := filepath.Join(g.tempDir, g.from.Original()) if err := g.runScaffoldsForVersion(g.from, fromDir); err != nil { - return errors.Wrapf(err, "failed to run scaffolds for version %s", g.from) + return errors.Wrapf(err, "failed to run scaffolds for 'FROM' version %s", g.from) } toDir := filepath.Join(g.tempDir, g.to.Original()) if err := g.runScaffoldsForVersion(g.to, toDir); err != nil { - return errors.Wrapf(err, "failed to run scaffolds for version %s", g.to) + return errors.Wrapf(err, "failed to run scaffolds for 'TO' version %s", g.to) } g.session.StartSpinner("Calculating diff...") From 9e7b2aee0976cbee6daea7311b54e6cdbcd496e3 Mon Sep 17 00:00:00 2001 From: Pantani Date: Mon, 26 Feb 2024 23:07:36 -0300 Subject: [PATCH 32/69] reset and clean the repo before the checkout to avoid conflicts --- ignite/internal/tools/gen-mig-diffs/migdiff/gen.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index 887c7a151e..a06d4b735d 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -306,8 +306,15 @@ func (g *Generator) checkoutToTag(tag string) error { return err } - err = wt.Checkout(&git.CheckoutOptions{Branch: plumbing.NewTagReferenceName(tag)}) - if err != nil { + // Reset and clean the git directory before the checkout to avoid conflicts. + if err := wt.Reset(&git.ResetOptions{Mode: git.HardReset}); err != nil { + return errors.Wrapf(err, "failed to reset %s", g.repoDir) + } + if err := wt.Clean(&git.CleanOptions{Dir: true}); err != nil { + return errors.Wrapf(err, "failed to reset %s", g.repoDir) + } + + if err = wt.Checkout(&git.CheckoutOptions{Branch: plumbing.NewTagReferenceName(tag)}); err != nil { return errors.Wrapf(err, "failed to checkout tag %s", tag) } From 8d1a7c41a8740dfdadefe3f8685568cc2c31ec41 Mon Sep 17 00:00:00 2001 From: Pantani Date: Tue, 27 Feb 2024 01:26:02 -0300 Subject: [PATCH 33/69] use https for repo url --- ignite/internal/tools/gen-mig-diffs/migdiff/gen.go | 2 +- ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go index a06d4b735d..0c0377fc33 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go @@ -20,7 +20,7 @@ import ( ) const ( - defaultRepoURL = "http://github.com/ignite/cli.git" + defaultRepoURL = "https://github.com/ignite/cli.git" defaultRepoPath = "src/github.com/ignite/cli" defaultBinaryPath = "dist/ignite" ) diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go b/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go index 7e5cdcea46..e0ab51138b 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go @@ -120,6 +120,7 @@ func (s *Scaffolder) runCommand( ver *semver.Version, out string, ) error { + // TODO add cache for duplicated commands. for _, p := range prerequisites { c, err := s.findCommand(p) if err != nil { From 0d90d3d9dcc61b85f84a970127b14c6c475165ed Mon Sep 17 00:00:00 2001 From: Pantani Date: Tue, 27 Feb 2024 02:22:14 -0300 Subject: [PATCH 34/69] draft refactor --- .../internal/tools/gen-mig-diffs/cmd/root.go | 50 ++++- .../tools/gen-mig-diffs/pkg/diff/diff.go | 114 ++++++++++++ .../{migdiff/gen.go => pkg/repo/repo.go} | 176 +++--------------- .../{migdiff => pkg/scaffold}/scaffold.go | 98 ++++------ 4 files changed, 228 insertions(+), 210 deletions(-) create mode 100644 ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go rename ignite/internal/tools/gen-mig-diffs/{migdiff/gen.go => pkg/repo/repo.go} (65%) rename ignite/internal/tools/gen-mig-diffs/{migdiff => pkg/scaffold}/scaffold.go (73%) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 80c3871b05..8805f9bee5 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -1,10 +1,14 @@ package cmd import ( - semver "github.com/Masterminds/semver/v3" + "fmt" + + "github.com/Masterminds/semver/v3" "github.com/spf13/cobra" - "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/migdiff" + "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/pkg/diff" + "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/pkg/repo" + "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/pkg/scaffold" "github.com/ignite/cli/v28/ignite/pkg/cliui" "github.com/ignite/cli/v28/ignite/pkg/errors" ) @@ -20,7 +24,7 @@ const ( func NewRootCmd() *cobra.Command { cmd := &cobra.Command{ Use: "gen-mig-diffs", - Short: "Generate migration diffs", + Short: "GenerateBinaries migration diffs", Long: "This tool is used to generate migration diff files for each of ignites scaffold commands", RunE: func(cmd *cobra.Command, args []string) error { var ( @@ -41,13 +45,47 @@ func NewRootCmd() *cobra.Command { session := cliui.New() defer session.End() - mdg, err := migdiff.NewGenerator(fromVer, toVer, session, migdiff.WithSource(source)) + + igniteRepo, err := repo.New(fromVer, toVer, session, repo.WithSource(source)) if err != nil { return err } - defer mdg.Cleanup() + defer igniteRepo.Cleanup() + + fromBin, toBin, err := igniteRepo.GenerateBinaries() + if err != nil { + return err + } + + sFrom := scaffold.New(fromBin, scaffold.DefaultCommands) + session.StartSpinner(fmt.Sprintf("Running scaffold commands for v%s...", fromVer.String())) + if err := sFrom.Run(fromVer, output); err != nil { + return err + } + + sTo := scaffold.New(toBin, scaffold.DefaultCommands) + session.StartSpinner(fmt.Sprintf("Running scaffold commands for v%s...", toVer.String())) + if err := sTo.Run(toVer, output); err != nil { + return err + } + + session.StopSpinner() + session.EventBus().SendInfo(fmt.Sprintf("Scaffolded code for commands at %s", output)) + + session.StartSpinner("Calculating diff...") + diffs, err := diff.CalculateDiffs(fromDir, toDir) + if err != nil { + return errors.Wrap(err, "failed to calculate diff") + } + session.StopSpinner() + session.EventBus().SendInfo("Diff calculated successfully") + + if err = diff.SaveDiffs(diffs, output); err != nil { + return errors.Wrap(err, "failed to save diff map") + } + session.Println("Migration diffs generated successfully at", output) - return mdg.Generate(output) + return nil }, } diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go new file mode 100644 index 0000000000..8007776317 --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go @@ -0,0 +1,114 @@ +package diff + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/hexops/gotextdiff" + + "github.com/ignite/cli/v28/ignite/pkg/diff" +) + +var diffIgnoreGlobs = []string{ + ".git/**", + "**.md", + "go.sum", + "**_test.go", + "**.pb.go", + "**.pb.gw.go", + "**.pulsar.go", + "**/node_modules/**", + "**/openapi.yml", + ".gitignore", + ".github/**", + "**.html", + "**.css", + "**.js", + "**.ts", + "**.json", +} + +func CalculateDiffs(fromDir, toDir string) (map[string][]gotextdiff.Unified, error) { + paths := make([]string, 0) + err := filepath.Walk(fromDir, func(path string, info os.FileInfo, err error) error { + if err == nil && info.IsDir() && path != fromDir { + paths = append(paths, path) + } + return nil + }) + if err != nil { + return nil, err + } + + diffs := make(map[string][]gotextdiff.Unified) + for _, s := range paths { + name := filepath.Base(s) + from := filepath.Join(fromDir, name) + if err := os.MkdirAll(from, os.ModePerm); err != nil { + return nil, err + } + to := filepath.Join(toDir, name) + if err := os.MkdirAll(to, os.ModePerm); err != nil { + return nil, err + } + + computedDiff, err := diff.ComputeFS( + os.DirFS(from), + os.DirFS(to), + diffIgnoreGlobs..., + ) + if err != nil { + return nil, err + } + + diffs[name] = computedDiff + } + return subtractBaseDiffs(diffs), nil +} + +// subtractBaseDiffs removes chain and module diffs from other diffs. +func subtractBaseDiffs(diffs map[string][]gotextdiff.Unified) map[string][]gotextdiff.Unified { + chainDiff := diffs["chain"] + moduleDiff := diffs["module"] + for name, d := range diffs { + if name != "chain" && name != "module" { + diffs[name] = subtractUnifieds(d, moduleDiff) + } + } + diffs["module"] = subtractUnifieds(moduleDiff, chainDiff) + return diffs +} + +func subtractUnifieds(a, b []gotextdiff.Unified) []gotextdiff.Unified { + for i, ad := range a { + for _, bd := range b { + if ad.From == bd.From && ad.To == bd.To { + a[i] = diff.Subtract(ad, bd) + } + } + } + return a +} + +func SaveDiffs(diffs map[string][]gotextdiff.Unified, outputPath string) error { + if err := os.MkdirAll(outputPath, os.ModePerm); err != nil { + return err + } + + for name, diffs := range diffs { + output, err := os.Create(filepath.Join(outputPath, name+".diff")) + if err != nil { + return err + } + for _, d := range diffs { + output.WriteString(fmt.Sprint(d)) + output.WriteString("\n") + } + if err := output.Close(); err != nil { + return err + } + } + + return nil +} diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go similarity index 65% rename from ignite/internal/tools/gen-mig-diffs/migdiff/gen.go rename to ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go index 0c0377fc33..9812622794 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/gen.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go @@ -1,4 +1,4 @@ -package migdiff +package repo import ( "context" @@ -10,12 +10,10 @@ import ( "github.com/Masterminds/semver/v3" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" - "github.com/hexops/gotextdiff" "github.com/ignite/cli/v28/ignite/pkg/cliui" "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/exec" "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/step" - "github.com/ignite/cli/v28/ignite/pkg/diff" "github.com/ignite/cli/v28/ignite/pkg/errors" ) @@ -25,25 +23,6 @@ const ( defaultBinaryPath = "dist/ignite" ) -var diffIgnoreGlobs = []string{ - ".git/**", - "**.md", - "go.sum", - "**_test.go", - "**.pb.go", - "**.pb.gw.go", - "**.pulsar.go", - "**/node_modules/**", - "**/openapi.yml", - ".gitignore", - ".github/**", - "**.html", - "**.css", - "**.js", - "**.ts", - "**.json", -} - type ( // Generator is used to generate migration diffs. Generator struct { @@ -93,9 +72,9 @@ func WithRepoURL(repoURL string) GenOptions { } } -// NewGenerator creates a new generator for migration diffs between from and to versions of ignite cli +// New creates a new generator for migration diffs between from and to versions of ignite cli // If source is empty, then it clones the ignite cli repository to a temporary directory and uses it as the source. -func NewGenerator(from, to *semver.Version, session *cliui.Session, options ...GenOptions) (*Generator, error) { +func New(from, to *semver.Version, session *cliui.Session, options ...GenOptions) (*Generator, error) { opts := newGenOptions() for _, apply := range options { apply(&opts) @@ -186,6 +165,17 @@ func getRepoVersionTags(repoDir string) (semver.Collection, error) { return versions, nil } +// Cleanup cleanup all temporary directories. +func (g *Generator) Cleanup() { + err := os.RemoveAll(g.tempDir) + if err != nil { + g.session.EventBus().SendError(err) + return + } + + g.session.EventBus().SendInfo(fmt.Sprintf("Removed temporary directory: %s", g.tempDir)) +} + // validateVersionRange checks if the provided fromVer and toVer exist in the versions and if any of them is nil, then it picks default values. func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collection) (*semver.Version, *semver.Version, error) { // Unable to generate migration document if there are less than two releases! @@ -233,73 +223,41 @@ func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collec return fromVer, toVer, nil } -func (g *Generator) Cleanup() { - err := os.RemoveAll(g.tempDir) - if err != nil { - g.session.EventBus().SendError(err) - return - } - - g.session.EventBus().SendInfo(fmt.Sprintf("Removed temporary directory: %s", g.tempDir)) -} - -func (g *Generator) Generate(outputPath string) error { +func (g *Generator) GenerateBinaries() (string, string, error) { g.session.Printf("Generating migration diffs for v%s -> v%s\n", g.from, g.to) - - fromDir := filepath.Join(g.tempDir, g.from.Original()) - if err := g.runScaffoldsForVersion(g.from, fromDir); err != nil { - return errors.Wrapf(err, "failed to run scaffolds for 'FROM' version %s", g.from) - } - toDir := filepath.Join(g.tempDir, g.to.Original()) - if err := g.runScaffoldsForVersion(g.to, toDir); err != nil { - return errors.Wrapf(err, "failed to run scaffolds for 'TO' version %s", g.to) - } - - g.session.StartSpinner("Calculating diff...") - diffs, err := calculateDiffs(fromDir, toDir) + fromBinPath, err := g.buildIgniteCli(g.from) if err != nil { - return errors.Wrap(err, "failed to calculate diff") + return "", "", errors.Wrapf(err, "failed to run scaffolds for 'FROM' version %s", g.from) } - g.session.StopSpinner() - g.session.EventBus().SendInfo("Diff calculated successfully") - - if err = saveDiffs(diffs, outputPath); err != nil { - return errors.Wrap(err, "failed to save diff map") + toBinPath, err := g.buildIgniteCli(g.to) + if err != nil { + return "", "", errors.Wrapf(err, "failed to run scaffolds for 'TO' version %s", g.to) } - g.session.Println("Migration diffs generated successfully at", outputPath) - - return nil + return fromBinPath, toBinPath, nil } -// Run scaffolds commands one by one with the given version of ignite cli and save the output in the output directory. -func (g *Generator) runScaffoldsForVersion(ver *semver.Version, outputDir string) error { +// buildIgniteCli build the ignite CLI from version. +func (g *Generator) buildIgniteCli(ver *semver.Version) (string, error) { g.session.StartSpinner(fmt.Sprintf("Building ignite cli for v%s...", ver)) if err := g.checkoutToTag(ver.Original()); err != nil { - return err + return "", err } - if err := g.buildIgniteCli(); err != nil { - return err + err := exec.Exec(context.Background(), []string{"make", "build"}, exec.StepOption(step.Workdir(g.repoDir))) + if err != nil { + return "", errors.Wrap(err, "failed to build ignite cli using make build") } - g.session.StopSpinner() - g.session.EventBus().SendInfo(fmt.Sprintf("Built ignite cli for v%s", ver)) - - g.session.StartSpinner(fmt.Sprintf("Running scaffold commands for v%s...", ver)) - binPath := filepath.Join(g.repoDir, defaultBinaryPath) - s := NewScaffolder(binPath, defaultScaffoldCommands) - if err := s.Run(ver, outputDir); err != nil { - return err - } g.session.StopSpinner() - g.session.EventBus().SendInfo(fmt.Sprintf("Scaffolded code for commands at %s", outputDir)) + g.session.EventBus().SendInfo(fmt.Sprintf("Built ignite cli for v%s", ver)) - return nil + return binPath, nil } +// checkoutToTag checkout the repository from a specific git tag. func (g *Generator) checkoutToTag(tag string) error { wt, err := g.repo.Worktree() if err != nil { @@ -320,77 +278,3 @@ func (g *Generator) checkoutToTag(tag string) error { return nil } - -func (g *Generator) buildIgniteCli() error { - err := exec.Exec(context.Background(), []string{"make", "build"}, exec.StepOption(step.Workdir(g.repoDir))) - if err != nil { - return errors.Wrap(err, "failed to build ignite cli using make build") - } - - return nil -} - -func calculateDiffs(fromDir, toDir string) (map[string][]gotextdiff.Unified, error) { - diffs := make(map[string][]gotextdiff.Unified) - for _, s := range defaultScaffoldCommands { - diff, err := diff.ComputeFS( - os.DirFS(filepath.Join(fromDir, s.Name)), - os.DirFS(filepath.Join(toDir, s.Name)), - diffIgnoreGlobs..., - ) - if err != nil { - return nil, err - } - diffs[s.Name] = diff - } - - subtractBaseDiffs(diffs) - - return diffs, nil -} - -// subtractBaseDiffs removes chain and module diffs from other diffs. -func subtractBaseDiffs(diffs map[string][]gotextdiff.Unified) { - chainDiff := diffs["chain"] - moduleDiff := diffs["module"] - for name, d := range diffs { - if name != "chain" && name != "module" { - diffs[name] = subtractUnifieds(d, moduleDiff) - } - } - - diffs["module"] = subtractUnifieds(moduleDiff, chainDiff) -} - -func subtractUnifieds(a, b []gotextdiff.Unified) []gotextdiff.Unified { - for i, ad := range a { - for _, bd := range b { - if ad.From == bd.From && ad.To == bd.To { - a[i] = diff.Subtract(ad, bd) - } - } - } - return a -} - -func saveDiffs(diffs map[string][]gotextdiff.Unified, outputPath string) error { - if err := os.MkdirAll(outputPath, os.ModePerm); err != nil { - return err - } - - for name, diffs := range diffs { - output, err := os.Create(filepath.Join(outputPath, name+".diff")) - if err != nil { - return err - } - for _, d := range diffs { - output.WriteString(fmt.Sprint(d)) - output.WriteString("\n") - } - if err := output.Close(); err != nil { - return err - } - } - - return nil -} diff --git a/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go similarity index 73% rename from ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go rename to ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go index e0ab51138b..e066716e9f 100644 --- a/ignite/internal/tools/gen-mig-diffs/migdiff/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go @@ -1,4 +1,4 @@ -package migdiff +package scaffold import ( "context" @@ -12,64 +12,73 @@ import ( "github.com/ignite/cli/v28/ignite/pkg/errors" ) -var defaultScaffoldCommands = []ScaffoldCommand{ - { - Name: "chain", - Commands: []string{ - "chain example --no-module", - }, +type ( + // Command represents a set of commands and prerequisites scaffold commands that are required to run before them. + Command struct { + // Name is the unique identifier of the command + Name string + // Prerequisites is the names of commands that need to be run before this command set + Prerequisites []string + // Commands is the list of scaffold commands that are going to be run + // The commands will be prefixed with "ignite scaffold" and executed in order + Commands []string + } + + Scaffold struct { + ignitePath string + commands Commands + } + + Commands = map[string]Command +) + +var DefaultCommands = Commands{ + "chain": Command{ + Commands: []string{"chain example --no-module"}, }, - { - Name: "module", + "module": Command{ Prerequisites: []string{"chain"}, Commands: []string{ "module example --ibc", }, }, - { - Name: "list", + "list": Command{ Prerequisites: []string{"module"}, Commands: []string{ "list list1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, }, - { - Name: "map", + "map": Command{ Prerequisites: []string{"module"}, Commands: []string{ "map map1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --index i1:string --module example --yes", }, }, - { - Name: "single", + "single": Command{ Prerequisites: []string{"module"}, Commands: []string{ "single single1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, }, - { - Name: "type", + "type": Command{ Prerequisites: []string{"module"}, Commands: []string{ "type type1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, }, - { - Name: "message", + "message": Command{ Prerequisites: []string{"module"}, Commands: []string{ "message message1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, }, - { - Name: "query", + "query": Command{ Prerequisites: []string{"module"}, Commands: []string{ "query query1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints --module example --yes", }, }, - { - Name: "packet", + "packet": Command{ Prerequisites: []string{"module"}, Commands: []string{ "packet packet1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --ack f1:string,f2:strings,f3:bool,f4:int,f5:ints,f6:uint,f7:uints,f8:coin,f9:coins --module example --yes", @@ -77,30 +86,14 @@ var defaultScaffoldCommands = []ScaffoldCommand{ }, } -// ScaffoldCommand represents a set of commands and prerequisites scaffold commands that are required to run before them. -type ScaffoldCommand struct { - // Name is the unique identifier of the command - Name string - // Prerequisites is the names of commands that need to be run before this command set - Prerequisites []string - // Commands is the list of scaffold commands that are going to be run - // The commands will be prefixed with "ignite scaffold" and executed in order - Commands []string -} - -type Scaffolder struct { - ignitePath string - commands []ScaffoldCommand -} - -func NewScaffolder(ignitePath string, commands []ScaffoldCommand) *Scaffolder { - return &Scaffolder{ +func New(ignitePath string, commands Commands) Scaffold { + return Scaffold{ ignitePath: ignitePath, commands: commands, } } -func (s *Scaffolder) Run(ver *semver.Version, out string) error { +func (s Scaffold) Run(ver *semver.Version, out string) error { for _, c := range s.commands { if err := s.runCommand(c.Name, c.Prerequisites, c.Commands, ver, out); err != nil { return err @@ -113,7 +106,7 @@ func (s *Scaffolder) Run(ver *semver.Version, out string) error { return nil } -func (s *Scaffolder) runCommand( +func (s Scaffold) runCommand( name string, prerequisites []string, cmds []string, @@ -122,11 +115,10 @@ func (s *Scaffolder) runCommand( ) error { // TODO add cache for duplicated commands. for _, p := range prerequisites { - c, err := s.findCommand(p) - if err != nil { - return err + c, ok := s.commands[p] + if !ok { + return errors.Errorf("command %s not found", name) } - if err := s.runCommand(name, c.Prerequisites, c.Commands, ver, out); err != nil { return err } @@ -141,17 +133,7 @@ func (s *Scaffolder) runCommand( return nil } -func (s *Scaffolder) findCommand(name string) (ScaffoldCommand, error) { - for _, c := range s.commands { - if c.Name == name { - return c, nil - } - } - - return ScaffoldCommand{}, errors.Errorf("command %s not found", name) -} - -func (s *Scaffolder) executeScaffold(ver *semver.Version, name, cmd string, out string) error { +func (s Scaffold) executeScaffold(ver *semver.Version, name, cmd string, out string) error { args := []string{s.ignitePath, "scaffold"} args = append(args, strings.Fields(cmd)...) args = append(args, "--path", filepath.Join(out, name)) From ccd1cc7c78f0a3a03bc2e734afe0885ed4c587fb Mon Sep 17 00:00:00 2001 From: Pantani Date: Tue, 27 Feb 2024 02:27:41 -0300 Subject: [PATCH 35/69] improve the logs --- .../tools/gen-mig-diffs/pkg/repo/repo.go | 3 +-- .../tools/gen-mig-diffs/pkg/scaffold/scaffold.go | 16 ++++------------ 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go index 9812622794..43767417f2 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go @@ -224,7 +224,6 @@ func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collec } func (g *Generator) GenerateBinaries() (string, string, error) { - g.session.Printf("Generating migration diffs for v%s -> v%s\n", g.from, g.to) fromBinPath, err := g.buildIgniteCli(g.from) if err != nil { return "", "", errors.Wrapf(err, "failed to run scaffolds for 'FROM' version %s", g.from) @@ -238,7 +237,7 @@ func (g *Generator) GenerateBinaries() (string, string, error) { // buildIgniteCli build the ignite CLI from version. func (g *Generator) buildIgniteCli(ver *semver.Version) (string, error) { - g.session.StartSpinner(fmt.Sprintf("Building ignite cli for v%s...", ver)) + g.session.StartSpinner(fmt.Sprintf("Building binary for version v%s...", ver)) if err := g.checkoutToTag(ver.Original()); err != nil { return "", err diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go index e066716e9f..034f5b432c 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go @@ -98,7 +98,6 @@ func (s Scaffold) Run(ver *semver.Version, out string) error { if err := s.runCommand(c.Name, c.Prerequisites, c.Commands, ver, out); err != nil { return err } - if err := applyPostScaffoldExceptions(ver, c.Name, out); err != nil { return err } @@ -129,20 +128,17 @@ func (s Scaffold) runCommand( return err } } - return nil } func (s Scaffold) executeScaffold(ver *semver.Version, name, cmd string, out string) error { - args := []string{s.ignitePath, "scaffold"} - args = append(args, strings.Fields(cmd)...) + args := append([]string{s.ignitePath, "scaffold"}, strings.Fields(cmd)...) args = append(args, "--path", filepath.Join(out, name)) args = applyPreExecuteExceptions(ver, args) if err := exec.Exec(context.Background(), args); err != nil { return errors.Wrapf(err, "failed to execute ignite scaffold command: %s", cmd) } - return nil } @@ -153,7 +149,6 @@ func applyPreExecuteExceptions(ver *semver.Version, args []string) []string { if ver.LessThan(semver.MustParse("v0.27.0")) && args[2] != "chain" { args[len(args)-1] = filepath.Join(args[len(args)-1], "example") } - return args } @@ -162,18 +157,15 @@ func applyPostScaffoldExceptions(ver *semver.Version, name string, out string) e // In versions <0.27.0, "scaffold chain" command always creates a new directory with the name of chain at the given --path // so we need to move the directory to the parent directory. if ver.LessThan(semver.MustParse("v0.27.0")) { - err := os.Rename(filepath.Join(out, name, "example"), filepath.Join(out, "example_tmp")) - if err != nil { + if err := os.Rename(filepath.Join(out, name, "example"), filepath.Join(out, "example_tmp")); err != nil { return errors.Wrapf(err, "failed to move %s directory to tmp directory", name) } - err = os.RemoveAll(filepath.Join(out, name)) - if err != nil { + if err := os.RemoveAll(filepath.Join(out, name)); err != nil { return errors.Wrapf(err, "failed to remove %s directory", name) } - err = os.Rename(filepath.Join(out, "example_tmp"), filepath.Join(out, name)) - if err != nil { + if err := os.Rename(filepath.Join(out, "example_tmp"), filepath.Join(out, name)); err != nil { return errors.Wrapf(err, "failed to move tmp directory to %s directory", name) } } From 58d2d5d724989c7f48a06f12569fe51fe1b62f2d Mon Sep 17 00:00:00 2001 From: Pantani Date: Wed, 28 Feb 2024 19:39:39 -0300 Subject: [PATCH 36/69] remove useless code --- .../internal/tools/gen-mig-diffs/cmd/root.go | 19 +-- .../tools/gen-mig-diffs/pkg/repo/repo.go | 50 +++--- .../gen-mig-diffs/pkg/scaffold/commands.go | 55 ++++++ .../gen-mig-diffs/pkg/scaffold/scaffold.go | 160 ++++++++---------- 4 files changed, 162 insertions(+), 122 deletions(-) create mode 100644 ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 8805f9bee5..47883d3684 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -27,13 +27,15 @@ func NewRootCmd() *cobra.Command { Short: "GenerateBinaries migration diffs", Long: "This tool is used to generate migration diff files for each of ignites scaffold commands", RunE: func(cmd *cobra.Command, args []string) error { + session := cliui.New() + defer session.End() + var ( from, _ = cmd.Flags().GetString(fromFlag) to, _ = cmd.Flags().GetString(toFlag) source, _ = cmd.Flags().GetString(sourceFlag) output, _ = cmd.Flags().GetString(outputFlag) ) - fromVer, err := semver.NewVersion(from) if err != nil && from != "" { return errors.Wrapf(err, "failed to parse from version %s", from) @@ -43,9 +45,6 @@ func NewRootCmd() *cobra.Command { return errors.Wrapf(err, "failed to parse to version %s", to) } - session := cliui.New() - defer session.End() - igniteRepo, err := repo.New(fromVer, toVer, session, repo.WithSource(source)) if err != nil { return err @@ -57,15 +56,15 @@ func NewRootCmd() *cobra.Command { return err } - sFrom := scaffold.New(fromBin, scaffold.DefaultCommands) - session.StartSpinner(fmt.Sprintf("Running scaffold commands for v%s...", fromVer.String())) - if err := sFrom.Run(fromVer, output); err != nil { + session.StartSpinner(fmt.Sprintf("Running scaffold commands for v%s...", igniteRepo.From.String())) + fromDir, err := scaffold.Run(fromBin, igniteRepo.From) + if err != nil { return err } - sTo := scaffold.New(toBin, scaffold.DefaultCommands) - session.StartSpinner(fmt.Sprintf("Running scaffold commands for v%s...", toVer.String())) - if err := sTo.Run(toVer, output); err != nil { + session.StartSpinner(fmt.Sprintf("Running scaffold commands for v%s...", igniteRepo.To.String())) + toDir, err := scaffold.Run(toBin, igniteRepo.To) + if err != nil { return err } diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go index 43767417f2..39ffb9b034 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go @@ -26,56 +26,56 @@ const ( type ( // Generator is used to generate migration diffs. Generator struct { - from, to *semver.Version + From, To *semver.Version tempDir, repoDir string repo *git.Repository session *cliui.Session } - // genOptions represents configuration for the generator. - genOptions struct { + // options represents configuration for the generator. + options struct { source string repoPath string repoURL string } - // GenOptions configures the generator. - GenOptions func(*genOptions) + // Options configures the generator. + Options func(*options) ) -// newGenOptions returns a genOptions with default options. -func newGenOptions() genOptions { - return genOptions{ +// newOptions returns a options with default options. +func newOptions() options { + return options{ source: "", repoPath: defaultRepoPath, repoURL: defaultRepoURL, } } -// WithSource set the repo source GenOptions. -func WithSource(source string) GenOptions { - return func(m *genOptions) { +// WithSource set the repo source Options. +func WithSource(source string) Options { + return func(m *options) { m.source = source } } -// WithRepoPath set the repo path GenOptions. -func WithRepoPath(repoPath string) GenOptions { - return func(m *genOptions) { +// WithRepoPath set the repo path Options. +func WithRepoPath(repoPath string) Options { + return func(m *options) { m.repoPath = repoPath } } -// WithRepoURL set the repo URL GenOptions. -func WithRepoURL(repoURL string) GenOptions { - return func(m *genOptions) { +// WithRepoURL set the repo URL Options. +func WithRepoURL(repoURL string) Options { + return func(m *options) { m.repoURL = repoURL } } // New creates a new generator for migration diffs between from and to versions of ignite cli // If source is empty, then it clones the ignite cli repository to a temporary directory and uses it as the source. -func New(from, to *semver.Version, session *cliui.Session, options ...GenOptions) (*Generator, error) { - opts := newGenOptions() +func New(from, to *semver.Version, session *cliui.Session, options ...Options) (*Generator, error) { + opts := newOptions() for _, apply := range options { apply(&opts) } @@ -121,8 +121,8 @@ func New(from, to *semver.Version, session *cliui.Session, options ...GenOptions } return &Generator{ - from: from, - to: to, + From: from, + To: to, tempDir: tempDir, repoDir: repoDir, repo: repo, @@ -224,13 +224,13 @@ func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collec } func (g *Generator) GenerateBinaries() (string, string, error) { - fromBinPath, err := g.buildIgniteCli(g.from) + fromBinPath, err := g.buildIgniteCli(g.From) if err != nil { - return "", "", errors.Wrapf(err, "failed to run scaffolds for 'FROM' version %s", g.from) + return "", "", errors.Wrapf(err, "failed to run scaffolds for 'FROM' version %s", g.From) } - toBinPath, err := g.buildIgniteCli(g.to) + toBinPath, err := g.buildIgniteCli(g.To) if err != nil { - return "", "", errors.Wrapf(err, "failed to run scaffolds for 'TO' version %s", g.to) + return "", "", errors.Wrapf(err, "failed to run scaffolds for 'TO' version %s", g.To) } return fromBinPath, toBinPath, nil } diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go new file mode 100644 index 0000000000..38820d4f3f --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go @@ -0,0 +1,55 @@ +package scaffold + +var DefaultCommands = Commands{ + "chain": Scaffold{ + Commands: []string{"chain example --no-module"}, + }, + "module": Scaffold{ + Prerequisites: []string{"chain"}, + Commands: []string{ + "module example --ibc", + }, + }, + "list": Scaffold{ + Prerequisites: []string{"module"}, + Commands: []string{ + "list list1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", + }, + }, + "map": Scaffold{ + Prerequisites: []string{"module"}, + Commands: []string{ + "map map1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --index i1:string --module example --yes", + }, + }, + "single": Scaffold{ + Prerequisites: []string{"module"}, + Commands: []string{ + "single single1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", + }, + }, + "type": Scaffold{ + Prerequisites: []string{"module"}, + Commands: []string{ + "type type1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", + }, + }, + "message": Scaffold{ + Prerequisites: []string{"module"}, + Commands: []string{ + "message message1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", + }, + }, + "query": Scaffold{ + Prerequisites: []string{"module"}, + Commands: []string{ + "query query1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints --module example --yes", + }, + }, + "packet": Scaffold{ + Prerequisites: []string{"module"}, + Commands: []string{ + "packet packet1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --ack f1:string,f2:strings,f3:bool,f4:int,f5:ints,f6:uint,f7:uints,f8:coin,f9:coins --module example --yes", + }, + }, +} diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go index 034f5b432c..6e7fee7b46 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go @@ -13,8 +13,8 @@ import ( ) type ( - // Command represents a set of commands and prerequisites scaffold commands that are required to run before them. - Command struct { + // Scaffold represents a set of commands and prerequisites scaffold commands that are required to run before them. + Scaffold struct { // Name is the unique identifier of the command Name string // Prerequisites is the names of commands that need to be run before this command set @@ -24,116 +24,102 @@ type ( Commands []string } - Scaffold struct { - ignitePath string - commands Commands - } + Commands = map[string]Scaffold +) - Commands = map[string]Command +type ( + // options represents configuration for the generator. + options struct { + cachePath string + output string + commands Commands + } + // Options configures the generator. + Options func(*options) ) -var DefaultCommands = Commands{ - "chain": Command{ - Commands: []string{"chain example --no-module"}, - }, - "module": Command{ - Prerequisites: []string{"chain"}, - Commands: []string{ - "module example --ibc", - }, - }, - "list": Command{ - Prerequisites: []string{"module"}, - Commands: []string{ - "list list1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", - }, - }, - "map": Command{ - Prerequisites: []string{"module"}, - Commands: []string{ - "map map1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --index i1:string --module example --yes", - }, - }, - "single": Command{ - Prerequisites: []string{"module"}, - Commands: []string{ - "single single1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", - }, - }, - "type": Command{ - Prerequisites: []string{"module"}, - Commands: []string{ - "type type1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", - }, - }, - "message": Command{ - Prerequisites: []string{"module"}, - Commands: []string{ - "message message1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", - }, - }, - "query": Command{ - Prerequisites: []string{"module"}, - Commands: []string{ - "query query1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints --module example --yes", - }, - }, - "packet": Command{ - Prerequisites: []string{"module"}, - Commands: []string{ - "packet packet1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --ack f1:string,f2:strings,f3:bool,f4:int,f5:ints,f6:uint,f7:uints,f8:coin,f9:coins --module example --yes", - }, - }, +// newOptions returns a options with default options. +func newOptions() options { + tmpDir := os.TempDir() + return options{ + cachePath: filepath.Join(tmpDir, "migration-cache"), + output: filepath.Join(tmpDir, "migration"), + commands: DefaultCommands, + } } -func New(ignitePath string, commands Commands) Scaffold { - return Scaffold{ - ignitePath: ignitePath, - commands: commands, +// WithOutput set the ignite scaffold output. +func WithOutput(output string) Options { + return func(m *options) { + m.output = output } } -func (s Scaffold) Run(ver *semver.Version, out string) error { - for _, c := range s.commands { - if err := s.runCommand(c.Name, c.Prerequisites, c.Commands, ver, out); err != nil { - return err +// WithCachePath set the ignite scaffold cache path. +func WithCachePath(cachePath string) Options { + return func(m *options) { + m.cachePath = cachePath + } +} + +// WithCommandList set the migration docs output. +func WithCommandList(commands Commands) Options { + return func(m *options) { + m.commands = commands + } +} + +func Run(binary string, ver *semver.Version, options ...Options) (string, error) { + opts := newOptions() + for _, apply := range options { + apply(&opts) + } + + output, err := filepath.Abs(opts.output) + if err != nil { + return "", err + } + output = filepath.Join(output, ver.Original()) + + for _, c := range opts.commands { + if err := runCommand(binary, output, c.Name, c.Prerequisites, c.Commands, ver, opts.commands); err != nil { + return "", err } - if err := applyPostScaffoldExceptions(ver, c.Name, out); err != nil { - return err + if err := applyPostScaffoldExceptions(ver, c.Name, output); err != nil { + return "", err } } - return nil + return output, nil } -func (s Scaffold) runCommand( - name string, - prerequisites []string, - cmds []string, +func runCommand( + binary, output, name string, + prerequisites, scaffoldCommands []string, ver *semver.Version, - out string, + commandList Commands, ) error { - // TODO add cache for duplicated commands. + // TODO add cache for duplicated scaffoldCommands. for _, p := range prerequisites { - c, ok := s.commands[p] + c, ok := commandList[p] if !ok { return errors.Errorf("command %s not found", name) } - if err := s.runCommand(name, c.Prerequisites, c.Commands, ver, out); err != nil { + if err := runCommand(binary, output, name, c.Prerequisites, c.Commands, ver, commandList); err != nil { return err } } - for _, cmd := range cmds { - if err := s.executeScaffold(ver, name, cmd, out); err != nil { + for _, cmd := range scaffoldCommands { + if err := executeScaffold(binary, name, cmd, output, ver); err != nil { return err } } return nil } -func (s Scaffold) executeScaffold(ver *semver.Version, name, cmd string, out string) error { - args := append([]string{s.ignitePath, "scaffold"}, strings.Fields(cmd)...) - args = append(args, "--path", filepath.Join(out, name)) +func executeScaffold(binary, name, cmd, output string, ver *semver.Version) error { + args := append([]string{binary, "scaffold"}, strings.Fields(cmd)...) + args = append(args, "--path", filepath.Join(output, name)) args = applyPreExecuteExceptions(ver, args) if err := exec.Exec(context.Background(), args); err != nil { @@ -153,19 +139,19 @@ func applyPreExecuteExceptions(ver *semver.Version, args []string) []string { } // In this function we can manipulate the output of scaffold commands after they have been executed in order to compensate for differences in versions. -func applyPostScaffoldExceptions(ver *semver.Version, name string, out string) error { +func applyPostScaffoldExceptions(ver *semver.Version, name string, output string) error { // In versions <0.27.0, "scaffold chain" command always creates a new directory with the name of chain at the given --path // so we need to move the directory to the parent directory. if ver.LessThan(semver.MustParse("v0.27.0")) { - if err := os.Rename(filepath.Join(out, name, "example"), filepath.Join(out, "example_tmp")); err != nil { + if err := os.Rename(filepath.Join(output, name, "example"), filepath.Join(output, "example_tmp")); err != nil { return errors.Wrapf(err, "failed to move %s directory to tmp directory", name) } - if err := os.RemoveAll(filepath.Join(out, name)); err != nil { + if err := os.RemoveAll(filepath.Join(output, name)); err != nil { return errors.Wrapf(err, "failed to remove %s directory", name) } - if err := os.Rename(filepath.Join(out, "example_tmp"), filepath.Join(out, name)); err != nil { + if err := os.Rename(filepath.Join(output, "example_tmp"), filepath.Join(output, name)); err != nil { return errors.Wrapf(err, "failed to move tmp directory to %s directory", name) } } From 33e64c2fb961294f784284ebd195326dd77f5770 Mon Sep 17 00:00:00 2001 From: Pantani Date: Wed, 28 Feb 2024 22:17:39 -0300 Subject: [PATCH 37/69] add pkg options --- .../internal/tools/gen-mig-diffs/cmd/root.go | 63 +++++++--- .../tools/gen-mig-diffs/pkg/diff/diff.go | 11 +- .../tools/gen-mig-diffs/pkg/repo/repo.go | 113 +++++++++++------- .../gen-mig-diffs/pkg/scaffold/commands.go | 2 +- .../gen-mig-diffs/pkg/scaffold/scaffold.go | 29 +++-- 5 files changed, 144 insertions(+), 74 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 47883d3684..b32fb9e829 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -14,10 +14,15 @@ import ( ) const ( - fromFlag = "from" - toFlag = "to" - sourceFlag = "source" - outputFlag = "output" + flagFrom = "from" + flagTo = "to" + flagOutput = "output" + flagSource = "repo-source" + flagRepoURL = "repo-url" + flagRepoOutput = "repo-output" + flagRepoCleanup = "repo-cleanup" + flagScaffoldOutput = "scaffold-output" + flagScaffoldCache = "scaffold-cache" ) // NewRootCmd creates a new root command. @@ -31,10 +36,15 @@ func NewRootCmd() *cobra.Command { defer session.End() var ( - from, _ = cmd.Flags().GetString(fromFlag) - to, _ = cmd.Flags().GetString(toFlag) - source, _ = cmd.Flags().GetString(sourceFlag) - output, _ = cmd.Flags().GetString(outputFlag) + from, _ = cmd.Flags().GetString(flagFrom) + to, _ = cmd.Flags().GetString(flagTo) + source, _ = cmd.Flags().GetString(flagSource) + output, _ = cmd.Flags().GetString(flagOutput) + repoURL, _ = cmd.Flags().GetString(flagRepoURL) + repoOutput, _ = cmd.Flags().GetString(flagRepoOutput) + repoCleanup, _ = cmd.Flags().GetBool(flagRepoCleanup) + scaffoldOutput, _ = cmd.Flags().GetString(flagScaffoldOutput) + scaffoldCache, _ = cmd.Flags().GetString(flagScaffoldCache) ) fromVer, err := semver.NewVersion(from) if err != nil && from != "" { @@ -45,7 +55,17 @@ func NewRootCmd() *cobra.Command { return errors.Wrapf(err, "failed to parse to version %s", to) } - igniteRepo, err := repo.New(fromVer, toVer, session, repo.WithSource(source)) + repoOptions := []repo.Options{repo.WithSource(source)} + if repoURL != "" { + repoOptions = append(repoOptions, repo.WithRepoURL(repoURL)) + } + if repoOutput != "" { + repoOptions = append(repoOptions, repo.WithRepoOutput(repoOutput)) + } + if repoCleanup { + repoOptions = append(repoOptions, repo.WithCleanup()) + } + igniteRepo, err := repo.New(fromVer, toVer, session, repoOptions...) if err != nil { return err } @@ -56,14 +76,22 @@ func NewRootCmd() *cobra.Command { return err } + scaffoldOptions := make([]scaffold.Options, 0) + if scaffoldOutput != "" { + scaffoldOptions = append(scaffoldOptions, scaffold.WithOutput(scaffoldOutput)) + } + if scaffoldCache != "" { + scaffoldOptions = append(scaffoldOptions, scaffold.WithCachePath(scaffoldCache)) + } + session.StartSpinner(fmt.Sprintf("Running scaffold commands for v%s...", igniteRepo.From.String())) - fromDir, err := scaffold.Run(fromBin, igniteRepo.From) + fromDir, err := scaffold.Run(fromBin, igniteRepo.From, scaffoldOptions...) if err != nil { return err } session.StartSpinner(fmt.Sprintf("Running scaffold commands for v%s...", igniteRepo.To.String())) - toDir, err := scaffold.Run(toBin, igniteRepo.To) + toDir, err := scaffold.Run(toBin, igniteRepo.To, scaffoldOptions...) if err != nil { return err } @@ -88,10 +116,15 @@ func NewRootCmd() *cobra.Command { }, } - cmd.Flags().StringP(fromFlag, "f", "", "Version of ignite or path to ignite source code to generate the diff from") - cmd.Flags().StringP(toFlag, "t", "", "Version of ignite or path to ignite source code to generate the diff to") - cmd.Flags().StringP(sourceFlag, "s", "", "Path to ignite source code repository (optional)") - cmd.Flags().StringP(outputFlag, "o", "./diffs", "Output directory to save the migration diff files") + cmd.Flags().StringP(flagFrom, "f", "", "Version of ignite or path to ignite source code to generate the diff from") + cmd.Flags().StringP(flagTo, "t", "", "Version of ignite or path to ignite source code to generate the diff to") + cmd.Flags().StringP(flagOutput, "o", "./diffs", "Output directory to save the migration diff files") + cmd.Flags().StringP(flagSource, "s", "", "Path to ignite source code repository (optional)") + cmd.Flags().String(flagRepoURL, "", "Git URL for the Ignite repository") + cmd.Flags().String(flagRepoOutput, "", "Output path to clone the ignite repository") + cmd.Flags().Bool(flagRepoCleanup, true, "Cleanup the repository path after use") + cmd.Flags().String(flagScaffoldOutput, "", "Output path to clone the ignite repository") + cmd.Flags().String(flagScaffoldCache, "", "Output path to clone the ignite repository") return cmd } diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go index 8007776317..2dbec5fb2e 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go @@ -10,6 +10,8 @@ import ( "github.com/ignite/cli/v28/ignite/pkg/diff" ) +type Diffs map[string][]gotextdiff.Unified + var diffIgnoreGlobs = []string{ ".git/**", "**.md", @@ -29,7 +31,7 @@ var diffIgnoreGlobs = []string{ "**.json", } -func CalculateDiffs(fromDir, toDir string) (map[string][]gotextdiff.Unified, error) { +func CalculateDiffs(fromDir, toDir string) (Diffs, error) { paths := make([]string, 0) err := filepath.Walk(fromDir, func(path string, info os.FileInfo, err error) error { if err == nil && info.IsDir() && path != fromDir { @@ -41,7 +43,7 @@ func CalculateDiffs(fromDir, toDir string) (map[string][]gotextdiff.Unified, err return nil, err } - diffs := make(map[string][]gotextdiff.Unified) + diffs := make(Diffs) for _, s := range paths { name := filepath.Base(s) from := filepath.Join(fromDir, name) @@ -68,7 +70,7 @@ func CalculateDiffs(fromDir, toDir string) (map[string][]gotextdiff.Unified, err } // subtractBaseDiffs removes chain and module diffs from other diffs. -func subtractBaseDiffs(diffs map[string][]gotextdiff.Unified) map[string][]gotextdiff.Unified { +func subtractBaseDiffs(diffs Diffs) Diffs { chainDiff := diffs["chain"] moduleDiff := diffs["module"] for name, d := range diffs { @@ -91,7 +93,8 @@ func subtractUnifieds(a, b []gotextdiff.Unified) []gotextdiff.Unified { return a } -func SaveDiffs(diffs map[string][]gotextdiff.Unified, outputPath string) error { +// SaveDiffs save all migration diffs to the output path. +func SaveDiffs(diffs Diffs, outputPath string) error { if err := os.MkdirAll(outputPath, os.ModePerm); err != nil { return err } diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go index 39ffb9b034..644e703151 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go @@ -19,24 +19,25 @@ import ( const ( defaultRepoURL = "https://github.com/ignite/cli.git" - defaultRepoPath = "src/github.com/ignite/cli" defaultBinaryPath = "dist/ignite" ) type ( // Generator is used to generate migration diffs. Generator struct { - From, To *semver.Version - tempDir, repoDir string - repo *git.Repository - session *cliui.Session + From, To *semver.Version + source string + repo *git.Repository + session *cliui.Session + cleanup bool } // options represents configuration for the generator. options struct { - source string - repoPath string - repoURL string + source string + output string + repoURL string + cleanup bool } // Options configures the generator. Options func(*options) @@ -44,34 +45,55 @@ type ( // newOptions returns a options with default options. func newOptions() options { + tmpDir := os.TempDir() return options{ - source: "", - repoPath: defaultRepoPath, - repoURL: defaultRepoURL, + source: "", + output: filepath.Join(tmpDir, "migration-source"), + repoURL: defaultRepoURL, } } // WithSource set the repo source Options. func WithSource(source string) Options { - return func(m *options) { - m.source = source + return func(o *options) { + o.source = source + // Do not clean up if set the source. + o.cleanup = false } } -// WithRepoPath set the repo path Options. -func WithRepoPath(repoPath string) Options { - return func(m *options) { - m.repoPath = repoPath +// WithRepoURL set the repo URL Options. +func WithRepoURL(repoURL string) Options { + return func(o *options) { + o.repoURL = repoURL } } -// WithRepoURL set the repo URL Options. -func WithRepoURL(repoURL string) Options { - return func(m *options) { - m.repoURL = repoURL +// WithRepoOutput set the repo output Options. +func WithRepoOutput(output string) Options { + return func(o *options) { + o.output = output } } +// WithCleanup cleanup folders after use. +func WithCleanup() Options { + return func(o *options) { + o.cleanup = true + } +} + +// validate options +func (o options) validate() error { + if o.source != "" && (o.repoURL != defaultRepoURL) { + return errors.New("cannot set source and repo URL at the same time") + } + if o.source != "" && o.cleanup { + return errors.New("cannot set source and cleanup the repo") + } + return nil +} + // New creates a new generator for migration diffs between from and to versions of ignite cli // If source is empty, then it clones the ignite cli repository to a temporary directory and uses it as the source. func New(from, to *semver.Version, session *cliui.Session, options ...Options) (*Generator, error) { @@ -79,38 +101,47 @@ func New(from, to *semver.Version, session *cliui.Session, options ...Options) ( for _, apply := range options { apply(&opts) } + if err := opts.validate(); err != nil { + return nil, err + } tempDir, err := os.MkdirTemp("", ".migdoc") if err != nil { return nil, errors.Wrap(err, "failed to create temporary directory") } + + session.StopSpinner() session.EventBus().SendInfo(fmt.Sprintf("Created temporary directory: %s", tempDir)) var ( - repoDir = opts.source - repo *git.Repository + source = opts.source + repo *git.Repository ) - if repoDir != "" { - repo, err = git.PlainOpen(repoDir) + if source != "" { + repo, err = git.PlainOpen(source) if err != nil { return nil, errors.Wrap(err, "failed to open ignite repository") } - session.EventBus().SendInfo(fmt.Sprintf("Using ignite repository at: %s", repoDir)) + session.EventBus().SendInfo(fmt.Sprintf("Using ignite repository at: %s", source)) } else { session.StartSpinner("Cloning ignite repository...") - repoDir = filepath.Join(tempDir, opts.repoPath) - repo, err = git.PlainClone(repoDir, false, &git.CloneOptions{URL: opts.repoURL}) + source = opts.output + if err := os.RemoveAll(source); err != nil { + return nil, errors.Wrap(err, "failed to clean the output directory") + } + + repo, err = git.PlainClone(source, false, &git.CloneOptions{URL: opts.repoURL, Depth: 1}) if err != nil { return nil, errors.Wrap(err, "failed to clone ignite repository") } session.StopSpinner() - session.EventBus().SendInfo(fmt.Sprintf("Cloned ignite repository to: %s", repoDir)) + session.EventBus().SendInfo(fmt.Sprintf("Cloned ignite repository to: %s", source)) } - versions, err := getRepoVersionTags(repoDir) + versions, err := getRepoVersionTags(source) if err != nil { return nil, err } @@ -123,8 +154,7 @@ func New(from, to *semver.Version, session *cliui.Session, options ...Options) ( return &Generator{ From: from, To: to, - tempDir: tempDir, - repoDir: repoDir, + source: source, repo: repo, session: session, }, nil @@ -167,13 +197,14 @@ func getRepoVersionTags(repoDir string) (semver.Collection, error) { // Cleanup cleanup all temporary directories. func (g *Generator) Cleanup() { - err := os.RemoveAll(g.tempDir) - if err != nil { + if !g.cleanup { + return + } + if err := os.RemoveAll(g.source); err != nil { g.session.EventBus().SendError(err) return } - - g.session.EventBus().SendInfo(fmt.Sprintf("Removed temporary directory: %s", g.tempDir)) + g.session.EventBus().SendInfo(fmt.Sprintf("Removed temporary directory: %s", g.source)) } // validateVersionRange checks if the provided fromVer and toVer exist in the versions and if any of them is nil, then it picks default values. @@ -243,12 +274,12 @@ func (g *Generator) buildIgniteCli(ver *semver.Version) (string, error) { return "", err } - err := exec.Exec(context.Background(), []string{"make", "build"}, exec.StepOption(step.Workdir(g.repoDir))) + err := exec.Exec(context.Background(), []string{"make", "build"}, exec.StepOption(step.Workdir(g.source))) if err != nil { return "", errors.Wrap(err, "failed to build ignite cli using make build") } - binPath := filepath.Join(g.repoDir, defaultBinaryPath) + binPath := filepath.Join(g.source, defaultBinaryPath) g.session.StopSpinner() g.session.EventBus().SendInfo(fmt.Sprintf("Built ignite cli for v%s", ver)) @@ -265,15 +296,13 @@ func (g *Generator) checkoutToTag(tag string) error { // Reset and clean the git directory before the checkout to avoid conflicts. if err := wt.Reset(&git.ResetOptions{Mode: git.HardReset}); err != nil { - return errors.Wrapf(err, "failed to reset %s", g.repoDir) + return errors.Wrapf(err, "failed to reset %s", g.source) } if err := wt.Clean(&git.CleanOptions{Dir: true}); err != nil { - return errors.Wrapf(err, "failed to reset %s", g.repoDir) + return errors.Wrapf(err, "failed to reset %s", g.source) } - if err = wt.Checkout(&git.CheckoutOptions{Branch: plumbing.NewTagReferenceName(tag)}); err != nil { return errors.Wrapf(err, "failed to checkout tag %s", tag) } - return nil } diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go index 38820d4f3f..837de4212a 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go @@ -1,6 +1,6 @@ package scaffold -var DefaultCommands = Commands{ +var defaultCommands = Commands{ "chain": Scaffold{ Commands: []string{"chain example --no-module"}, }, diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go index 6e7fee7b46..973c1075f6 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go @@ -12,6 +12,8 @@ import ( "github.com/ignite/cli/v28/ignite/pkg/errors" ) +var v027 = semver.MustParse("v0.27.0") + type ( // Scaffold represents a set of commands and prerequisites scaffold commands that are required to run before them. Scaffold struct { @@ -24,7 +26,7 @@ type ( Commands []string } - Commands = map[string]Scaffold + Commands map[string]Scaffold ) type ( @@ -44,31 +46,32 @@ func newOptions() options { return options{ cachePath: filepath.Join(tmpDir, "migration-cache"), output: filepath.Join(tmpDir, "migration"), - commands: DefaultCommands, + commands: defaultCommands, } } // WithOutput set the ignite scaffold output. func WithOutput(output string) Options { - return func(m *options) { - m.output = output + return func(o *options) { + o.output = output } } // WithCachePath set the ignite scaffold cache path. func WithCachePath(cachePath string) Options { - return func(m *options) { - m.cachePath = cachePath + return func(o *options) { + o.cachePath = cachePath } } // WithCommandList set the migration docs output. func WithCommandList(commands Commands) Options { - return func(m *options) { - m.commands = commands + return func(o *options) { + o.commands = commands } } +// Run execute the scaffold commands based in the binary semantic version. func Run(binary string, ver *semver.Version, options ...Options) (string, error) { opts := newOptions() for _, apply := range options { @@ -128,21 +131,23 @@ func executeScaffold(binary, name, cmd, output string, ver *semver.Version) erro return nil } -// In this function we can manipulate command arguments before executing it in order to compensate for differences in versions. +// applyPreExecuteExceptions this function we can manipulate command arguments before executing it in +// order to compensate for differences in versions. func applyPreExecuteExceptions(ver *semver.Version, args []string) []string { // In versions <0.27.0, "scaffold chain" command always creates a new directory with the name of chain at the given --path // so we need to append "example" to the path if the command is not "chain" - if ver.LessThan(semver.MustParse("v0.27.0")) && args[2] != "chain" { + if ver.LessThan(v027) && args[2] != "chain" { args[len(args)-1] = filepath.Join(args[len(args)-1], "example") } return args } -// In this function we can manipulate the output of scaffold commands after they have been executed in order to compensate for differences in versions. +// applyPostScaffoldExceptions this function we can manipulate the output of scaffold commands after +// they have been executed in order to compensate for differences in versions. func applyPostScaffoldExceptions(ver *semver.Version, name string, output string) error { // In versions <0.27.0, "scaffold chain" command always creates a new directory with the name of chain at the given --path // so we need to move the directory to the parent directory. - if ver.LessThan(semver.MustParse("v0.27.0")) { + if ver.LessThan(v027) { if err := os.Rename(filepath.Join(output, name, "example"), filepath.Join(output, "example_tmp")); err != nil { return errors.Wrapf(err, "failed to move %s directory to tmp directory", name) } From cd9e9170901ba5f6f8d1663fe3579f55052cf7b9 Mon Sep 17 00:00:00 2001 From: Pantani Date: Wed, 28 Feb 2024 23:52:49 -0300 Subject: [PATCH 38/69] pass the context to the commands --- .../internal/tools/gen-mig-diffs/cmd/root.go | 26 +++++++++++-------- .../tools/gen-mig-diffs/pkg/repo/repo.go | 12 ++++----- .../gen-mig-diffs/pkg/scaffold/commands.go | 4 +-- .../gen-mig-diffs/pkg/scaffold/scaffold.go | 24 ++++++++--------- 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index b32fb9e829..6fde6fdf86 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -38,7 +38,7 @@ func NewRootCmd() *cobra.Command { var ( from, _ = cmd.Flags().GetString(flagFrom) to, _ = cmd.Flags().GetString(flagTo) - source, _ = cmd.Flags().GetString(flagSource) + repoSource, _ = cmd.Flags().GetString(flagSource) output, _ = cmd.Flags().GetString(flagOutput) repoURL, _ = cmd.Flags().GetString(flagRepoURL) repoOutput, _ = cmd.Flags().GetString(flagRepoOutput) @@ -55,23 +55,27 @@ func NewRootCmd() *cobra.Command { return errors.Wrapf(err, "failed to parse to version %s", to) } - repoOptions := []repo.Options{repo.WithSource(source)} + repoOptions := make([]repo.Options, 0) + if repoCleanup { + repoOptions = append(repoOptions, repo.WithCleanup()) + } + if repoSource != "" { + repoOptions = append(repoOptions, repo.WithSource(repoSource)) + } if repoURL != "" { repoOptions = append(repoOptions, repo.WithRepoURL(repoURL)) } if repoOutput != "" { repoOptions = append(repoOptions, repo.WithRepoOutput(repoOutput)) } - if repoCleanup { - repoOptions = append(repoOptions, repo.WithCleanup()) - } + igniteRepo, err := repo.New(fromVer, toVer, session, repoOptions...) if err != nil { return err } defer igniteRepo.Cleanup() - fromBin, toBin, err := igniteRepo.GenerateBinaries() + fromBin, toBin, err := igniteRepo.GenerateBinaries(cmd.Context()) if err != nil { return err } @@ -84,14 +88,14 @@ func NewRootCmd() *cobra.Command { scaffoldOptions = append(scaffoldOptions, scaffold.WithCachePath(scaffoldCache)) } - session.StartSpinner(fmt.Sprintf("Running scaffold commands for v%s...", igniteRepo.From.String())) - fromDir, err := scaffold.Run(fromBin, igniteRepo.From, scaffoldOptions...) + session.StartSpinner(fmt.Sprintf("Running scaffold commands for %s...", igniteRepo.From.Original())) + fromDir, err := scaffold.Run(cmd.Context(), fromBin, igniteRepo.From, scaffoldOptions...) if err != nil { return err } - session.StartSpinner(fmt.Sprintf("Running scaffold commands for v%s...", igniteRepo.To.String())) - toDir, err := scaffold.Run(toBin, igniteRepo.To, scaffoldOptions...) + session.StartSpinner(fmt.Sprintf("Running scaffold commands for %s...", igniteRepo.To.Original())) + toDir, err := scaffold.Run(cmd.Context(), toBin, igniteRepo.To, scaffoldOptions...) if err != nil { return err } @@ -119,7 +123,7 @@ func NewRootCmd() *cobra.Command { cmd.Flags().StringP(flagFrom, "f", "", "Version of ignite or path to ignite source code to generate the diff from") cmd.Flags().StringP(flagTo, "t", "", "Version of ignite or path to ignite source code to generate the diff to") cmd.Flags().StringP(flagOutput, "o", "./diffs", "Output directory to save the migration diff files") - cmd.Flags().StringP(flagSource, "s", "", "Path to ignite source code repository (optional)") + cmd.Flags().StringP(flagSource, "s", "", "Path to ignite source code repository. Set the source automatically set the cleanup to false") cmd.Flags().String(flagRepoURL, "", "Git URL for the Ignite repository") cmd.Flags().String(flagRepoOutput, "", "Output path to clone the ignite repository") cmd.Flags().Bool(flagRepoCleanup, true, "Cleanup the repository path after use") diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go index 644e703151..ef93201874 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go @@ -254,12 +254,12 @@ func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collec return fromVer, toVer, nil } -func (g *Generator) GenerateBinaries() (string, string, error) { - fromBinPath, err := g.buildIgniteCli(g.From) +func (g *Generator) GenerateBinaries(ctx context.Context) (string, string, error) { + fromBinPath, err := g.buildIgniteCli(ctx, g.From) if err != nil { return "", "", errors.Wrapf(err, "failed to run scaffolds for 'FROM' version %s", g.From) } - toBinPath, err := g.buildIgniteCli(g.To) + toBinPath, err := g.buildIgniteCli(ctx, g.To) if err != nil { return "", "", errors.Wrapf(err, "failed to run scaffolds for 'TO' version %s", g.To) } @@ -267,14 +267,14 @@ func (g *Generator) GenerateBinaries() (string, string, error) { } // buildIgniteCli build the ignite CLI from version. -func (g *Generator) buildIgniteCli(ver *semver.Version) (string, error) { +func (g *Generator) buildIgniteCli(ctx context.Context, ver *semver.Version) (string, error) { g.session.StartSpinner(fmt.Sprintf("Building binary for version v%s...", ver)) if err := g.checkoutToTag(ver.Original()); err != nil { return "", err } - err := exec.Exec(context.Background(), []string{"make", "build"}, exec.StepOption(step.Workdir(g.source))) + err := exec.Exec(ctx, []string{"make", "build"}, exec.StepOption(step.Workdir(g.source))) if err != nil { return "", errors.Wrap(err, "failed to build ignite cli using make build") } @@ -282,7 +282,7 @@ func (g *Generator) buildIgniteCli(ver *semver.Version) (string, error) { binPath := filepath.Join(g.source, defaultBinaryPath) g.session.StopSpinner() - g.session.EventBus().SendInfo(fmt.Sprintf("Built ignite cli for v%s", ver)) + g.session.EventBus().SendInfo(fmt.Sprintf("Built ignite cli for %s", ver.Original())) return binPath, nil } diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go index 837de4212a..aad29d2b03 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go @@ -6,9 +6,7 @@ var defaultCommands = Commands{ }, "module": Scaffold{ Prerequisites: []string{"chain"}, - Commands: []string{ - "module example --ibc", - }, + Commands: []string{"module example --ibc"}, }, "list": Scaffold{ Prerequisites: []string{"module"}, diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go index 973c1075f6..297e2491a3 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go @@ -72,7 +72,7 @@ func WithCommandList(commands Commands) Options { } // Run execute the scaffold commands based in the binary semantic version. -func Run(binary string, ver *semver.Version, options ...Options) (string, error) { +func Run(ctx context.Context, binary string, ver *semver.Version, options ...Options) (string, error) { opts := newOptions() for _, apply := range options { apply(&opts) @@ -85,7 +85,7 @@ func Run(binary string, ver *semver.Version, options ...Options) (string, error) output = filepath.Join(output, ver.Original()) for _, c := range opts.commands { - if err := runCommand(binary, output, c.Name, c.Prerequisites, c.Commands, ver, opts.commands); err != nil { + if err := runCommand(ctx, binary, output, c.Name, c.Prerequisites, c.Commands, ver, opts.commands); err != nil { return "", err } if err := applyPostScaffoldExceptions(ver, c.Name, output); err != nil { @@ -96,6 +96,7 @@ func Run(binary string, ver *semver.Version, options ...Options) (string, error) } func runCommand( + ctx context.Context, binary, output, name string, prerequisites, scaffoldCommands []string, ver *semver.Version, @@ -107,25 +108,25 @@ func runCommand( if !ok { return errors.Errorf("command %s not found", name) } - if err := runCommand(binary, output, name, c.Prerequisites, c.Commands, ver, commandList); err != nil { + if err := runCommand(ctx, binary, output, name, c.Prerequisites, c.Commands, ver, commandList); err != nil { return err } } for _, cmd := range scaffoldCommands { - if err := executeScaffold(binary, name, cmd, output, ver); err != nil { + if err := executeScaffold(ctx, binary, name, cmd, output, ver); err != nil { return err } } return nil } -func executeScaffold(binary, name, cmd, output string, ver *semver.Version) error { +func executeScaffold(ctx context.Context, binary, name, cmd, output string, ver *semver.Version) error { args := append([]string{binary, "scaffold"}, strings.Fields(cmd)...) args = append(args, "--path", filepath.Join(output, name)) args = applyPreExecuteExceptions(ver, args) - if err := exec.Exec(context.Background(), args); err != nil { + if err := exec.Exec(ctx, args); err != nil { return errors.Wrapf(err, "failed to execute ignite scaffold command: %s", cmd) } return nil @@ -134,8 +135,9 @@ func executeScaffold(binary, name, cmd, output string, ver *semver.Version) erro // applyPreExecuteExceptions this function we can manipulate command arguments before executing it in // order to compensate for differences in versions. func applyPreExecuteExceptions(ver *semver.Version, args []string) []string { - // In versions <0.27.0, "scaffold chain" command always creates a new directory with the name of chain at the given --path - // so we need to append "example" to the path if the command is not "chain" + // In versions <0.27.0, "scaffold chain" command always creates a new directory with the + // name of chain at the given --path so we need to append "example" to the path if the + // command is not "chain". if ver.LessThan(v027) && args[2] != "chain" { args[len(args)-1] = filepath.Join(args[len(args)-1], "example") } @@ -145,17 +147,15 @@ func applyPreExecuteExceptions(ver *semver.Version, args []string) []string { // applyPostScaffoldExceptions this function we can manipulate the output of scaffold commands after // they have been executed in order to compensate for differences in versions. func applyPostScaffoldExceptions(ver *semver.Version, name string, output string) error { - // In versions <0.27.0, "scaffold chain" command always creates a new directory with the name of chain at the given --path - // so we need to move the directory to the parent directory. + // In versions <0.27.0, "scaffold chain" command always creates a new directory with the name of + // chain at the given --path so we need to move the directory to the parent directory. if ver.LessThan(v027) { if err := os.Rename(filepath.Join(output, name, "example"), filepath.Join(output, "example_tmp")); err != nil { return errors.Wrapf(err, "failed to move %s directory to tmp directory", name) } - if err := os.RemoveAll(filepath.Join(output, name)); err != nil { return errors.Wrapf(err, "failed to remove %s directory", name) } - if err := os.Rename(filepath.Join(output, "example_tmp"), filepath.Join(output, name)); err != nil { return errors.Wrapf(err, "failed to move tmp directory to %s directory", name) } From 9b2f891f820a60e52d3eb1ea50d1139056e839f9 Mon Sep 17 00:00:00 2001 From: Pantani Date: Thu, 29 Feb 2024 00:10:04 -0300 Subject: [PATCH 39/69] add cache file --- .../tools/gen-mig-diffs/pkg/scaffold/cache.go | 91 +++++++++++++++++++ .../gen-mig-diffs/pkg/scaffold/scaffold.go | 6 +- 2 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go new file mode 100644 index 0000000000..5652c40526 --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go @@ -0,0 +1,91 @@ +package scaffold + +import ( + "io" + "os" + "path/filepath" + "sync" +) + +// cache represents a cache for executed scaffold commands. +type cache struct { + cachePath string + cachesPath map[string]string + mu sync.RWMutex +} + +// newCache initializes a new Cache instance. +func newCache(path string) *cache { + return &cache{ + cachePath: path, + cachesPath: make(map[string]string), + } +} + +// saveCache save a new cache +func (c *cache) saveCache(name, path string) error { + c.mu.Lock() + defer c.mu.Unlock() + + cachePath := filepath.Join(path, name) + // Walk through the original path and copy all content to the cache path. + err := filepath.Walk(path, func(srcPath string, info os.FileInfo, err error) error { + if err != nil { + return err + } + relPath, err := filepath.Rel(path, srcPath) + if err != nil { + return err + } + dstPath := filepath.Join(cachePath, relPath) + if info.IsDir() { + return os.MkdirAll(dstPath, info.Mode()) + } + srcFile, err := os.Open(srcPath) + if err != nil { + return err + } + defer srcFile.Close() + dstFile, err := os.Create(dstPath) + if err != nil { + return err + } + defer dstFile.Close() + _, err = io.Copy(dstFile, srcFile) + return err + }) + if err != nil { + return err + } + + c.cachesPath[name] = cachePath + return nil +} + +// cacheExist checks if a cache path exist. +func (c *cache) cacheExist(name string) bool { + c.mu.RLock() + defer c.mu.RUnlock() + cachePath, ok := c.cachesPath[name] + if !ok { + return false + } + if _, err := os.Stat(cachePath); os.IsNotExist(err) { + return false + } + return true +} + +// get return the cache path +func (c *cache) get(name string) (string, bool) { + c.mu.RLock() + defer c.mu.RUnlock() + cachePath, ok := c.cachesPath[name] + if !ok { + return "", false + } + if _, err := os.Stat(cachePath); os.IsNotExist(err) { + return "", false + } + return cachePath, true +} diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go index 297e2491a3..37b17d504b 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go @@ -78,6 +78,7 @@ func Run(ctx context.Context, binary string, ver *semver.Version, options ...Opt apply(&opts) } + cache := newCache(opts.cachePath) output, err := filepath.Abs(opts.output) if err != nil { return "", err @@ -85,7 +86,7 @@ func Run(ctx context.Context, binary string, ver *semver.Version, options ...Opt output = filepath.Join(output, ver.Original()) for _, c := range opts.commands { - if err := runCommand(ctx, binary, output, c.Name, c.Prerequisites, c.Commands, ver, opts.commands); err != nil { + if err := runCommand(ctx, cache, binary, output, c.Name, c.Prerequisites, c.Commands, ver, opts.commands); err != nil { return "", err } if err := applyPostScaffoldExceptions(ver, c.Name, output); err != nil { @@ -97,6 +98,7 @@ func Run(ctx context.Context, binary string, ver *semver.Version, options ...Opt func runCommand( ctx context.Context, + cache *cache, binary, output, name string, prerequisites, scaffoldCommands []string, ver *semver.Version, @@ -108,7 +110,7 @@ func runCommand( if !ok { return errors.Errorf("command %s not found", name) } - if err := runCommand(ctx, binary, output, name, c.Prerequisites, c.Commands, ver, commandList); err != nil { + if err := runCommand(ctx, cache, binary, output, name, c.Prerequisites, c.Commands, ver, commandList); err != nil { return err } } From 381a16a652990a5785af125e7fa373ae10e4b5c7 Mon Sep 17 00:00:00 2001 From: Pantani Date: Thu, 29 Feb 2024 00:25:34 -0300 Subject: [PATCH 40/69] create Scaffold struct --- .../internal/tools/gen-mig-diffs/cmd/root.go | 12 ++- .../tools/gen-mig-diffs/pkg/scaffold/cache.go | 16 +--- .../gen-mig-diffs/pkg/scaffold/commands.go | 18 ++--- .../gen-mig-diffs/pkg/scaffold/scaffold.go | 79 +++++++++++-------- 4 files changed, 66 insertions(+), 59 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 6fde6fdf86..36211b642d 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -89,22 +89,28 @@ func NewRootCmd() *cobra.Command { } session.StartSpinner(fmt.Sprintf("Running scaffold commands for %s...", igniteRepo.From.Original())) - fromDir, err := scaffold.Run(cmd.Context(), fromBin, igniteRepo.From, scaffoldOptions...) + sFrom, err := scaffold.New(fromBin, igniteRepo.From, scaffoldOptions...) if err != nil { return err } + if err := sFrom.Run(cmd.Context()); err != nil { + return err + } session.StartSpinner(fmt.Sprintf("Running scaffold commands for %s...", igniteRepo.To.Original())) - toDir, err := scaffold.Run(cmd.Context(), toBin, igniteRepo.To, scaffoldOptions...) + sTo, err := scaffold.New(toBin, igniteRepo.To, scaffoldOptions...) if err != nil { return err } + if err := sTo.Run(cmd.Context()); err != nil { + return err + } session.StopSpinner() session.EventBus().SendInfo(fmt.Sprintf("Scaffolded code for commands at %s", output)) session.StartSpinner("Calculating diff...") - diffs, err := diff.CalculateDiffs(fromDir, toDir) + diffs, err := diff.CalculateDiffs(sFrom.Output, sTo.Output) if err != nil { return errors.Wrap(err, "failed to calculate diff") } diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go index 5652c40526..bba57a7a5d 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go @@ -7,7 +7,7 @@ import ( "sync" ) -// cache represents a cache for executed scaffold commands. +// cache represents a cache for executed scaffold commandList. type cache struct { cachePath string cachesPath map[string]string @@ -62,20 +62,6 @@ func (c *cache) saveCache(name, path string) error { return nil } -// cacheExist checks if a cache path exist. -func (c *cache) cacheExist(name string) bool { - c.mu.RLock() - defer c.mu.RUnlock() - cachePath, ok := c.cachesPath[name] - if !ok { - return false - } - if _, err := os.Stat(cachePath); os.IsNotExist(err) { - return false - } - return true -} - // get return the cache path func (c *cache) get(name string) (string, bool) { c.mu.RLock() diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go index aad29d2b03..4439dc212d 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go @@ -1,50 +1,50 @@ package scaffold var defaultCommands = Commands{ - "chain": Scaffold{ + "chain": Command{ Commands: []string{"chain example --no-module"}, }, - "module": Scaffold{ + "module": Command{ Prerequisites: []string{"chain"}, Commands: []string{"module example --ibc"}, }, - "list": Scaffold{ + "list": Command{ Prerequisites: []string{"module"}, Commands: []string{ "list list1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, }, - "map": Scaffold{ + "map": Command{ Prerequisites: []string{"module"}, Commands: []string{ "map map1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --index i1:string --module example --yes", }, }, - "single": Scaffold{ + "single": Command{ Prerequisites: []string{"module"}, Commands: []string{ "single single1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, }, - "type": Scaffold{ + "type": Command{ Prerequisites: []string{"module"}, Commands: []string{ "type type1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, }, - "message": Scaffold{ + "message": Command{ Prerequisites: []string{"module"}, Commands: []string{ "message message1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, }, - "query": Scaffold{ + "query": Command{ Prerequisites: []string{"module"}, Commands: []string{ "query query1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints --module example --yes", }, }, - "packet": Scaffold{ + "packet": Command{ Prerequisites: []string{"module"}, Commands: []string{ "packet packet1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --ack f1:string,f2:strings,f3:bool,f4:int,f5:ints,f6:uint,f7:uints,f8:coin,f9:coins --module example --yes", diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go index 37b17d504b..780d17312a 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go @@ -15,21 +15,28 @@ import ( var v027 = semver.MustParse("v0.27.0") type ( - // Scaffold represents a set of commands and prerequisites scaffold commands that are required to run before them. + // Scaffold holder the Scaffold logic. Scaffold struct { + Output string + binary string + version *semver.Version + cache *cache + cachePath string + commandList Commands + } + // Command represents a set of commandList and prerequisites scaffold commandList that are required to run before them. + Command struct { // Name is the unique identifier of the command Name string - // Prerequisites is the names of commands that need to be run before this command set + // Prerequisites is the names of commandList that need to be run before this command set Prerequisites []string - // Commands is the list of scaffold commands that are going to be run - // The commands will be prefixed with "ignite scaffold" and executed in order + // Commands is the list of scaffold commandList that are going to be run + // The commandList will be prefixed with "ignite scaffold" and executed in order Commands []string } - Commands map[string]Scaffold -) + Commands map[string]Command -type ( // options represents configuration for the generator. options struct { cachePath string @@ -50,7 +57,7 @@ func newOptions() options { } } -// WithOutput set the ignite scaffold output. +// WithOutput set the ignite scaffold Output. func WithOutput(output string) Options { return func(o *options) { o.output = output @@ -64,69 +71,77 @@ func WithCachePath(cachePath string) Options { } } -// WithCommandList set the migration docs output. +// WithCommandList set the migration docs Output. func WithCommandList(commands Commands) Options { return func(o *options) { o.commands = commands } } -// Run execute the scaffold commands based in the binary semantic version. -func Run(ctx context.Context, binary string, ver *semver.Version, options ...Options) (string, error) { +// New returns a new Scaffold. +func New(binary string, ver *semver.Version, options ...Options) (*Scaffold, error) { opts := newOptions() for _, apply := range options { apply(&opts) } - cache := newCache(opts.cachePath) output, err := filepath.Abs(opts.output) if err != nil { - return "", err + return nil, err } output = filepath.Join(output, ver.Original()) - for _, c := range opts.commands { - if err := runCommand(ctx, cache, binary, output, c.Name, c.Prerequisites, c.Commands, ver, opts.commands); err != nil { - return "", err + return &Scaffold{ + binary: binary, + version: ver, + cache: newCache(opts.cachePath), + cachePath: opts.cachePath, + Output: opts.output, + commandList: opts.commands, + }, nil +} + +// Run execute the scaffold commandList based in the binary semantic version. +func (s *Scaffold) Run(ctx context.Context) error { + for _, c := range s.commandList { + if err := s.runCommand(ctx, c.Name, c.Prerequisites, c.Commands); err != nil { + return err } - if err := applyPostScaffoldExceptions(ver, c.Name, output); err != nil { - return "", err + if err := applyPostScaffoldExceptions(s.version, c.Name, s.Output); err != nil { + return err } } - return output, nil + return nil } -func runCommand( +func (s *Scaffold) runCommand( ctx context.Context, - cache *cache, - binary, output, name string, + name string, prerequisites, scaffoldCommands []string, - ver *semver.Version, - commandList Commands, ) error { // TODO add cache for duplicated scaffoldCommands. for _, p := range prerequisites { - c, ok := commandList[p] + c, ok := s.commandList[p] if !ok { return errors.Errorf("command %s not found", name) } - if err := runCommand(ctx, cache, binary, output, name, c.Prerequisites, c.Commands, ver, commandList); err != nil { + if err := s.runCommand(ctx, name, c.Prerequisites, c.Commands); err != nil { return err } } for _, cmd := range scaffoldCommands { - if err := executeScaffold(ctx, binary, name, cmd, output, ver); err != nil { + if err := s.executeScaffold(ctx, name, cmd); err != nil { return err } } return nil } -func executeScaffold(ctx context.Context, binary, name, cmd, output string, ver *semver.Version) error { - args := append([]string{binary, "scaffold"}, strings.Fields(cmd)...) - args = append(args, "--path", filepath.Join(output, name)) - args = applyPreExecuteExceptions(ver, args) +func (s *Scaffold) executeScaffold(ctx context.Context, name, cmd string) error { + args := append([]string{s.binary, "scaffold"}, strings.Fields(cmd)...) + args = append(args, "--path", filepath.Join(s.Output, name)) + args = applyPreExecuteExceptions(s.version, args) if err := exec.Exec(ctx, args); err != nil { return errors.Wrapf(err, "failed to execute ignite scaffold command: %s", cmd) @@ -146,7 +161,7 @@ func applyPreExecuteExceptions(ver *semver.Version, args []string) []string { return args } -// applyPostScaffoldExceptions this function we can manipulate the output of scaffold commands after +// applyPostScaffoldExceptions this function we can manipulate the Output of scaffold commandList after // they have been executed in order to compensate for differences in versions. func applyPostScaffoldExceptions(ver *semver.Version, name string, output string) error { // In versions <0.27.0, "scaffold chain" command always creates a new directory with the name of From 0fd57fb4a756a62ea60221586143f51727dbb4f7 Mon Sep 17 00:00:00 2001 From: Pantani Date: Thu, 29 Feb 2024 07:47:49 -0300 Subject: [PATCH 41/69] fix wrong output --- .../gen-mig-diffs/pkg/scaffold/scaffold.go | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go index 780d17312a..1cde36978a 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go @@ -26,8 +26,6 @@ type ( } // Command represents a set of commandList and prerequisites scaffold commandList that are required to run before them. Command struct { - // Name is the unique identifier of the command - Name string // Prerequisites is the names of commandList that need to be run before this command set Prerequisites []string // Commands is the list of scaffold commandList that are going to be run @@ -89,25 +87,23 @@ func New(binary string, ver *semver.Version, options ...Options) (*Scaffold, err if err != nil { return nil, err } - output = filepath.Join(output, ver.Original()) - return &Scaffold{ binary: binary, version: ver, cache: newCache(opts.cachePath), cachePath: opts.cachePath, - Output: opts.output, + Output: filepath.Join(output, ver.Original()), commandList: opts.commands, }, nil } // Run execute the scaffold commandList based in the binary semantic version. func (s *Scaffold) Run(ctx context.Context) error { - for _, c := range s.commandList { - if err := s.runCommand(ctx, c.Name, c.Prerequisites, c.Commands); err != nil { + for name, c := range s.commandList { + if err := s.runCommand(ctx, name, c.Prerequisites, c.Commands); err != nil { return err } - if err := applyPostScaffoldExceptions(s.version, c.Name, s.Output); err != nil { + if err := applyPostScaffoldExceptions(s.version, name, s.Output); err != nil { return err } } @@ -120,8 +116,8 @@ func (s *Scaffold) runCommand( prerequisites, scaffoldCommands []string, ) error { // TODO add cache for duplicated scaffoldCommands. - for _, p := range prerequisites { - c, ok := s.commandList[p] + for _, name := range prerequisites { + c, ok := s.commandList[name] if !ok { return errors.Errorf("command %s not found", name) } @@ -153,7 +149,7 @@ func (s *Scaffold) executeScaffold(ctx context.Context, name, cmd string) error // order to compensate for differences in versions. func applyPreExecuteExceptions(ver *semver.Version, args []string) []string { // In versions <0.27.0, "scaffold chain" command always creates a new directory with the - // name of chain at the given --path so we need to append "example" to the path if the + // name of chain at the given '--path' so we need to append "example" to the path if the // command is not "chain". if ver.LessThan(v027) && args[2] != "chain" { args[len(args)-1] = filepath.Join(args[len(args)-1], "example") @@ -177,6 +173,5 @@ func applyPostScaffoldExceptions(ver *semver.Version, name string, output string return errors.Wrapf(err, "failed to move tmp directory to %s directory", name) } } - return nil } From ddedaf3eed2258760c66985e8ba2fd15c6783ba8 Mon Sep 17 00:00:00 2001 From: Pantani Date: Thu, 29 Feb 2024 19:06:09 -0300 Subject: [PATCH 42/69] add the scaffold cache --- .../tools/gen-mig-diffs/pkg/repo/repo.go | 2 +- .../tools/gen-mig-diffs/pkg/scaffold/cache.go | 100 +++++++++++------ .../gen-mig-diffs/pkg/scaffold/commands.go | 102 ++++++++++++++---- .../gen-mig-diffs/pkg/scaffold/scaffold.go | 76 +++++++------ 4 files changed, 197 insertions(+), 83 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go index ef93201874..3f1cbe3a62 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go @@ -83,7 +83,7 @@ func WithCleanup() Options { } } -// validate options +// validate options. func (o options) validate() error { if o.source != "" && (o.repoURL != defaultRepoURL) { return errors.New("cannot set source and repo URL at the same time") diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go index bba57a7a5d..90ba48a7b5 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go @@ -5,9 +5,11 @@ import ( "os" "path/filepath" "sync" + + "github.com/ignite/cli/v28/ignite/pkg/errors" ) -// cache represents a cache for executed scaffold commandList. +// cache represents a cache for executed scaffold command. type cache struct { cachePath string cachesPath map[string]string @@ -15,33 +17,91 @@ type cache struct { } // newCache initializes a new Cache instance. -func newCache(path string) *cache { +func newCache(path string) (*cache, error) { return &cache{ cachePath: path, cachesPath: make(map[string]string), - } + }, os.MkdirAll(path, os.ModePerm) } -// saveCache save a new cache -func (c *cache) saveCache(name, path string) error { +// save creates a new cache. +func (c *cache) save(name, path string) error { c.mu.Lock() defer c.mu.Unlock() - cachePath := filepath.Join(path, name) + dstPath := filepath.Join(c.cachePath, name) + if err := copyFiles(path, dstPath); err != nil { + return err + } + + c.cachesPath[name] = dstPath + return nil +} + +// has return if the cache exist. +func (c *cache) has(name string) bool { + c.mu.RLock() + defer c.mu.RUnlock() + + cachePath, ok := c.cachesPath[name] + if !ok { + return false + } + if _, err := os.Stat(cachePath); os.IsNotExist(err) { + return false + } + + return true +} + +// get return the cache path and copy all files to the destination path. +func (c *cache) get(name, dstPath string) error { + c.mu.RLock() + defer c.mu.RUnlock() + + cachePath, ok := c.cachesPath[name] + if !ok { + return errors.Errorf("command %s not exist in the cache list", name) + } + if _, err := os.Stat(cachePath); os.IsNotExist(err) { + return errors.Wrapf(err, "cache %s not exist in the path", name) + } + dstPath, err := filepath.Abs(dstPath) + if err != nil { + return err + } + if err := copyFiles(cachePath, dstPath); err != nil { + return errors.Wrapf(err, "error to copy cache from %s to %s", cachePath, dstPath) + } + return nil +} + +// copyFiles copy all files from the source path to the destination path. +func copyFiles(srcPath, dstPath string) error { + srcInfo, err := os.Stat(srcPath) + switch { + case os.IsNotExist(err): + return errors.Wrapf(err, "cache %s not exist in the path", srcPath) + case err != nil: + return err + case !srcInfo.IsDir(): + return errors.Wrapf(err, "cache %s is not a directory", srcPath) + } + // Walk through the original path and copy all content to the cache path. - err := filepath.Walk(path, func(srcPath string, info os.FileInfo, err error) error { + return filepath.Walk(srcPath, func(path string, info os.FileInfo, err error) error { if err != nil { return err } - relPath, err := filepath.Rel(path, srcPath) + relPath, err := filepath.Rel(srcPath, path) if err != nil { return err } - dstPath := filepath.Join(cachePath, relPath) + dstPath := filepath.Join(dstPath, relPath) if info.IsDir() { return os.MkdirAll(dstPath, info.Mode()) } - srcFile, err := os.Open(srcPath) + srcFile, err := os.Open(path) if err != nil { return err } @@ -54,24 +114,4 @@ func (c *cache) saveCache(name, path string) error { _, err = io.Copy(dstFile, srcFile) return err }) - if err != nil { - return err - } - - c.cachesPath[name] = cachePath - return nil -} - -// get return the cache path -func (c *cache) get(name string) (string, bool) { - c.mu.RLock() - defer c.mu.RUnlock() - cachePath, ok := c.cachesPath[name] - if !ok { - return "", false - } - if _, err := os.Stat(cachePath); os.IsNotExist(err) { - return "", false - } - return cachePath, true } diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go index 4439dc212d..18a9a0e215 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go @@ -1,51 +1,117 @@ package scaffold +import "github.com/ignite/cli/v28/ignite/pkg/errors" + +type ( + // Command represents a set of command and prerequisites scaffold command that are required to run before them. + Command struct { + // Name is the unique identifier of the command + Name string + // Prerequisite is the name of command that need to be run before this command set + Prerequisite string + // Commands is the list of scaffold command that are going to be run + // The command will be prefixed with "ignite scaffold" and executed in order + Commands []string + } + + Commands []Command +) + +func (c Commands) Get(name string) (Command, error) { + for _, cmd := range c { + if cmd.Name == name { + return cmd, nil + } + } + return Command{}, errors.Errorf("command %s not exist", name) +} + +func (c Commands) Has(name string) bool { + for _, cmd := range c { + if cmd.Name == name { + return true + } + } + return false +} + +func (c Commands) Validate() error { + cmdMap := make(map[string]bool) + for i, command := range c { + if cmdMap[command.Name] { + return errors.Errorf("duplicate command name found: %s", command.Name) + } + cmdMap[command.Name] = true + if command.Name == "" { + return errors.Errorf("empty command name at index %d: %v", i, command) + } + if len(command.Commands) == 0 { + return errors.Errorf("empty command list at index %d: %v", i, command) + } + } + for _, command := range c { + if command.Prerequisite != "" && !cmdMap[command.Prerequisite] { + return errors.Errorf("command %s pre-requisete %s not found", command.Name, command.Prerequisite) + } + } + return nil +} + var defaultCommands = Commands{ - "chain": Command{ + Command{ + Name: "chain", Commands: []string{"chain example --no-module"}, }, - "module": Command{ - Prerequisites: []string{"chain"}, - Commands: []string{"module example --ibc"}, + Command{ + Name: "module", + Prerequisite: "chain", + Commands: []string{"module example --ibc"}, }, - "list": Command{ - Prerequisites: []string{"module"}, + Command{ + Name: "list", + Prerequisite: "module", Commands: []string{ "list list1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, }, - "map": Command{ - Prerequisites: []string{"module"}, + Command{ + Name: "map", + Prerequisite: "module", Commands: []string{ "map map1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --index i1:string --module example --yes", }, }, - "single": Command{ - Prerequisites: []string{"module"}, + Command{ + Name: "single", + Prerequisite: "module", Commands: []string{ "single single1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, }, - "type": Command{ - Prerequisites: []string{"module"}, + Command{ + Name: "type", + Prerequisite: "module", Commands: []string{ "type type1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, }, - "message": Command{ - Prerequisites: []string{"module"}, + Command{ + Name: "message", + Prerequisite: "module", Commands: []string{ "message message1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --module example --yes", }, }, - "query": Command{ - Prerequisites: []string{"module"}, + Command{ + Name: "query", + Prerequisite: "module", Commands: []string{ "query query1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints --module example --yes", }, }, - "packet": Command{ - Prerequisites: []string{"module"}, + Command{ + Name: "packet", + Prerequisite: "module", Commands: []string{ "packet packet1 f1:string f2:strings f3:bool f4:int f5:ints f6:uint f7:uints f8:coin f9:coins --ack f1:string,f2:strings,f3:bool,f4:int,f5:ints,f6:uint,f7:uints,f8:coin,f9:coins --module example --yes", }, diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go index 1cde36978a..7b620aad22 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go @@ -10,6 +10,7 @@ import ( "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/exec" "github.com/ignite/cli/v28/ignite/pkg/errors" + "github.com/ignite/cli/v28/ignite/pkg/randstr" ) var v027 = semver.MustParse("v0.27.0") @@ -24,16 +25,6 @@ type ( cachePath string commandList Commands } - // Command represents a set of commandList and prerequisites scaffold commandList that are required to run before them. - Command struct { - // Prerequisites is the names of commandList that need to be run before this command set - Prerequisites []string - // Commands is the list of scaffold commandList that are going to be run - // The commandList will be prefixed with "ignite scaffold" and executed in order - Commands []string - } - - Commands map[string]Command // options represents configuration for the generator. options struct { @@ -47,7 +38,7 @@ type ( // newOptions returns a options with default options. func newOptions() options { - tmpDir := os.TempDir() + tmpDir := filepath.Join(os.TempDir(), randstr.Runes(4)) return options{ cachePath: filepath.Join(tmpDir, "migration-cache"), output: filepath.Join(tmpDir, "migration"), @@ -87,56 +78,73 @@ func New(binary string, ver *semver.Version, options ...Options) (*Scaffold, err if err != nil { return nil, err } + + c, err := newCache(opts.cachePath) + if err != nil { + return nil, err + } + + if err := opts.commands.Validate(); err != nil { + return nil, err + } + return &Scaffold{ binary: binary, version: ver, - cache: newCache(opts.cachePath), + cache: c, cachePath: opts.cachePath, Output: filepath.Join(output, ver.Original()), commandList: opts.commands, }, nil } -// Run execute the scaffold commandList based in the binary semantic version. +// Run execute the scaffold command based in the binary semantic version. func (s *Scaffold) Run(ctx context.Context) error { - for name, c := range s.commandList { - if err := s.runCommand(ctx, name, c.Prerequisites, c.Commands); err != nil { + if err := os.RemoveAll(s.Output); err != nil { + return errors.Wrapf(err, "failed to remove the scaffold output directory: %s", s.Output) + } + + for _, command := range s.commandList { + if err := s.runCommand(ctx, command.Name, command); err != nil { return err } - if err := applyPostScaffoldExceptions(s.version, name, s.Output); err != nil { + if err := applyPostScaffoldExceptions(s.version, command.Name, s.Output); err != nil { return err } } return nil } -func (s *Scaffold) runCommand( - ctx context.Context, - name string, - prerequisites, scaffoldCommands []string, -) error { - // TODO add cache for duplicated scaffoldCommands. - for _, name := range prerequisites { - c, ok := s.commandList[name] - if !ok { - return errors.Errorf("command %s not found", name) +func (s *Scaffold) runCommand(ctx context.Context, name string, command Command) error { + path := filepath.Join(s.Output, name) + if command.Prerequisite != "" { + reqCmd, err := s.commandList.Get(command.Prerequisite) + if err != nil { + return errors.Wrapf(err, "pre-requisite command %s from %s not found", command.Prerequisite, name) } - if err := s.runCommand(ctx, name, c.Prerequisites, c.Commands); err != nil { - return err + + if s.cache.has(command.Prerequisite) { + if err := s.cache.get(command.Prerequisite, path); err != nil { + return errors.Wrapf(err, "failed to get cache key %s", command.Prerequisite) + } + } else { + if err := s.runCommand(ctx, name, reqCmd); err != nil { + return err + } } } - for _, cmd := range scaffoldCommands { - if err := s.executeScaffold(ctx, name, cmd); err != nil { + for _, cmd := range command.Commands { + if err := s.executeScaffold(ctx, cmd, path); err != nil { return err } } - return nil + return s.cache.save(command.Name, path) } -func (s *Scaffold) executeScaffold(ctx context.Context, name, cmd string) error { +func (s *Scaffold) executeScaffold(ctx context.Context, cmd, path string) error { args := append([]string{s.binary, "scaffold"}, strings.Fields(cmd)...) - args = append(args, "--path", filepath.Join(s.Output, name)) + args = append(args, "--path", path) args = applyPreExecuteExceptions(s.version, args) if err := exec.Exec(ctx, args); err != nil { @@ -157,7 +165,7 @@ func applyPreExecuteExceptions(ver *semver.Version, args []string) []string { return args } -// applyPostScaffoldExceptions this function we can manipulate the Output of scaffold commandList after +// applyPostScaffoldExceptions this function we can manipulate the Output of scaffold command after // they have been executed in order to compensate for differences in versions. func applyPostScaffoldExceptions(ver *semver.Version, name string, output string) error { // In versions <0.27.0, "scaffold chain" command always creates a new directory with the name of From 60b96e960792e2d0c24f7585a494a824d750ce6c Mon Sep 17 00:00:00 2001 From: Pantani Date: Thu, 29 Feb 2024 20:05:14 -0300 Subject: [PATCH 43/69] fix folder search for diffs --- .../tools/gen-mig-diffs/pkg/diff/diff.go | 86 +++++++++++-------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go index 2dbec5fb2e..d0de70e29e 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go @@ -31,26 +31,27 @@ var diffIgnoreGlobs = []string{ "**.json", } +// CalculateDiffs calculate the diff from two directories. func CalculateDiffs(fromDir, toDir string) (Diffs, error) { - paths := make([]string, 0) - err := filepath.Walk(fromDir, func(path string, info os.FileInfo, err error) error { - if err == nil && info.IsDir() && path != fromDir { - paths = append(paths, path) - } - return nil - }) + paths, err := readRootFolders(fromDir) + if err != nil { + return nil, err + } + toPaths, err := readRootFolders(toDir) if err != nil { return nil, err } + for key, value := range toPaths { + paths[key] = value + } diffs := make(Diffs) - for _, s := range paths { - name := filepath.Base(s) - from := filepath.Join(fromDir, name) + for path, _ := range paths { + from := filepath.Join(fromDir, path) if err := os.MkdirAll(from, os.ModePerm); err != nil { return nil, err } - to := filepath.Join(toDir, name) + to := filepath.Join(toDir, path) if err := os.MkdirAll(to, os.ModePerm); err != nil { return nil, err } @@ -64,11 +65,49 @@ func CalculateDiffs(fromDir, toDir string) (Diffs, error) { return nil, err } - diffs[name] = computedDiff + diffs[path] = computedDiff } return subtractBaseDiffs(diffs), nil } +// SaveDiffs save all migration diffs to the output path. +func SaveDiffs(diffs Diffs, outputPath string) error { + if err := os.MkdirAll(outputPath, os.ModePerm); err != nil { + return err + } + + for name, diffs := range diffs { + output, err := os.Create(filepath.Join(outputPath, name+".diff")) + if err != nil { + return err + } + for _, d := range diffs { + output.WriteString(fmt.Sprint(d)) + output.WriteString("\n") + } + if err := output.Close(); err != nil { + return err + } + } + + return nil +} + +// readRootFolders return a map of all root folders from a directory. +func readRootFolders(dir string) (map[string]struct{}, error) { + paths := make(map[string]struct{}) + dirEntries, err := os.ReadDir(dir) + if err != nil { + return nil, err + } + for _, entry := range dirEntries { + if entry.IsDir() { + paths[entry.Name()] = struct{}{} + } + } + return paths, nil +} + // subtractBaseDiffs removes chain and module diffs from other diffs. func subtractBaseDiffs(diffs Diffs) Diffs { chainDiff := diffs["chain"] @@ -92,26 +131,3 @@ func subtractUnifieds(a, b []gotextdiff.Unified) []gotextdiff.Unified { } return a } - -// SaveDiffs save all migration diffs to the output path. -func SaveDiffs(diffs Diffs, outputPath string) error { - if err := os.MkdirAll(outputPath, os.ModePerm); err != nil { - return err - } - - for name, diffs := range diffs { - output, err := os.Create(filepath.Join(outputPath, name+".diff")) - if err != nil { - return err - } - for _, d := range diffs { - output.WriteString(fmt.Sprint(d)) - output.WriteString("\n") - } - if err := output.Close(); err != nil { - return err - } - } - - return nil -} From 4e6dd602401b431598662a4966c3641fd717c9a0 Mon Sep 17 00:00:00 2001 From: Pantani Date: Thu, 29 Feb 2024 20:15:12 -0300 Subject: [PATCH 44/69] improve the logs and comments --- ignite/internal/tools/gen-mig-diffs/cmd/root.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 36211b642d..b523e09a94 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -55,6 +55,7 @@ func NewRootCmd() *cobra.Command { return errors.Wrapf(err, "failed to parse to version %s", to) } + // Check or download the source and generate the binaries for each version. repoOptions := make([]repo.Options, 0) if repoCleanup { repoOptions = append(repoOptions, repo.WithCleanup()) @@ -80,6 +81,7 @@ func NewRootCmd() *cobra.Command { return err } + // Scaffold the default commands for each version. scaffoldOptions := make([]scaffold.Options, 0) if scaffoldOutput != "" { scaffoldOptions = append(scaffoldOptions, scaffold.WithOutput(scaffoldOutput)) @@ -96,6 +98,8 @@ func NewRootCmd() *cobra.Command { if err := sFrom.Run(cmd.Context()); err != nil { return err } + session.StopSpinner() + session.EventBus().SendInfo(fmt.Sprintf("Scaffolded code for %s at %s", igniteRepo.From.Original(), sFrom.Output)) session.StartSpinner(fmt.Sprintf("Running scaffold commands for %s...", igniteRepo.To.Original())) sTo, err := scaffold.New(toBin, igniteRepo.To, scaffoldOptions...) @@ -105,10 +109,10 @@ func NewRootCmd() *cobra.Command { if err := sTo.Run(cmd.Context()); err != nil { return err } - session.StopSpinner() - session.EventBus().SendInfo(fmt.Sprintf("Scaffolded code for commands at %s", output)) + session.EventBus().SendInfo(fmt.Sprintf("Scaffolded code for %s at %s", igniteRepo.To.Original(), sTo.Output)) + // Calculate and save the diffs from the scaffolded code. session.StartSpinner("Calculating diff...") diffs, err := diff.CalculateDiffs(sFrom.Output, sTo.Output) if err != nil { From 302cc9ec53ddcf57cbfbf28e7248112c97e9cd5a Mon Sep 17 00:00:00 2001 From: Pantani Date: Thu, 29 Feb 2024 20:17:50 -0300 Subject: [PATCH 45/69] remove unused temp folder creation --- ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go | 2 +- ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go index d0de70e29e..dcdb31de37 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go @@ -46,7 +46,7 @@ func CalculateDiffs(fromDir, toDir string) (Diffs, error) { } diffs := make(Diffs) - for path, _ := range paths { + for path := range paths { from := filepath.Join(fromDir, path) if err := os.MkdirAll(from, os.ModePerm); err != nil { return nil, err diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go index 3f1cbe3a62..5fc6fe49ee 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go @@ -101,18 +101,12 @@ func New(from, to *semver.Version, session *cliui.Session, options ...Options) ( for _, apply := range options { apply(&opts) } - if err := opts.validate(); err != nil { - return nil, err - } - tempDir, err := os.MkdirTemp("", ".migdoc") + err := opts.validate() if err != nil { - return nil, errors.Wrap(err, "failed to create temporary directory") + return nil, err } - session.StopSpinner() - session.EventBus().SendInfo(fmt.Sprintf("Created temporary directory: %s", tempDir)) - var ( source = opts.source repo *git.Repository @@ -123,6 +117,7 @@ func New(from, to *semver.Version, session *cliui.Session, options ...Options) ( return nil, errors.Wrap(err, "failed to open ignite repository") } + session.StopSpinner() session.EventBus().SendInfo(fmt.Sprintf("Using ignite repository at: %s", source)) } else { session.StartSpinner("Cloning ignite repository...") From 57ea7b3493a25854850ad1871b6249955bf7949b Mon Sep 17 00:00:00 2001 From: Pantani Date: Thu, 29 Feb 2024 22:40:02 -0300 Subject: [PATCH 46/69] fix binaries path --- .../internal/tools/gen-mig-diffs/cmd/root.go | 6 +- .../tools/gen-mig-diffs/pkg/repo/repo.go | 67 ++++++++++++++++++- .../tools/gen-mig-diffs/pkg/scaffold/cache.go | 46 +------------ .../gen-mig-diffs/pkg/scaffold/scaffold.go | 8 +++ 4 files changed, 80 insertions(+), 47 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index b523e09a94..04b14d7bbf 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -95,6 +95,8 @@ func NewRootCmd() *cobra.Command { if err != nil { return err } + defer sFrom.Cleanup() + if err := sFrom.Run(cmd.Context()); err != nil { return err } @@ -106,6 +108,8 @@ func NewRootCmd() *cobra.Command { if err != nil { return err } + defer sTo.Cleanup() + if err := sTo.Run(cmd.Context()); err != nil { return err } @@ -124,7 +128,7 @@ func NewRootCmd() *cobra.Command { if err = diff.SaveDiffs(diffs, output); err != nil { return errors.Wrap(err, "failed to save diff map") } - session.Println("Migration diffs generated successfully at", output) + session.Printf("Migration diffs generated successfully at %s\n", output) return nil }, diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go index 5fc6fe49ee..131167d58c 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go @@ -3,6 +3,7 @@ package repo import ( "context" "fmt" + "io" "os" "path/filepath" "sort" @@ -27,6 +28,7 @@ type ( Generator struct { From, To *semver.Version source string + binPath string repo *git.Repository session *cliui.Session cleanup bool @@ -37,6 +39,7 @@ type ( source string output string repoURL string + binPath string cleanup bool } // Options configures the generator. @@ -48,6 +51,7 @@ func newOptions() options { tmpDir := os.TempDir() return options{ source: "", + binPath: filepath.Join(tmpDir, "bin"), output: filepath.Join(tmpDir, "migration-source"), repoURL: defaultRepoURL, } @@ -76,6 +80,13 @@ func WithRepoOutput(output string) Options { } } +// WithBinPath set the binary path to build the source. +func WithBinPath(binPath string) Options { + return func(o *options) { + o.binPath = binPath + } +} + // WithCleanup cleanup folders after use. func WithCleanup() Options { return func(o *options) { @@ -146,12 +157,18 @@ func New(from, to *semver.Version, session *cliui.Session, options ...Options) ( return nil, err } + binPath, err := filepath.Abs(opts.binPath) + if err != nil { + return nil, err + } + return &Generator{ From: from, To: to, source: source, repo: repo, session: session, + binPath: binPath, }, nil } @@ -274,10 +291,15 @@ func (g *Generator) buildIgniteCli(ctx context.Context, ver *semver.Version) (st return "", errors.Wrap(err, "failed to build ignite cli using make build") } - binPath := filepath.Join(g.source, defaultBinaryPath) + // Copy the built binary to the binary path. + genBinaryPath := filepath.Join(g.source, defaultBinaryPath) + binPath := filepath.Join(g.binPath, ver.Original(), "ignite") + if err := copyFile(genBinaryPath, binPath); err != nil { + return "", err + } g.session.StopSpinner() - g.session.EventBus().SendInfo(fmt.Sprintf("Built ignite cli for %s", ver.Original())) + g.session.EventBus().SendInfo(fmt.Sprintf("Built ignite cli for %s at %s", ver.Original(), binPath)) return binPath, nil } @@ -288,7 +310,6 @@ func (g *Generator) checkoutToTag(tag string) error { if err != nil { return err } - // Reset and clean the git directory before the checkout to avoid conflicts. if err := wt.Reset(&git.ResetOptions{Mode: git.HardReset}); err != nil { return errors.Wrapf(err, "failed to reset %s", g.source) @@ -301,3 +322,43 @@ func (g *Generator) checkoutToTag(tag string) error { } return nil } + +// copyFile copy a file to a destination directory. Creates the directory if not exist. +func copyFile(srcPath, dstPath string) error { + dstDir := filepath.Dir(dstPath) + if err := os.RemoveAll(dstDir); err != nil { + return err + } + if err := os.MkdirAll(dstDir, os.ModePerm); err != nil { + return err + } + + src, err := os.Open(srcPath) + if err != nil { + return errors.Wrap(err, "failed to open source file") + } + defer src.Close() + + dst, err := os.Create(dstPath) + if err != nil { + return errors.Wrap(err, "failed to create destination file") + } + defer dst.Close() + + _, err = io.Copy(dst, src) + if err != nil { + return errors.Wrap(err, "failed to copy data: %s") + } + // Sync to ensure data is flushed to disk. + err = dst.Sync() + if err != nil { + return errors.Wrap(err, "failed to sync destination file") + } + + // Set executable permissions on the destination file. + err = os.Chmod(dstPath, 0o755) + if err != nil { + return errors.Wrap(err, "failed to set executable permissions") + } + return err +} diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go index 90ba48a7b5..17c1445caa 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go @@ -1,12 +1,12 @@ package scaffold import ( - "io" "os" "path/filepath" "sync" "github.com/ignite/cli/v28/ignite/pkg/errors" + "github.com/ignite/cli/v28/ignite/pkg/xos" ) // cache represents a cache for executed scaffold command. @@ -30,7 +30,7 @@ func (c *cache) save(name, path string) error { defer c.mu.Unlock() dstPath := filepath.Join(c.cachePath, name) - if err := copyFiles(path, dstPath); err != nil { + if err := xos.CopyFolder(path, dstPath); err != nil { return err } @@ -70,48 +70,8 @@ func (c *cache) get(name, dstPath string) error { if err != nil { return err } - if err := copyFiles(cachePath, dstPath); err != nil { + if err := xos.CopyFolder(cachePath, dstPath); err != nil { return errors.Wrapf(err, "error to copy cache from %s to %s", cachePath, dstPath) } return nil } - -// copyFiles copy all files from the source path to the destination path. -func copyFiles(srcPath, dstPath string) error { - srcInfo, err := os.Stat(srcPath) - switch { - case os.IsNotExist(err): - return errors.Wrapf(err, "cache %s not exist in the path", srcPath) - case err != nil: - return err - case !srcInfo.IsDir(): - return errors.Wrapf(err, "cache %s is not a directory", srcPath) - } - - // Walk through the original path and copy all content to the cache path. - return filepath.Walk(srcPath, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - relPath, err := filepath.Rel(srcPath, path) - if err != nil { - return err - } - dstPath := filepath.Join(dstPath, relPath) - if info.IsDir() { - return os.MkdirAll(dstPath, info.Mode()) - } - srcFile, err := os.Open(path) - if err != nil { - return err - } - defer srcFile.Close() - dstFile, err := os.Create(dstPath) - if err != nil { - return err - } - defer dstFile.Close() - _, err = io.Copy(dstFile, srcFile) - return err - }) -} diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go index 7b620aad22..34e7fac2ab 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go @@ -115,6 +115,14 @@ func (s *Scaffold) Run(ctx context.Context) error { return nil } +// Cleanup cleanup all temporary directories. +func (s *Scaffold) Cleanup() error { + if err := os.RemoveAll(s.cachePath); err != nil { + return err + } + return os.RemoveAll(s.Output) +} + func (s *Scaffold) runCommand(ctx context.Context, name string, command Command) error { path := filepath.Join(s.Output, name) if command.Prerequisite != "" { From 6f7c06ecd6f1306d279d18284e6b48552c7896aa Mon Sep 17 00:00:00 2001 From: Pantani Date: Fri, 1 Mar 2024 18:03:13 -0300 Subject: [PATCH 47/69] generate migration docs inside a doc template --- docs/docs/06-migration/v28.0.0.md | 6 +- .../internal/tools/gen-mig-diffs/cmd/root.go | 38 +++- .../tools/gen-mig-diffs/pkg/diff/diff.go | 15 ++ .../tools/gen-mig-diffs/pkg/repo/repo.go | 169 ++++++++++-------- .../tools/gen-mig-diffs/templates/doc/doc.go | 69 +++++++ .../templates/doc/files/{{Version}}.md.plush | 19 ++ ignite/pkg/xstrings/xstrings_test.go | 12 ++ 7 files changed, 247 insertions(+), 81 deletions(-) create mode 100644 ignite/internal/tools/gen-mig-diffs/templates/doc/doc.go create mode 100644 ignite/internal/tools/gen-mig-diffs/templates/doc/files/{{Version}}.md.plush diff --git a/docs/docs/06-migration/v28.0.0.md b/docs/docs/06-migration/v28.0.0.md index 9c618fefd8..7ece1836f6 100644 --- a/docs/docs/06-migration/v28.0.0.md +++ b/docs/docs/06-migration/v28.0.0.md @@ -81,15 +81,15 @@ This guide provides a step-by-step process for developers to upgrade their appli - **Old Code**: ```go - store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.PostKey)) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.PostKey)) ``` - **New Code**: ```go - storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) - store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.PostKey)) + storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) + store := prefix.NewStore(storeAdapter, types.KeyPrefix(types.PostKey)) ``` diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 04b14d7bbf..d8e08cbc98 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "path/filepath" "github.com/Masterminds/semver/v3" "github.com/spf13/cobra" @@ -9,8 +10,11 @@ import ( "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/pkg/diff" "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/pkg/repo" "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/pkg/scaffold" + "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/templates/doc" "github.com/ignite/cli/v28/ignite/pkg/cliui" "github.com/ignite/cli/v28/ignite/pkg/errors" + "github.com/ignite/cli/v28/ignite/pkg/placeholder" + "github.com/ignite/cli/v28/ignite/pkg/xgenny" ) const ( @@ -23,6 +27,8 @@ const ( flagRepoCleanup = "repo-cleanup" flagScaffoldOutput = "scaffold-output" flagScaffoldCache = "scaffold-cache" + + defaultDocPath = "docs/docs/06-migration" ) // NewRootCmd creates a new root command. @@ -76,6 +82,11 @@ func NewRootCmd() *cobra.Command { } defer igniteRepo.Cleanup() + releaseDescription, err := igniteRepo.ReleaseDescription() + if err != nil { + return errors.Wrapf(err, "failed to fetch the release tag %s description", igniteRepo.To.Original()) + } + fromBin, toBin, err := igniteRepo.GenerateBinaries(cmd.Context()) if err != nil { return err @@ -122,13 +133,32 @@ func NewRootCmd() *cobra.Command { if err != nil { return errors.Wrap(err, "failed to calculate diff") } + + formatedDiffs, err := diff.FormatDiffs(diffs) + if err != nil { + return errors.Wrap(err, "failed to save diff map") + } session.StopSpinner() session.EventBus().SendInfo("Diff calculated successfully") - if err = diff.SaveDiffs(diffs, output); err != nil { - return errors.Wrap(err, "failed to save diff map") + output, err = filepath.Abs(output) + if err != nil { + return errors.Wrap(err, "failed to find the abs path") + } + + // Generate the docs file. + g, err := doc.NewGenerator(doc.Options{ + Path: output, + FromVersion: igniteRepo.From, + ToVersion: igniteRepo.To, + Diffs: string(formatedDiffs), + Description: releaseDescription, + }) + if _, err := xgenny.RunWithValidation(placeholder.New(), g); err != nil { + return err } - session.Printf("Migration diffs generated successfully at %s\n", output) + + session.Printf("Migration doc generated successfully at %s\n", output) return nil }, @@ -136,7 +166,7 @@ func NewRootCmd() *cobra.Command { cmd.Flags().StringP(flagFrom, "f", "", "Version of ignite or path to ignite source code to generate the diff from") cmd.Flags().StringP(flagTo, "t", "", "Version of ignite or path to ignite source code to generate the diff to") - cmd.Flags().StringP(flagOutput, "o", "./diffs", "Output directory to save the migration diff files") + cmd.Flags().StringP(flagOutput, "o", defaultDocPath, "Output directory to save the migration document") cmd.Flags().StringP(flagSource, "s", "", "Path to ignite source code repository. Set the source automatically set the cleanup to false") cmd.Flags().String(flagRepoURL, "", "Git URL for the Ignite repository") cmd.Flags().String(flagRepoOutput, "", "Output path to clone the ignite repository") diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go index dcdb31de37..768c7c26cc 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go @@ -1,6 +1,7 @@ package diff import ( + "bytes" "fmt" "os" "path/filepath" @@ -8,6 +9,7 @@ import ( "github.com/hexops/gotextdiff" "github.com/ignite/cli/v28/ignite/pkg/diff" + "github.com/ignite/cli/v28/ignite/pkg/xstrings" ) type Diffs map[string][]gotextdiff.Unified @@ -93,6 +95,19 @@ func SaveDiffs(diffs Diffs, outputPath string) error { return nil } +// FormatDiffs format all diffs in a single markdown byte array. +func FormatDiffs(diffs Diffs) ([]byte, error) { + buffer := &bytes.Buffer{} + for name, diffs := range diffs { + buffer.WriteString(fmt.Sprintf("#### **%s diff**\n\n", xstrings.ToUpperFirst(name))) + for _, d := range diffs { + buffer.WriteString(fmt.Sprint(d)) + buffer.WriteString("\n\n") + } + } + return buffer.Bytes(), nil +} + // readRootFolders return a map of all root folders from a directory. func readRootFolders(dir string) (map[string]struct{}, error) { paths := make(map[string]struct{}) diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go index 131167d58c..b216f60afc 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go @@ -147,7 +147,7 @@ func New(from, to *semver.Version, session *cliui.Session, options ...Options) ( session.EventBus().SendInfo(fmt.Sprintf("Cloned ignite repository to: %s", source)) } - versions, err := getRepoVersionTags(source) + versions, err := getRepoVersionTags(repo) if err != nil { return nil, err } @@ -172,13 +172,103 @@ func New(from, to *semver.Version, session *cliui.Session, options ...Options) ( }, nil } -// getRepoVersionTags returns a sorted collection of semver tags from the ignite cli repository. -func getRepoVersionTags(repoDir string) (semver.Collection, error) { - repo, err := git.PlainOpen(repoDir) +func (g *Generator) ReleaseDescription() (string, error) { + tag, err := g.repo.Tag(g.To.Original()) if err != nil { - return nil, err + return "", errors.Wrapf(err, "failed to get tag %s", g.To.Original()) } + tagObj, err := g.repo.TagObject(tag.Hash()) + if err != nil { + return "", errors.Wrapf(err, "failed to get tag object %s", tag.Hash().String()) + } + description := fmt.Sprintf(`Tag: %[1]v +Commit: %[2]v +Author: %[3]v +Date: %[4]v + +%[5]v +`, + g.To.Original(), + tagObj.Hash.String(), + tagObj.Tagger.String(), + tagObj.Tagger.When.Format("Jan 2 15:04:05 2006"), + tagObj.Message, + ) + + return description, nil +} +// Cleanup cleanup all temporary directories. +func (g *Generator) Cleanup() { + if !g.cleanup { + return + } + if err := os.RemoveAll(g.source); err != nil { + g.session.EventBus().SendError(err) + return + } + g.session.EventBus().SendInfo(fmt.Sprintf("Removed temporary directory: %s", g.source)) +} + +func (g *Generator) GenerateBinaries(ctx context.Context) (string, string, error) { + fromBinPath, err := g.buildIgniteCli(ctx, g.From) + if err != nil { + return "", "", errors.Wrapf(err, "failed to run scaffolds for 'FROM' version %s", g.From) + } + toBinPath, err := g.buildIgniteCli(ctx, g.To) + if err != nil { + return "", "", errors.Wrapf(err, "failed to run scaffolds for 'TO' version %s", g.To) + } + return fromBinPath, toBinPath, nil +} + +// buildIgniteCli build the ignite CLI from version. +func (g *Generator) buildIgniteCli(ctx context.Context, ver *semver.Version) (string, error) { + g.session.StartSpinner(fmt.Sprintf("Building binary for version v%s...", ver)) + + if err := g.checkoutToTag(ver.Original()); err != nil { + return "", err + } + + err := exec.Exec(ctx, []string{"make", "build"}, exec.StepOption(step.Workdir(g.source))) + if err != nil { + return "", errors.Wrap(err, "failed to build ignite cli using make build") + } + + // Copy the built binary to the binary path. + genBinaryPath := filepath.Join(g.source, defaultBinaryPath) + binPath := filepath.Join(g.binPath, ver.Original(), "ignite") + if err := copyFile(genBinaryPath, binPath); err != nil { + return "", err + } + + g.session.StopSpinner() + g.session.EventBus().SendInfo(fmt.Sprintf("Built ignite cli for %s at %s", ver.Original(), binPath)) + + return binPath, nil +} + +// checkoutToTag checkout the repository from a specific git tag. +func (g *Generator) checkoutToTag(tag string) error { + wt, err := g.repo.Worktree() + if err != nil { + return err + } + // Reset and clean the git directory before the checkout to avoid conflicts. + if err := wt.Reset(&git.ResetOptions{Mode: git.HardReset}); err != nil { + return errors.Wrapf(err, "failed to reset %s", g.source) + } + if err := wt.Clean(&git.CleanOptions{Dir: true}); err != nil { + return errors.Wrapf(err, "failed to reset %s", g.source) + } + if err = wt.Checkout(&git.CheckoutOptions{Branch: plumbing.NewTagReferenceName(tag)}); err != nil { + return errors.Wrapf(err, "failed to checkout tag %s", tag) + } + return nil +} + +// getRepoVersionTags returns a sorted collection of semver tags from the ignite cli repository. +func getRepoVersionTags(repo *git.Repository) (semver.Collection, error) { tags, err := repo.Tags() if err != nil { return nil, errors.Wrap(err, "failed to get tags") @@ -207,18 +297,6 @@ func getRepoVersionTags(repoDir string) (semver.Collection, error) { return versions, nil } -// Cleanup cleanup all temporary directories. -func (g *Generator) Cleanup() { - if !g.cleanup { - return - } - if err := os.RemoveAll(g.source); err != nil { - g.session.EventBus().SendError(err) - return - } - g.session.EventBus().SendInfo(fmt.Sprintf("Removed temporary directory: %s", g.source)) -} - // validateVersionRange checks if the provided fromVer and toVer exist in the versions and if any of them is nil, then it picks default values. func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collection) (*semver.Version, *semver.Version, error) { // Unable to generate migration document if there are less than two releases! @@ -266,63 +344,6 @@ func validateVersionRange(fromVer, toVer *semver.Version, versions semver.Collec return fromVer, toVer, nil } -func (g *Generator) GenerateBinaries(ctx context.Context) (string, string, error) { - fromBinPath, err := g.buildIgniteCli(ctx, g.From) - if err != nil { - return "", "", errors.Wrapf(err, "failed to run scaffolds for 'FROM' version %s", g.From) - } - toBinPath, err := g.buildIgniteCli(ctx, g.To) - if err != nil { - return "", "", errors.Wrapf(err, "failed to run scaffolds for 'TO' version %s", g.To) - } - return fromBinPath, toBinPath, nil -} - -// buildIgniteCli build the ignite CLI from version. -func (g *Generator) buildIgniteCli(ctx context.Context, ver *semver.Version) (string, error) { - g.session.StartSpinner(fmt.Sprintf("Building binary for version v%s...", ver)) - - if err := g.checkoutToTag(ver.Original()); err != nil { - return "", err - } - - err := exec.Exec(ctx, []string{"make", "build"}, exec.StepOption(step.Workdir(g.source))) - if err != nil { - return "", errors.Wrap(err, "failed to build ignite cli using make build") - } - - // Copy the built binary to the binary path. - genBinaryPath := filepath.Join(g.source, defaultBinaryPath) - binPath := filepath.Join(g.binPath, ver.Original(), "ignite") - if err := copyFile(genBinaryPath, binPath); err != nil { - return "", err - } - - g.session.StopSpinner() - g.session.EventBus().SendInfo(fmt.Sprintf("Built ignite cli for %s at %s", ver.Original(), binPath)) - - return binPath, nil -} - -// checkoutToTag checkout the repository from a specific git tag. -func (g *Generator) checkoutToTag(tag string) error { - wt, err := g.repo.Worktree() - if err != nil { - return err - } - // Reset and clean the git directory before the checkout to avoid conflicts. - if err := wt.Reset(&git.ResetOptions{Mode: git.HardReset}); err != nil { - return errors.Wrapf(err, "failed to reset %s", g.source) - } - if err := wt.Clean(&git.CleanOptions{Dir: true}); err != nil { - return errors.Wrapf(err, "failed to reset %s", g.source) - } - if err = wt.Checkout(&git.CheckoutOptions{Branch: plumbing.NewTagReferenceName(tag)}); err != nil { - return errors.Wrapf(err, "failed to checkout tag %s", tag) - } - return nil -} - // copyFile copy a file to a destination directory. Creates the directory if not exist. func copyFile(srcPath, dstPath string) error { dstDir := filepath.Dir(dstPath) diff --git a/ignite/internal/tools/gen-mig-diffs/templates/doc/doc.go b/ignite/internal/tools/gen-mig-diffs/templates/doc/doc.go new file mode 100644 index 0000000000..ae0bf0315e --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/templates/doc/doc.go @@ -0,0 +1,69 @@ +package doc + +import ( + "embed" + "fmt" + "time" + + "github.com/Masterminds/semver/v3" + "github.com/gobuffalo/genny/v2" + "github.com/gobuffalo/plush/v4" + + "github.com/ignite/cli/v28/ignite/pkg/xgenny" + "github.com/ignite/cli/v28/ignite/templates/field/plushhelpers" +) + +//go:embed files/* +var fsFiles embed.FS + +// Options represents the options to scaffold a migration document. +type Options struct { + Path string + FromVersion *semver.Version + ToVersion *semver.Version + Diffs string + Description string +} + +func (o Options) position() string { + return fmt.Sprintf("%02d%02d%02d", o.ToVersion.Major(), o.ToVersion.Minor(), o.ToVersion.Patch()) +} + +func (o Options) shortDescription() string { + return fmt.Sprintf("Release %s", o.ToVersion.Original()) +} + +func (o Options) date() string { + return time.Now().Format("Jan 2 15:04:05 2006") +} + +// NewGenerator returns the generator to scaffold a migration doc. +func NewGenerator(opts Options) (*genny.Generator, error) { + var ( + g = genny.New() + docTemplate = xgenny.NewEmbedWalker( + fsFiles, + "files/", + opts.Path, + ) + ) + + if err := g.Box(docTemplate); err != nil { + return g, err + } + + ctx := plush.NewContext() + ctx.Set("Position", opts.position()) + ctx.Set("FromVersion", opts.FromVersion.Original()) + ctx.Set("ToVersion", opts.ToVersion.Original()) + ctx.Set("Diffs", opts.Diffs) + ctx.Set("Description", opts.Description) + ctx.Set("ShortDescription", opts.shortDescription()) + ctx.Set("Date", opts.date()) + + plushhelpers.ExtendPlushContext(ctx) + g.Transformer(xgenny.Transformer(ctx)) + g.Transformer(genny.Replace("{{Version}}", opts.ToVersion.Original())) + + return g, nil +} diff --git a/ignite/internal/tools/gen-mig-diffs/templates/doc/files/{{Version}}.md.plush b/ignite/internal/tools/gen-mig-diffs/templates/doc/files/{{Version}}.md.plush new file mode 100644 index 0000000000..09f30733d7 --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/templates/doc/files/{{Version}}.md.plush @@ -0,0 +1,19 @@ +--- +sidebar_position: <%= Position %> +title: <%= ToVersion %> +description: <%= ShortDescription %> +--- + +## **<%= ToVersion %>** + +<%= Description %> + +### **Chain migration diffs** + +<%= Diffs %> + +### **Details** + +- **The CLI tools automatically generated this file**; +- Generated from <%= FromVersion %> to <%= ToVersion %>; +- Generated <%= Date %>; diff --git a/ignite/pkg/xstrings/xstrings_test.go b/ignite/pkg/xstrings/xstrings_test.go index ea52b956df..a54e6b5b5c 100644 --- a/ignite/pkg/xstrings/xstrings_test.go +++ b/ignite/pkg/xstrings/xstrings_test.go @@ -8,6 +8,18 @@ import ( "github.com/ignite/cli/v28/ignite/pkg/xstrings" ) +func TestTitle(t *testing.T) { + require.Equal(t, "Foo", xstrings.Title("foo")) + require.Equal(t, "Foo", xstrings.Title("FOO")) + require.Equal(t, "Foobar", xstrings.Title("fooBar")) +} + +func TestToUpperFirst(t *testing.T) { + require.Equal(t, "Foo", xstrings.ToUpperFirst("foo")) + require.Equal(t, "FOO", xstrings.ToUpperFirst("FOO")) + require.Equal(t, "FooBar", xstrings.ToUpperFirst("fooBar")) +} + func TestNoDash(t *testing.T) { require.Equal(t, "foo", xstrings.NoDash("foo")) require.Equal(t, "foo", xstrings.NoDash("-f-o-o---")) From ee3ff4995414b1d824a11c4816a7eb22e80ef94f Mon Sep 17 00:00:00 2001 From: Pantani Date: Fri, 1 Mar 2024 18:23:48 -0300 Subject: [PATCH 48/69] format the markdown file --- ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go | 6 ++++-- ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go | 3 +-- .../gen-mig-diffs/templates/doc/files/{{Version}}.md.plush | 3 --- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go index 768c7c26cc..06058da2fb 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go @@ -100,9 +100,11 @@ func FormatDiffs(diffs Diffs) ([]byte, error) { buffer := &bytes.Buffer{} for name, diffs := range diffs { buffer.WriteString(fmt.Sprintf("#### **%s diff**\n\n", xstrings.ToUpperFirst(name))) - for _, d := range diffs { + for i, d := range diffs { buffer.WriteString(fmt.Sprint(d)) - buffer.WriteString("\n\n") + if i < len(diffs)-1 { + buffer.WriteString("\n\n") + } } } return buffer.Bytes(), nil diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go index b216f60afc..d738b6c52c 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go @@ -186,8 +186,7 @@ Commit: %[2]v Author: %[3]v Date: %[4]v -%[5]v -`, +%[5]v`, g.To.Original(), tagObj.Hash.String(), tagObj.Tagger.String(), diff --git a/ignite/internal/tools/gen-mig-diffs/templates/doc/files/{{Version}}.md.plush b/ignite/internal/tools/gen-mig-diffs/templates/doc/files/{{Version}}.md.plush index 09f30733d7..cd3599abe3 100644 --- a/ignite/internal/tools/gen-mig-diffs/templates/doc/files/{{Version}}.md.plush +++ b/ignite/internal/tools/gen-mig-diffs/templates/doc/files/{{Version}}.md.plush @@ -7,11 +7,8 @@ description: <%= ShortDescription %> ## **<%= ToVersion %>** <%= Description %> - ### **Chain migration diffs** - <%= Diffs %> - ### **Details** - **The CLI tools automatically generated this file**; From 35279f4ad07e30115d763c36e7b5727a839fe0d0 Mon Sep 17 00:00:00 2001 From: Pantani Date: Fri, 1 Mar 2024 18:28:46 -0300 Subject: [PATCH 49/69] unhandled error --- ignite/internal/tools/gen-mig-diffs/cmd/root.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index d8e08cbc98..ce58d0d326 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -154,6 +154,10 @@ func NewRootCmd() *cobra.Command { Diffs: string(formatedDiffs), Description: releaseDescription, }) + if err != nil { + return errors.Wrap(err, "failed to create the doc generator object") + } + if _, err := xgenny.RunWithValidation(placeholder.New(), g); err != nil { return err } From 4ce3fc62e423b7338c99f4d762d633c4ddf3943e Mon Sep 17 00:00:00 2001 From: Pantani Date: Fri, 1 Mar 2024 18:29:58 -0300 Subject: [PATCH 50/69] fix changelog --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 36922eade2..12640c4e45 100644 --- a/changelog.md +++ b/changelog.md @@ -7,6 +7,7 @@ - [#3977](https://github.com/ignite/cli/pull/3977) Add `chain lint` command to lint the chain's codebase using `golangci-lint` - [#3770](https://github.com/ignite/cli/pull/3770) Add `scaffold configs` and `scaffold params` commands - [#3985](https://github.com/ignite/cli/pull/3985) Make some `cmd` pkg functions public +- [#3718](https://github.com/ignite/cli/pull/3718) Add `gen-mig-diffs` tool app to compare scaffold output of two versions of ignite ### Changes @@ -33,7 +34,6 @@ - [#3835](https://github.com/ignite/cli/pull/3835) Add `--minimal` flag to `scaffold chain` to scaffold a chain with the least amount of sdk modules - [#3820](https://github.com/ignite/cli/pull/3820) Add integration tests for IBC chains - [#3956](https://github.com/ignite/cli/pull/3956) Prepare for wasm app -- [#3718](https://github.com/ignite/cli/pull/3718) Add `gen-mig-diffs` tool app to compare scaffold output of two versions of ignite ### Changes From 82f9b7db0f4558a8c3678a3714b4fdaf79ab6c35 Mon Sep 17 00:00:00 2001 From: Pantani Date: Fri, 1 Mar 2024 18:31:51 -0300 Subject: [PATCH 51/69] markdown breakline --- .../tools/gen-mig-diffs/templates/doc/files/{{Version}}.md.plush | 1 + 1 file changed, 1 insertion(+) diff --git a/ignite/internal/tools/gen-mig-diffs/templates/doc/files/{{Version}}.md.plush b/ignite/internal/tools/gen-mig-diffs/templates/doc/files/{{Version}}.md.plush index cd3599abe3..e250845bef 100644 --- a/ignite/internal/tools/gen-mig-diffs/templates/doc/files/{{Version}}.md.plush +++ b/ignite/internal/tools/gen-mig-diffs/templates/doc/files/{{Version}}.md.plush @@ -8,6 +8,7 @@ description: <%= ShortDescription %> <%= Description %> ### **Chain migration diffs** + <%= Diffs %> ### **Details** From e5d23fd9ba349a0ba303a53e1978bd45ad5247f6 Mon Sep 17 00:00:00 2001 From: Pantani Date: Sat, 2 Mar 2024 16:38:12 -0300 Subject: [PATCH 52/69] add CI to generate migration docs for each release --- .github/workflows/gen-docs-cli.yml | 2 +- .github/workflows/gen-docs-migration.yml | 34 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/gen-docs-migration.yml diff --git a/.github/workflows/gen-docs-cli.yml b/.github/workflows/gen-docs-cli.yml index 2c53a5c34a..dceab21797 100644 --- a/.github/workflows/gen-docs-cli.yml +++ b/.github/workflows/gen-docs-cli.yml @@ -20,7 +20,7 @@ jobs: - name: Create Pull Request id: cpr - uses: peter-evans/create-pull-request@v3 + uses: peter-evans/create-pull-request@v4 with: title: "docs(cli): update generated docs" commit-message: "docs(cli): update generated docs" diff --git a/.github/workflows/gen-docs-migration.yml b/.github/workflows/gen-docs-migration.yml new file mode 100644 index 0000000000..be8dc48597 --- /dev/null +++ b/.github/workflows/gen-docs-migration.yml @@ -0,0 +1,34 @@ +name: Generate Migration Docs +on: + release: + types: [published] + +jobs: + cli: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-go@v4 + with: + go-version: '1.21' + + - name: Generate Scaffold Migration Docs + run: go run ./ignite/internal/tools/gen-mig-diffs/main.go + + - name: Create Pull Request + id: cpr + uses: peter-evans/create-pull-request@v4 + with: + title: "docs(migration): update generated docs" + commit-message: "docs(migration): update generated docs" + body: "" + branch: feat/gen-migration-docs + add-paths: | + docs/ + + - name: Check outputs + run: | + echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" + echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" + From 49d1ee264cb2da12710fb2411378d9af3076b128 Mon Sep 17 00:00:00 2001 From: Pantani Date: Thu, 7 Mar 2024 00:35:48 -0300 Subject: [PATCH 53/69] skip diff if is empty --- ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go index 06058da2fb..07b153f0dc 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go @@ -97,8 +97,14 @@ func SaveDiffs(diffs Diffs, outputPath string) error { // FormatDiffs format all diffs in a single markdown byte array. func FormatDiffs(diffs Diffs) ([]byte, error) { + if len(diffs) == 0 { + return []byte{}, nil + } buffer := &bytes.Buffer{} for name, diffs := range diffs { + if len(diffs) == 0 { + continue + } buffer.WriteString(fmt.Sprintf("#### **%s diff**\n\n", xstrings.ToUpperFirst(name))) for i, d := range diffs { buffer.WriteString(fmt.Sprint(d)) From 29d148d383e3b2523111669727ed641b73fa7b13 Mon Sep 17 00:00:00 2001 From: Pantani Date: Fri, 8 Mar 2024 03:27:20 -0300 Subject: [PATCH 54/69] use script to gen mig file --- .github/workflows/gen-docs-migration.yml | 4 ++-- scripts/gen-mig-diffs | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100755 scripts/gen-mig-diffs diff --git a/.github/workflows/gen-docs-migration.yml b/.github/workflows/gen-docs-migration.yml index be8dc48597..f51b95f2fc 100644 --- a/.github/workflows/gen-docs-migration.yml +++ b/.github/workflows/gen-docs-migration.yml @@ -1,7 +1,7 @@ name: Generate Migration Docs on: release: - types: [published] + types: [ published ] jobs: cli: @@ -14,7 +14,7 @@ jobs: go-version: '1.21' - name: Generate Scaffold Migration Docs - run: go run ./ignite/internal/tools/gen-mig-diffs/main.go + run: ./scripts/gen-mig-diffs - name: Create Pull Request id: cpr diff --git a/scripts/gen-mig-diffs b/scripts/gen-mig-diffs new file mode 100755 index 0000000000..d6e2bfb305 --- /dev/null +++ b/scripts/gen-mig-diffs @@ -0,0 +1,3 @@ +#!/bin/bash + +go run ignite/internal/tools/gen-mig-diffs/*.go From 68c9862663c5b43046a3c973871f7009e7aa73c0 Mon Sep 17 00:00:00 2001 From: Pantani Date: Tue, 19 Mar 2024 22:37:09 +0100 Subject: [PATCH 55/69] fix link for the genesis file --- docs/versioned_docs/version-v0.25/kb/04-genesis.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/versioned_docs/version-v0.25/kb/04-genesis.md b/docs/versioned_docs/version-v0.25/kb/04-genesis.md index d400cb3c30..f4333dcda4 100644 --- a/docs/versioned_docs/version-v0.25/kb/04-genesis.md +++ b/docs/versioned_docs/version-v0.25/kb/04-genesis.md @@ -34,7 +34,7 @@ genesis: ## Genesis file -For genesis file details and field definitions, see Cosmos Hub documentation for the [Genesis File](https://hub.cosmos.network/main/resources/genesis.html). +For genesis file details and field definitions, see Cosmos Hub documentation for the [Genesis File](https://hub.cosmos.network/resources/genesis). ## Genesis block summary From 9a1594215092e29606dd6d3cc39586fa89208ee5 Mon Sep 17 00:00:00 2001 From: Pantani Date: Wed, 20 Mar 2024 13:49:41 +0100 Subject: [PATCH 56/69] use v29 import instead v28 --- ignite/internal/tools/gen-mig-diffs/cmd/root.go | 16 ++++++++-------- ignite/internal/tools/gen-mig-diffs/main.go | 2 +- .../tools/gen-mig-diffs/pkg/diff/diff.go | 4 ++-- .../tools/gen-mig-diffs/pkg/repo/repo.go | 8 ++++---- .../tools/gen-mig-diffs/pkg/scaffold/cache.go | 4 ++-- .../tools/gen-mig-diffs/pkg/scaffold/commands.go | 2 +- .../tools/gen-mig-diffs/pkg/scaffold/scaffold.go | 6 +++--- .../tools/gen-mig-diffs/templates/doc/doc.go | 4 ++-- ignite/pkg/diff/compute.go | 2 +- ignite/pkg/diff/compute_test.go | 2 +- ignite/pkg/diff/subtract_test.go | 2 +- ignite/services/chain/init.go | 2 +- 12 files changed, 27 insertions(+), 27 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index ce58d0d326..4c1675b5cd 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -7,14 +7,14 @@ import ( "github.com/Masterminds/semver/v3" "github.com/spf13/cobra" - "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/pkg/diff" - "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/pkg/repo" - "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/pkg/scaffold" - "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/templates/doc" - "github.com/ignite/cli/v28/ignite/pkg/cliui" - "github.com/ignite/cli/v28/ignite/pkg/errors" - "github.com/ignite/cli/v28/ignite/pkg/placeholder" - "github.com/ignite/cli/v28/ignite/pkg/xgenny" + "github.com/ignite/cli/v29/ignite/internal/tools/gen-mig-diffs/pkg/diff" + "github.com/ignite/cli/v29/ignite/internal/tools/gen-mig-diffs/pkg/repo" + "github.com/ignite/cli/v29/ignite/internal/tools/gen-mig-diffs/pkg/scaffold" + "github.com/ignite/cli/v29/ignite/internal/tools/gen-mig-diffs/templates/doc" + "github.com/ignite/cli/v29/ignite/pkg/cliui" + "github.com/ignite/cli/v29/ignite/pkg/errors" + "github.com/ignite/cli/v29/ignite/pkg/placeholder" + "github.com/ignite/cli/v29/ignite/pkg/xgenny" ) const ( diff --git a/ignite/internal/tools/gen-mig-diffs/main.go b/ignite/internal/tools/gen-mig-diffs/main.go index 4b549f7df9..414d2411f3 100644 --- a/ignite/internal/tools/gen-mig-diffs/main.go +++ b/ignite/internal/tools/gen-mig-diffs/main.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/ignite/cli/v28/ignite/internal/tools/gen-mig-diffs/cmd" + "github.com/ignite/cli/v29/ignite/internal/tools/gen-mig-diffs/cmd" ) func main() { diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go index 07b153f0dc..72cf290006 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go @@ -8,8 +8,8 @@ import ( "github.com/hexops/gotextdiff" - "github.com/ignite/cli/v28/ignite/pkg/diff" - "github.com/ignite/cli/v28/ignite/pkg/xstrings" + "github.com/ignite/cli/v29/ignite/pkg/diff" + "github.com/ignite/cli/v29/ignite/pkg/xstrings" ) type Diffs map[string][]gotextdiff.Unified diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go index d738b6c52c..c9c8eb7c46 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go @@ -12,10 +12,10 @@ import ( "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" - "github.com/ignite/cli/v28/ignite/pkg/cliui" - "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/exec" - "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/step" - "github.com/ignite/cli/v28/ignite/pkg/errors" + "github.com/ignite/cli/v29/ignite/pkg/cliui" + "github.com/ignite/cli/v29/ignite/pkg/cmdrunner/exec" + "github.com/ignite/cli/v29/ignite/pkg/cmdrunner/step" + "github.com/ignite/cli/v29/ignite/pkg/errors" ) const ( diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go index 17c1445caa..f63dc34813 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go @@ -5,8 +5,8 @@ import ( "path/filepath" "sync" - "github.com/ignite/cli/v28/ignite/pkg/errors" - "github.com/ignite/cli/v28/ignite/pkg/xos" + "github.com/ignite/cli/v29/ignite/pkg/errors" + "github.com/ignite/cli/v29/ignite/pkg/xos" ) // cache represents a cache for executed scaffold command. diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go index 18a9a0e215..69725e899a 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/commands.go @@ -1,6 +1,6 @@ package scaffold -import "github.com/ignite/cli/v28/ignite/pkg/errors" +import "github.com/ignite/cli/v29/ignite/pkg/errors" type ( // Command represents a set of command and prerequisites scaffold command that are required to run before them. diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go index 34e7fac2ab..24d312ac10 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go @@ -8,9 +8,9 @@ import ( "github.com/Masterminds/semver/v3" - "github.com/ignite/cli/v28/ignite/pkg/cmdrunner/exec" - "github.com/ignite/cli/v28/ignite/pkg/errors" - "github.com/ignite/cli/v28/ignite/pkg/randstr" + "github.com/ignite/cli/v29/ignite/pkg/cmdrunner/exec" + "github.com/ignite/cli/v29/ignite/pkg/errors" + "github.com/ignite/cli/v29/ignite/pkg/randstr" ) var v027 = semver.MustParse("v0.27.0") diff --git a/ignite/internal/tools/gen-mig-diffs/templates/doc/doc.go b/ignite/internal/tools/gen-mig-diffs/templates/doc/doc.go index ae0bf0315e..707ec95fb1 100644 --- a/ignite/internal/tools/gen-mig-diffs/templates/doc/doc.go +++ b/ignite/internal/tools/gen-mig-diffs/templates/doc/doc.go @@ -9,8 +9,8 @@ import ( "github.com/gobuffalo/genny/v2" "github.com/gobuffalo/plush/v4" - "github.com/ignite/cli/v28/ignite/pkg/xgenny" - "github.com/ignite/cli/v28/ignite/templates/field/plushhelpers" + "github.com/ignite/cli/v29/ignite/pkg/xgenny" + "github.com/ignite/cli/v29/ignite/templates/field/plushhelpers" ) //go:embed files/* diff --git a/ignite/pkg/diff/compute.go b/ignite/pkg/diff/compute.go index ca24775267..02549d0477 100644 --- a/ignite/pkg/diff/compute.go +++ b/ignite/pkg/diff/compute.go @@ -11,7 +11,7 @@ import ( "github.com/hexops/gotextdiff/myers" "github.com/hexops/gotextdiff/span" - "github.com/ignite/cli/v28/ignite/pkg/errors" + "github.com/ignite/cli/v29/ignite/pkg/errors" ) // ComputeFS computes the unified diffs between the origin and modified filesystems. diff --git a/ignite/pkg/diff/compute_test.go b/ignite/pkg/diff/compute_test.go index 32fe7f5b75..7549d5ac71 100644 --- a/ignite/pkg/diff/compute_test.go +++ b/ignite/pkg/diff/compute_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/ignite/cli/v28/ignite/pkg/diff" + "github.com/ignite/cli/v29/ignite/pkg/diff" ) func TestComputeFS(t *testing.T) { diff --git a/ignite/pkg/diff/subtract_test.go b/ignite/pkg/diff/subtract_test.go index 8e072e5ee1..49a50c527d 100644 --- a/ignite/pkg/diff/subtract_test.go +++ b/ignite/pkg/diff/subtract_test.go @@ -6,7 +6,7 @@ import ( "github.com/hexops/gotextdiff" - "github.com/ignite/cli/v28/ignite/pkg/diff" + "github.com/ignite/cli/v29/ignite/pkg/diff" ) func TestSubtract(t *testing.T) { diff --git a/ignite/services/chain/init.go b/ignite/services/chain/init.go index ea89936f63..863b58c6b0 100644 --- a/ignite/services/chain/init.go +++ b/ignite/services/chain/init.go @@ -9,7 +9,7 @@ import ( "github.com/imdario/mergo" chainconfig "github.com/ignite/cli/v29/ignite/config/chain" - "github.com/ignite/cli/v29/ignite/internal/plugin" + plugininternal "github.com/ignite/cli/v29/ignite/internal/plugin" chaincmdrunner "github.com/ignite/cli/v29/ignite/pkg/chaincmd/runner" "github.com/ignite/cli/v29/ignite/pkg/cliui/view/accountview" "github.com/ignite/cli/v29/ignite/pkg/confile" From 935b55e5056972d83622ca2070fff96010c80ca4 Mon Sep 17 00:00:00 2001 From: Pantani Date: Fri, 29 Mar 2024 03:01:17 +0100 Subject: [PATCH 57/69] add new xgenny runner --- ignite/internal/tools/gen-mig-diffs/cmd/root.go | 6 +++--- ignite/pkg/xgenny/runner.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 4c1675b5cd..bd2853a776 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -13,7 +13,6 @@ import ( "github.com/ignite/cli/v29/ignite/internal/tools/gen-mig-diffs/templates/doc" "github.com/ignite/cli/v29/ignite/pkg/cliui" "github.com/ignite/cli/v29/ignite/pkg/errors" - "github.com/ignite/cli/v29/ignite/pkg/placeholder" "github.com/ignite/cli/v29/ignite/pkg/xgenny" ) @@ -158,11 +157,12 @@ func NewRootCmd() *cobra.Command { return errors.Wrap(err, "failed to create the doc generator object") } - if _, err := xgenny.RunWithValidation(placeholder.New(), g); err != nil { + sm, err := xgenny.NewRunner(cmd.Context(), output).RunAndApply(g) + if err != nil { return err } - session.Printf("Migration doc generated successfully at %s\n", output) + session.EventBus().SendInfo(fmt.Sprintf("Migration doc generated successfully at %s\n%s", output, sm)) return nil }, diff --git a/ignite/pkg/xgenny/runner.go b/ignite/pkg/xgenny/runner.go index 5b7e2de0fb..93e4efbcb5 100644 --- a/ignite/pkg/xgenny/runner.go +++ b/ignite/pkg/xgenny/runner.go @@ -22,12 +22,12 @@ type Runner struct { } // NewRunner is a xgenny Runner with a logger. -func NewRunner(ctx context.Context, appPath string) *Runner { +func NewRunner(ctx context.Context, root string) *Runner { var ( runner = genny.WetRunner(ctx) tmpPath = filepath.Join(os.TempDir(), randstr.Runes(5)) ) - runner.Root = appPath + runner.Root = root r := &Runner{ ctx: ctx, Runner: runner, From 503e69ca47c99c6fd4693f1d41f8a6080f82ee42 Mon Sep 17 00:00:00 2001 From: Pantani Date: Fri, 29 Mar 2024 03:38:55 +0100 Subject: [PATCH 58/69] improve logs --- ignite/internal/tools/gen-mig-diffs/cmd/root.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index bd2853a776..c33969144a 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -162,7 +162,12 @@ func NewRootCmd() *cobra.Command { return err } - session.EventBus().SendInfo(fmt.Sprintf("Migration doc generated successfully at %s\n%s", output, sm)) + if len(sm.CreatedFiles()) == 0 { + return errors.Errorf("migration doc not created at %s", output) + } + session.EventBus().SendInfo( + fmt.Sprintf("Migration doc generated successfully at %s", sm.CreatedFiles()[0]), + ) return nil }, From e46e01d1b1a201692834a14a02f44eca53673aff Mon Sep 17 00:00:00 2001 From: Danilo Pantani Date: Mon, 1 Apr 2024 21:59:12 +0200 Subject: [PATCH 59/69] Update ignite/internal/tools/gen-mig-diffs/cmd/root.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jerónimo Albi --- ignite/internal/tools/gen-mig-diffs/cmd/root.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index c33969144a..117fd68097 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -181,7 +181,7 @@ func NewRootCmd() *cobra.Command { cmd.Flags().String(flagRepoOutput, "", "Output path to clone the ignite repository") cmd.Flags().Bool(flagRepoCleanup, true, "Cleanup the repository path after use") cmd.Flags().String(flagScaffoldOutput, "", "Output path to clone the ignite repository") - cmd.Flags().String(flagScaffoldCache, "", "Output path to clone the ignite repository") + cmd.Flags().String(flagScaffoldCache, "", "Path to cache directory") return cmd } From 74dc385ce68767251fdc8d7b1d95b5857df752d9 Mon Sep 17 00:00:00 2001 From: Pantani Date: Wed, 3 Apr 2024 02:47:04 +0200 Subject: [PATCH 60/69] improve the logic if the repo-output already exist --- .../internal/tools/gen-mig-diffs/cmd/root.go | 12 +-- .../tools/gen-mig-diffs/pkg/diff/diff.go | 2 + .../tools/gen-mig-diffs/pkg/repo/repo.go | 94 ++++++++++++++----- 3 files changed, 81 insertions(+), 27 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 117fd68097..3c7df92b2a 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -173,14 +173,14 @@ func NewRootCmd() *cobra.Command { }, } - cmd.Flags().StringP(flagFrom, "f", "", "Version of ignite or path to ignite source code to generate the diff from") - cmd.Flags().StringP(flagTo, "t", "", "Version of ignite or path to ignite source code to generate the diff to") + cmd.Flags().StringP(flagFrom, "f", "", "Version of Ignite or path to Ignite source code to generate the diff from") + cmd.Flags().StringP(flagTo, "t", "", "Version of Ignite or path to Ignite source code to generate the diff to") cmd.Flags().StringP(flagOutput, "o", defaultDocPath, "Output directory to save the migration document") - cmd.Flags().StringP(flagSource, "s", "", "Path to ignite source code repository. Set the source automatically set the cleanup to false") - cmd.Flags().String(flagRepoURL, "", "Git URL for the Ignite repository") - cmd.Flags().String(flagRepoOutput, "", "Output path to clone the ignite repository") + cmd.Flags().StringP(flagSource, "s", "", "Path to Ignite source code repository. Set the source automatically set the cleanup to false") + cmd.Flags().String(flagRepoURL, repo.DefaultRepoURL, "Git URL for the Ignite repository") + cmd.Flags().String(flagRepoOutput, "", "Output path to clone the Ignite repository") cmd.Flags().Bool(flagRepoCleanup, true, "Cleanup the repository path after use") - cmd.Flags().String(flagScaffoldOutput, "", "Output path to clone the ignite repository") + cmd.Flags().String(flagScaffoldOutput, "", "Output path to clone the Ignite repository") cmd.Flags().String(flagScaffoldCache, "", "Path to cache directory") return cmd diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go index 72cf290006..653a17a707 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go @@ -107,7 +107,9 @@ func FormatDiffs(diffs Diffs) ([]byte, error) { } buffer.WriteString(fmt.Sprintf("#### **%s diff**\n\n", xstrings.ToUpperFirst(name))) for i, d := range diffs { + buffer.WriteString("```diff") buffer.WriteString(fmt.Sprint(d)) + buffer.WriteString("```\n") if i < len(diffs)-1 { buffer.WriteString("\n\n") } diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go index c9c8eb7c46..d9a79c0240 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go @@ -7,6 +7,8 @@ import ( "os" "path/filepath" "sort" + "strings" + "time" "github.com/Masterminds/semver/v3" "github.com/go-git/go-git/v5" @@ -19,7 +21,7 @@ import ( ) const ( - defaultRepoURL = "https://github.com/ignite/cli.git" + DefaultRepoURL = "https://github.com/ignite/cli.git" defaultBinaryPath = "dist/ignite" ) @@ -47,14 +49,24 @@ type ( ) // newOptions returns a options with default options. -func newOptions() options { - tmpDir := os.TempDir() +func newOptions() (options, error) { + var ( + tmpDir = os.TempDir() + binPath = filepath.Join(tmpDir, "bin") + output = filepath.Join(tmpDir, "migration-source") + ) + if err := os.RemoveAll(binPath); err != nil { + return options{}, errors.Wrap(err, "failed to clean the output directory") + } + if err := os.RemoveAll(output); err != nil { + return options{}, errors.Wrap(err, "failed to clean the output directory") + } return options{ source: "", binPath: filepath.Join(tmpDir, "bin"), output: filepath.Join(tmpDir, "migration-source"), - repoURL: defaultRepoURL, - } + repoURL: DefaultRepoURL, + }, nil } // WithSource set the repo source Options. @@ -96,7 +108,7 @@ func WithCleanup() Options { // validate options. func (o options) validate() error { - if o.source != "" && (o.repoURL != defaultRepoURL) { + if o.source != "" && (o.repoURL != DefaultRepoURL) { return errors.New("cannot set source and repo URL at the same time") } if o.source != "" && o.cleanup { @@ -108,13 +120,15 @@ func (o options) validate() error { // New creates a new generator for migration diffs between from and to versions of ignite cli // If source is empty, then it clones the ignite cli repository to a temporary directory and uses it as the source. func New(from, to *semver.Version, session *cliui.Session, options ...Options) (*Generator, error) { - opts := newOptions() + opts, err := newOptions() + if err != nil { + return nil, err + } + for _, apply := range options { apply(&opts) } - - err := opts.validate() - if err != nil { + if err := opts.validate(); err != nil { return nil, err } @@ -123,7 +137,7 @@ func New(from, to *semver.Version, session *cliui.Session, options ...Options) ( repo *git.Repository ) if source != "" { - repo, err = git.PlainOpen(source) + repo, err = verifyRepoSource(source, opts.repoURL) if err != nil { return nil, errors.Wrap(err, "failed to open ignite repository") } @@ -134,11 +148,10 @@ func New(from, to *semver.Version, session *cliui.Session, options ...Options) ( session.StartSpinner("Cloning ignite repository...") source = opts.output - if err := os.RemoveAll(source); err != nil { - return nil, errors.Wrap(err, "failed to clean the output directory") - } - repo, err = git.PlainClone(source, false, &git.CloneOptions{URL: opts.repoURL, Depth: 1}) + if errors.Is(err, git.ErrRepositoryAlreadyExists) { + repo, err = verifyRepoSource(source, opts.repoURL) + } if err != nil { return nil, errors.Wrap(err, "failed to clone ignite repository") } @@ -172,15 +185,36 @@ func New(from, to *semver.Version, session *cliui.Session, options ...Options) ( }, nil } +// ReleaseDescription generate the release description based in the tag data, if not exist, from the commit data. func (g *Generator) ReleaseDescription() (string, error) { tag, err := g.repo.Tag(g.To.Original()) if err != nil { return "", errors.Wrapf(err, "failed to get tag %s", g.To.Original()) } + + var ( + author string + date time.Time + msg string + ) tagObj, err := g.repo.TagObject(tag.Hash()) - if err != nil { + switch { + case errors.Is(err, plumbing.ErrObjectNotFound): + commit, err := g.repo.CommitObject(tag.Hash()) + if err != nil { + return "", errors.Wrapf(err, "failed to get commit %s", g.To.Original()) + } + author = commit.Author.String() + date = commit.Author.When + msg = commit.Message + case err != nil: return "", errors.Wrapf(err, "failed to get tag object %s", tag.Hash().String()) + default: + author = tagObj.Tagger.String() + date = tagObj.Tagger.When + msg = tagObj.Message } + description := fmt.Sprintf(`Tag: %[1]v Commit: %[2]v Author: %[3]v @@ -188,12 +222,11 @@ Date: %[4]v %[5]v`, g.To.Original(), - tagObj.Hash.String(), - tagObj.Tagger.String(), - tagObj.Tagger.When.Format("Jan 2 15:04:05 2006"), - tagObj.Message, + tag.Hash().String(), + author, + msg, + date.Format("Jan 2 15:04:05 2006"), ) - return description, nil } @@ -382,3 +415,22 @@ func copyFile(srcPath, dstPath string) error { } return err } + +// verifyRepoSource checks if the repose source path is the same from the provider URL +// and returns the *git.Repository object. +func verifyRepoSource(source, URL string) (*git.Repository, error) { + repo, err := git.PlainOpen(source) + if err != nil { + return nil, errors.Wrap(err, "failed to open ignite repository") + } + remote, err := repo.Remote("origin") + if err != nil { + return nil, errors.Wrap(err, "failed to open ignite repository") + } + for _, remoteURL := range remote.Config().URLs { + if strings.TrimSuffix(URL, ".git") == strings.TrimSuffix(remoteURL, ".git") { + return repo, nil + } + } + return nil, errors.Wrap(err, "repository folder does not match the repo URL") +} From da6dc8d7db0574ab5a2592bca4a669126fb4bdda Mon Sep 17 00:00:00 2001 From: Pantani Date: Wed, 3 Apr 2024 02:50:16 +0200 Subject: [PATCH 61/69] remove repo cleanup flag --- ignite/internal/tools/gen-mig-diffs/cmd/root.go | 6 ------ ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go | 12 +----------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 3c7df92b2a..5e2afcc5b2 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -23,7 +23,6 @@ const ( flagSource = "repo-source" flagRepoURL = "repo-url" flagRepoOutput = "repo-output" - flagRepoCleanup = "repo-cleanup" flagScaffoldOutput = "scaffold-output" flagScaffoldCache = "scaffold-cache" @@ -47,7 +46,6 @@ func NewRootCmd() *cobra.Command { output, _ = cmd.Flags().GetString(flagOutput) repoURL, _ = cmd.Flags().GetString(flagRepoURL) repoOutput, _ = cmd.Flags().GetString(flagRepoOutput) - repoCleanup, _ = cmd.Flags().GetBool(flagRepoCleanup) scaffoldOutput, _ = cmd.Flags().GetString(flagScaffoldOutput) scaffoldCache, _ = cmd.Flags().GetString(flagScaffoldCache) ) @@ -62,9 +60,6 @@ func NewRootCmd() *cobra.Command { // Check or download the source and generate the binaries for each version. repoOptions := make([]repo.Options, 0) - if repoCleanup { - repoOptions = append(repoOptions, repo.WithCleanup()) - } if repoSource != "" { repoOptions = append(repoOptions, repo.WithSource(repoSource)) } @@ -179,7 +174,6 @@ func NewRootCmd() *cobra.Command { cmd.Flags().StringP(flagSource, "s", "", "Path to Ignite source code repository. Set the source automatically set the cleanup to false") cmd.Flags().String(flagRepoURL, repo.DefaultRepoURL, "Git URL for the Ignite repository") cmd.Flags().String(flagRepoOutput, "", "Output path to clone the Ignite repository") - cmd.Flags().Bool(flagRepoCleanup, true, "Cleanup the repository path after use") cmd.Flags().String(flagScaffoldOutput, "", "Output path to clone the Ignite repository") cmd.Flags().String(flagScaffoldCache, "", "Path to cache directory") diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go index d9a79c0240..144cb289a8 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go @@ -42,7 +42,6 @@ type ( output string repoURL string binPath string - cleanup bool } // Options configures the generator. Options func(*options) @@ -73,8 +72,6 @@ func newOptions() (options, error) { func WithSource(source string) Options { return func(o *options) { o.source = source - // Do not clean up if set the source. - o.cleanup = false } } @@ -99,19 +96,12 @@ func WithBinPath(binPath string) Options { } } -// WithCleanup cleanup folders after use. -func WithCleanup() Options { - return func(o *options) { - o.cleanup = true - } -} - // validate options. func (o options) validate() error { if o.source != "" && (o.repoURL != DefaultRepoURL) { return errors.New("cannot set source and repo URL at the same time") } - if o.source != "" && o.cleanup { + if o.source != "" { return errors.New("cannot set source and cleanup the repo") } return nil From 3d05463f7e70ea83b69bf05e0d32759488afded9 Mon Sep 17 00:00:00 2001 From: Pantani Date: Wed, 3 Apr 2024 02:57:48 +0200 Subject: [PATCH 62/69] fix lint issue --- ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go index 144cb289a8..000eab5f52 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/repo/repo.go @@ -408,7 +408,7 @@ func copyFile(srcPath, dstPath string) error { // verifyRepoSource checks if the repose source path is the same from the provider URL // and returns the *git.Repository object. -func verifyRepoSource(source, URL string) (*git.Repository, error) { +func verifyRepoSource(source, url string) (*git.Repository, error) { repo, err := git.PlainOpen(source) if err != nil { return nil, errors.Wrap(err, "failed to open ignite repository") @@ -418,7 +418,7 @@ func verifyRepoSource(source, URL string) (*git.Repository, error) { return nil, errors.Wrap(err, "failed to open ignite repository") } for _, remoteURL := range remote.Config().URLs { - if strings.TrimSuffix(URL, ".git") == strings.TrimSuffix(remoteURL, ".git") { + if strings.TrimSuffix(url, ".git") == strings.TrimSuffix(remoteURL, ".git") { return repo, nil } } From 858d156d82d900bdab76c5095cc575c69db135f8 Mon Sep 17 00:00:00 2001 From: Pantani Date: Wed, 3 Apr 2024 03:12:10 +0200 Subject: [PATCH 63/69] fix diff output format --- ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go index 653a17a707..e3440a5954 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go @@ -106,15 +106,13 @@ func FormatDiffs(diffs Diffs) ([]byte, error) { continue } buffer.WriteString(fmt.Sprintf("#### **%s diff**\n\n", xstrings.ToUpperFirst(name))) - for i, d := range diffs { - buffer.WriteString("```diff") + buffer.WriteString("```diff\n") + for _, d := range diffs { buffer.WriteString(fmt.Sprint(d)) - buffer.WriteString("```\n") - if i < len(diffs)-1 { - buffer.WriteString("\n\n") - } } + buffer.WriteString("```\n\n") } + buffer.WriteString("\n") return buffer.Bytes(), nil } From 7b9f0ace527314113a5df5323b468fc0e948bfa3 Mon Sep 17 00:00:00 2001 From: Pantani Date: Wed, 3 Apr 2024 03:25:00 +0200 Subject: [PATCH 64/69] fix wrong log output --- .../internal/tools/gen-mig-diffs/cmd/root.go | 5 ++-- .../pkg/{scaffold => cache}/cache.go | 24 +++++++++---------- .../gen-mig-diffs/pkg/scaffold/scaffold.go | 15 ++++++------ 3 files changed, 23 insertions(+), 21 deletions(-) rename ignite/internal/tools/gen-mig-diffs/pkg/{scaffold => cache}/cache.go (72%) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 5e2afcc5b2..18c55c2ff3 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -157,11 +157,12 @@ func NewRootCmd() *cobra.Command { return err } - if len(sm.CreatedFiles()) == 0 { + files := append(sm.CreatedFiles(), sm.ModifiedFiles()...) + if len(files) == 0 { return errors.Errorf("migration doc not created at %s", output) } session.EventBus().SendInfo( - fmt.Sprintf("Migration doc generated successfully at %s", sm.CreatedFiles()[0]), + fmt.Sprintf("Migration doc generated successfully at %s", files[0]), ) return nil diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go b/ignite/internal/tools/gen-mig-diffs/pkg/cache/cache.go similarity index 72% rename from ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go rename to ignite/internal/tools/gen-mig-diffs/pkg/cache/cache.go index f63dc34813..3804d5c766 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/cache.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/cache/cache.go @@ -1,4 +1,4 @@ -package scaffold +package cache import ( "os" @@ -9,23 +9,23 @@ import ( "github.com/ignite/cli/v29/ignite/pkg/xos" ) -// cache represents a cache for executed scaffold command. -type cache struct { +// Cache represents a cache for executed scaffold command. +type Cache struct { cachePath string cachesPath map[string]string mu sync.RWMutex } -// newCache initializes a new Cache instance. -func newCache(path string) (*cache, error) { - return &cache{ +// New initializes a new Cache instance. +func New(path string) (*Cache, error) { + return &Cache{ cachePath: path, cachesPath: make(map[string]string), }, os.MkdirAll(path, os.ModePerm) } -// save creates a new cache. -func (c *cache) save(name, path string) error { +// Save creates a new cache. +func (c *Cache) Save(name, path string) error { c.mu.Lock() defer c.mu.Unlock() @@ -38,8 +38,8 @@ func (c *cache) save(name, path string) error { return nil } -// has return if the cache exist. -func (c *cache) has(name string) bool { +// Has return if the cache exist. +func (c *Cache) Has(name string) bool { c.mu.RLock() defer c.mu.RUnlock() @@ -54,8 +54,8 @@ func (c *cache) has(name string) bool { return true } -// get return the cache path and copy all files to the destination path. -func (c *cache) get(name, dstPath string) error { +// Get return the cache path and copy all files to the destination path. +func (c *Cache) Get(name, dstPath string) error { c.mu.RLock() defer c.mu.RUnlock() diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go index 24d312ac10..9a67f7feb8 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go @@ -8,6 +8,7 @@ import ( "github.com/Masterminds/semver/v3" + "github.com/ignite/cli/v29/ignite/internal/tools/gen-mig-diffs/pkg/cache" "github.com/ignite/cli/v29/ignite/pkg/cmdrunner/exec" "github.com/ignite/cli/v29/ignite/pkg/errors" "github.com/ignite/cli/v29/ignite/pkg/randstr" @@ -21,7 +22,7 @@ type ( Output string binary string version *semver.Version - cache *cache + cache *cache.Cache cachePath string commandList Commands } @@ -79,7 +80,7 @@ func New(binary string, ver *semver.Version, options ...Options) (*Scaffold, err return nil, err } - c, err := newCache(opts.cachePath) + c, err := cache.New(opts.cachePath) if err != nil { return nil, err } @@ -131,8 +132,8 @@ func (s *Scaffold) runCommand(ctx context.Context, name string, command Command) return errors.Wrapf(err, "pre-requisite command %s from %s not found", command.Prerequisite, name) } - if s.cache.has(command.Prerequisite) { - if err := s.cache.get(command.Prerequisite, path); err != nil { + if s.cache.Has(command.Prerequisite) { + if err := s.cache.Get(command.Prerequisite, path); err != nil { return errors.Wrapf(err, "failed to get cache key %s", command.Prerequisite) } } else { @@ -147,7 +148,7 @@ func (s *Scaffold) runCommand(ctx context.Context, name string, command Command) return err } } - return s.cache.save(command.Name, path) + return s.cache.Save(command.Name, path) } func (s *Scaffold) executeScaffold(ctx context.Context, cmd, path string) error { @@ -165,7 +166,7 @@ func (s *Scaffold) executeScaffold(ctx context.Context, cmd, path string) error // order to compensate for differences in versions. func applyPreExecuteExceptions(ver *semver.Version, args []string) []string { // In versions <0.27.0, "scaffold chain" command always creates a new directory with the - // name of chain at the given '--path' so we need to append "example" to the path if the + // name of chain at the given '--path', so we need to append "example" to the path if the // command is not "chain". if ver.LessThan(v027) && args[2] != "chain" { args[len(args)-1] = filepath.Join(args[len(args)-1], "example") @@ -177,7 +178,7 @@ func applyPreExecuteExceptions(ver *semver.Version, args []string) []string { // they have been executed in order to compensate for differences in versions. func applyPostScaffoldExceptions(ver *semver.Version, name string, output string) error { // In versions <0.27.0, "scaffold chain" command always creates a new directory with the name of - // chain at the given --path so we need to move the directory to the parent directory. + // chain at the given '--path', so we need to move the directory to the parent directory. if ver.LessThan(v027) { if err := os.Rename(filepath.Join(output, name, "example"), filepath.Join(output, "example_tmp")); err != nil { return errors.Wrapf(err, "failed to move %s directory to tmp directory", name) From 561a4d9dc38db3916739bcd06b9119c30678a453 Mon Sep 17 00:00:00 2001 From: Pantani Date: Wed, 3 Apr 2024 03:28:22 +0200 Subject: [PATCH 65/69] improve md format --- ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go | 1 - 1 file changed, 1 deletion(-) diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go index e3440a5954..9987d6d7db 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go @@ -112,7 +112,6 @@ func FormatDiffs(diffs Diffs) ([]byte, error) { } buffer.WriteString("```\n\n") } - buffer.WriteString("\n") return buffer.Bytes(), nil } From b409a88562cf7db8141115f9ab2a8826f93075d3 Mon Sep 17 00:00:00 2001 From: Pantani Date: Sat, 6 Apr 2024 04:48:51 +0200 Subject: [PATCH 66/69] create a go.mod for the diff tool --- go.mod | 5 +- go.sum | 2 - .../internal/tools/gen-mig-diffs/cmd/root.go | 9 +- ignite/internal/tools/gen-mig-diffs/go.mod | 93 +++++ ignite/internal/tools/gen-mig-diffs/go.sum | 325 ++++++++++++++++++ ignite/internal/tools/gen-mig-diffs/main.go | 2 +- .../tools/gen-mig-diffs}/pkg/diff/compute.go | 4 +- .../gen-mig-diffs}/pkg/diff/compute_test.go | 8 +- .../tools/gen-mig-diffs/pkg/diff/diff.go | 5 +- .../tools/gen-mig-diffs}/pkg/diff/subtract.go | 4 +- .../gen-mig-diffs}/pkg/diff/subtract_test.go | 8 +- .../gen-mig-diffs/pkg/scaffold/scaffold.go | 3 +- 12 files changed, 440 insertions(+), 28 deletions(-) create mode 100644 ignite/internal/tools/gen-mig-diffs/go.mod create mode 100644 ignite/internal/tools/gen-mig-diffs/go.sum rename ignite/{ => internal/tools/gen-mig-diffs}/pkg/diff/compute.go (95%) rename ignite/{ => internal/tools/gen-mig-diffs}/pkg/diff/compute_test.go (86%) rename ignite/{ => internal/tools/gen-mig-diffs}/pkg/diff/subtract.go (96%) rename ignite/{ => internal/tools/gen-mig-diffs}/pkg/diff/subtract_test.go (95%) diff --git a/go.mod b/go.mod index 765aeb45ad..01de6d0972 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,6 @@ require ( github.com/99designs/keyring v1.2.2 github.com/AlecAivazis/survey/v2 v2.3.7 github.com/DATA-DOG/go-sqlmock v1.5.0 - github.com/Masterminds/semver/v3 v3.2.0 github.com/blang/semver/v4 v4.0.0 github.com/briandowns/spinner v1.23.0 github.com/bufbuild/buf v1.29.0 @@ -46,7 +45,6 @@ require ( github.com/gobuffalo/genny/v2 v2.1.0 github.com/gobuffalo/packd v1.0.2 github.com/gobuffalo/plush/v4 v4.1.19 - github.com/gobwas/glob v0.2.3 github.com/goccy/go-yaml v1.11.2 github.com/golangci/golangci-lint v1.55.2 github.com/google/go-github/v48 v48.2.0 @@ -55,7 +53,6 @@ require ( github.com/gorilla/rpc v1.2.1 github.com/hashicorp/go-hclog v1.5.0 github.com/hashicorp/go-plugin v1.6.0 - github.com/hexops/gotextdiff v1.0.3 github.com/iancoleman/strcase v0.3.0 github.com/ignite/ignite-files/nodetime v0.0.4 github.com/ignite/ignite-files/protoc v0.0.1 @@ -248,6 +245,7 @@ require ( github.com/gobuffalo/logger v1.0.7 // indirect github.com/gobuffalo/tags/v3 v3.1.4 // indirect github.com/gobuffalo/validate/v3 v3.3.3 // indirect + github.com/gobwas/glob v0.2.3 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect @@ -296,6 +294,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.1.0 // indirect + github.com/hexops/gotextdiff v1.0.3 // indirect github.com/huandu/skiplist v1.2.0 // indirect github.com/huandu/xstrings v1.4.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect diff --git a/go.sum b/go.sum index a69c70c86d..fc48d7e1a6 100644 --- a/go.sum +++ b/go.sum @@ -119,8 +119,6 @@ github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0/go.mod h1:rZLTje5A9kFBe0 github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= -github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 18c55c2ff3..8ced9ee4fe 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -7,13 +7,14 @@ import ( "github.com/Masterminds/semver/v3" "github.com/spf13/cobra" - "github.com/ignite/cli/v29/ignite/internal/tools/gen-mig-diffs/pkg/diff" - "github.com/ignite/cli/v29/ignite/internal/tools/gen-mig-diffs/pkg/repo" - "github.com/ignite/cli/v29/ignite/internal/tools/gen-mig-diffs/pkg/scaffold" - "github.com/ignite/cli/v29/ignite/internal/tools/gen-mig-diffs/templates/doc" "github.com/ignite/cli/v29/ignite/pkg/cliui" "github.com/ignite/cli/v29/ignite/pkg/errors" "github.com/ignite/cli/v29/ignite/pkg/xgenny" + + "github.com/ignite/mig-diffs/pkg/diff" + "github.com/ignite/mig-diffs/pkg/repo" + "github.com/ignite/mig-diffs/pkg/scaffold" + "github.com/ignite/mig-diffs/templates/doc" ) const ( diff --git a/ignite/internal/tools/gen-mig-diffs/go.mod b/ignite/internal/tools/gen-mig-diffs/go.mod new file mode 100644 index 0000000000..0f29fe5d19 --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/go.mod @@ -0,0 +1,93 @@ +module github.com/ignite/mig-diffs + +go 1.22.2 + +replace github.com/ignite/cli/v29 => ../../../../ + +require ( + github.com/Masterminds/semver/v3 v3.2.1 + github.com/go-git/go-git/v5 v5.12.0 + github.com/gobuffalo/genny/v2 v2.1.0 + github.com/gobuffalo/plush/v4 v4.1.19 + github.com/gobwas/glob v0.2.3 + github.com/hexops/gotextdiff v1.0.3 + github.com/ignite/cli/v29 v29.0.0-00010101000000-000000000000 + github.com/spf13/cobra v1.8.0 + github.com/stretchr/testify v1.9.0 +) + +require ( + dario.cat/mergo v1.0.0 // indirect + github.com/AlecAivazis/survey/v2 v2.3.7 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/ProtonMail/go-crypto v1.0.0 // indirect + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/briandowns/spinner v1.23.0 // indirect + github.com/charmbracelet/lipgloss v0.6.0 // indirect + github.com/chzyer/readline v1.5.1 // indirect + github.com/cloudflare/circl v1.3.7 // indirect + github.com/cockroachdb/errors v1.11.1 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cyphar/filepath-securejoin v0.2.4 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/proto v1.12.2 // indirect + github.com/emicklei/proto-contrib v0.15.0 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/fatih/color v1.15.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/getsentry/sentry-go v0.27.0 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/gobuffalo/flect v0.3.0 // indirect + github.com/gobuffalo/github_flavored_markdown v1.1.4 // indirect + github.com/gobuffalo/helpers v0.6.7 // indirect + github.com/gobuffalo/logger v1.0.7 // indirect + github.com/gobuffalo/packd v1.0.2 // indirect + github.com/gobuffalo/tags/v3 v3.1.4 // indirect + github.com/gobuffalo/validate/v3 v3.3.3 // indirect + github.com/gofrs/uuid v4.4.0+incompatible // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/manifoldco/promptui v0.9.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect + github.com/microcosm-cc/bluemonday v1.0.23 // indirect + github.com/muesli/reflow v0.3.0 // indirect + github.com/muesli/termenv v0.15.1 // indirect + github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/rivo/uniseg v0.4.4 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/skeema/knownhosts v1.2.2 // indirect + github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d // indirect + github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect + golang.org/x/mod v0.15.0 // indirect + golang.org/x/net v0.22.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.18.0 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/ignite/internal/tools/gen-mig-diffs/go.sum b/ignite/internal/tools/gen-mig-diffs/go.sum new file mode 100644 index 0000000000..bfde45b02a --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/go.sum @@ -0,0 +1,325 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= +github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= +github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= +github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= +github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A= +github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/charmbracelet/lipgloss v0.6.0 h1:1StyZB9vBSOyuZxQUcUwGr17JmojPNm87inij9N3wJY= +github.com/charmbracelet/lipgloss v0.6.0/go.mod h1:tHh2wr34xcHjC2HCXIlGSG1jaDF0S0atAUvBMP6Ppuk= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= +github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= +github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/emicklei/proto v1.12.2 h1:ZDyDzrfMt7ncmyor/j07uoOCGLKtU5F87vTPwIzLe/o= +github.com/emicklei/proto v1.12.2/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= +github.com/emicklei/proto-contrib v0.15.0 h1:5D8JKpV1qekMDFwEJp8NVJGY1We6t14dn9D4G05fpyo= +github.com/emicklei/proto-contrib v0.15.0/go.mod h1:p6zmoy14hFYiwUb35X7nJ4u4l1vfvjc1mWrIt8QB3kw= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= +github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= +github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= +github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= +github.com/gobuffalo/flect v0.3.0 h1:erfPWM+K1rFNIQeRPdeEXxo8yFr/PO17lhRnS8FUrtk= +github.com/gobuffalo/flect v0.3.0/go.mod h1:5pf3aGnsvqvCj50AVni7mJJF8ICxGZ8HomberC3pXLE= +github.com/gobuffalo/genny/v2 v2.1.0 h1:cCRBbqzo3GfNvj3UetD16zRgUvWFEyyl0qTqquuIqOM= +github.com/gobuffalo/genny/v2 v2.1.0/go.mod h1:4yoTNk4bYuP3BMM6uQKYPvtP6WsXFGm2w2EFYZdRls8= +github.com/gobuffalo/github_flavored_markdown v1.1.3/go.mod h1:IzgO5xS6hqkDmUh91BW/+Qxo/qYnvfzoz3A7uLkg77I= +github.com/gobuffalo/github_flavored_markdown v1.1.4 h1:WacrEGPXUDX+BpU1GM/Y0ADgMzESKNWls9hOTG1MHVs= +github.com/gobuffalo/github_flavored_markdown v1.1.4/go.mod h1:Vl9686qrVVQou4GrHRK/KOG3jCZOKLUqV8MMOAYtlso= +github.com/gobuffalo/helpers v0.6.7 h1:C9CedoRSfgWg2ZoIkVXgjI5kgmSpL34Z3qdnzpfNVd8= +github.com/gobuffalo/helpers v0.6.7/go.mod h1:j0u1iC1VqlCaJEEVkZN8Ia3TEzfj/zoXANqyJExTMTA= +github.com/gobuffalo/logger v1.0.7 h1:LTLwWelETXDYyqF/ASf0nxaIcdEOIJNxRokPcfI/xbU= +github.com/gobuffalo/logger v1.0.7/go.mod h1:u40u6Bq3VVvaMcy5sRBclD8SXhBYPS0Qk95ubt+1xJM= +github.com/gobuffalo/packd v1.0.2 h1:Yg523YqnOxGIWCp69W12yYBKsoChwI7mtu6ceM9Bwfw= +github.com/gobuffalo/packd v1.0.2/go.mod h1:sUc61tDqGMXON80zpKGp92lDb86Km28jfvX7IAyxFT8= +github.com/gobuffalo/plush/v4 v4.1.16/go.mod h1:6t7swVsarJ8qSLw1qyAH/KbrcSTwdun2ASEQkOznakg= +github.com/gobuffalo/plush/v4 v4.1.19 h1:o0E5gEJw+ozkAwQoCeiaWC6VOU2lEmX+GhtGkwpqZ8o= +github.com/gobuffalo/plush/v4 v4.1.19/go.mod h1:WiKHJx3qBvfaDVlrv8zT7NCd3dEMaVR/fVxW4wqV17M= +github.com/gobuffalo/tags/v3 v3.1.4 h1:X/ydLLPhgXV4h04Hp2xlbI2oc5MDaa7eub6zw8oHjsM= +github.com/gobuffalo/tags/v3 v3.1.4/go.mod h1:ArRNo3ErlHO8BtdA0REaZxijuWnWzF6PUXngmMXd2I0= +github.com/gobuffalo/validate/v3 v3.3.3 h1:o7wkIGSvZBYBd6ChQoLxkz2y1pfmhbI4jNJYh6PuNJ4= +github.com/gobuffalo/validate/v3 v3.3.3/go.mod h1:YC7FsbJ/9hW/VjQdmXPvFqvRis4vrRYFxr69WiNZw6g= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= +github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= +github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= +github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/microcosm-cc/bluemonday v1.0.20/go.mod h1:yfBmMi8mxvaZut3Yytv+jTXRY8mxyjJ0/kQBTElld50= +github.com/microcosm-cc/bluemonday v1.0.22/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM= +github.com/microcosm-cc/bluemonday v1.0.23 h1:SMZe2IGa0NuHvnVNAZ+6B38gsTbi5e4sViiWJyDDqFY= +github.com/microcosm-cc/bluemonday v1.0.23/go.mod h1:mN70sk7UkkF8TUr2IGBpNN0jAgStuPzlK76QuruE/z4= +github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ= +github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= +github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= +github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= +github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs= +github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= +github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d h1:yKm7XZV6j9Ev6lojP2XaIshpT4ymkqhMeSghO5Ps00E= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e h1:qpG93cPwA5f7s/ZPBJnGOYQNK/vKsaDaseuKT5Asee8= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/ignite/internal/tools/gen-mig-diffs/main.go b/ignite/internal/tools/gen-mig-diffs/main.go index 414d2411f3..7b10252d29 100644 --- a/ignite/internal/tools/gen-mig-diffs/main.go +++ b/ignite/internal/tools/gen-mig-diffs/main.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/ignite/cli/v29/ignite/internal/tools/gen-mig-diffs/cmd" + "github.com/ignite/mig-diffs/cmd" ) func main() { diff --git a/ignite/pkg/diff/compute.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/compute.go similarity index 95% rename from ignite/pkg/diff/compute.go rename to ignite/internal/tools/gen-mig-diffs/pkg/diff/compute.go index 02549d0477..b1ae925e03 100644 --- a/ignite/pkg/diff/compute.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/compute.go @@ -14,9 +14,9 @@ import ( "github.com/ignite/cli/v29/ignite/pkg/errors" ) -// ComputeFS computes the unified diffs between the origin and modified filesystems. +// computeFS computes the unified diffs between the origin and modified filesystems. // but ignores files that match the given globs. -func ComputeFS(origin, modified fs.FS, ignoreGlobs ...string) ([]gotextdiff.Unified, error) { +func computeFS(origin, modified fs.FS, ignoreGlobs ...string) ([]gotextdiff.Unified, error) { compiledGlobs, err := compileGlobs(ignoreGlobs) if err != nil { return nil, err diff --git a/ignite/pkg/diff/compute_test.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/compute_test.go similarity index 86% rename from ignite/pkg/diff/compute_test.go rename to ignite/internal/tools/gen-mig-diffs/pkg/diff/compute_test.go index 7549d5ac71..01b3968180 100644 --- a/ignite/pkg/diff/compute_test.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/compute_test.go @@ -1,12 +1,10 @@ -package diff_test +package diff import ( "testing" "testing/fstest" "github.com/stretchr/testify/require" - - "github.com/ignite/cli/v29/ignite/pkg/diff" ) func TestComputeFS(t *testing.T) { @@ -38,7 +36,7 @@ func TestComputeFS(t *testing.T) { }, } - unified, err := diff.ComputeFS(origin, modified) + unified, err := computeFS(origin, modified) require.NoError(err) require.Len(unified, 3) expectedFiles := []string{"foo.txt", "new.txt", "pkg/main.go"} @@ -47,7 +45,7 @@ func TestComputeFS(t *testing.T) { } // Test ignoring files - unified, err = diff.ComputeFS(origin, modified, "**.go") + unified, err = computeFS(origin, modified, "**.go") require.NoError(err) require.Len(unified, 2) expectedFiles = []string{"foo.txt", "new.txt"} diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go index 9987d6d7db..b66b7a1ced 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/diff.go @@ -8,7 +8,6 @@ import ( "github.com/hexops/gotextdiff" - "github.com/ignite/cli/v29/ignite/pkg/diff" "github.com/ignite/cli/v29/ignite/pkg/xstrings" ) @@ -58,7 +57,7 @@ func CalculateDiffs(fromDir, toDir string) (Diffs, error) { return nil, err } - computedDiff, err := diff.ComputeFS( + computedDiff, err := computeFS( os.DirFS(from), os.DirFS(to), diffIgnoreGlobs..., @@ -147,7 +146,7 @@ func subtractUnifieds(a, b []gotextdiff.Unified) []gotextdiff.Unified { for i, ad := range a { for _, bd := range b { if ad.From == bd.From && ad.To == bd.To { - a[i] = diff.Subtract(ad, bd) + a[i] = subtract(ad, bd) } } } diff --git a/ignite/pkg/diff/subtract.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/subtract.go similarity index 96% rename from ignite/pkg/diff/subtract.go rename to ignite/internal/tools/gen-mig-diffs/pkg/diff/subtract.go index 23da396b15..f80edcd513 100644 --- a/ignite/pkg/diff/subtract.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/subtract.go @@ -6,8 +6,8 @@ import ( "github.com/hexops/gotextdiff" ) -// Subtract two unified diffs from each other. -func Subtract(a, b gotextdiff.Unified) gotextdiff.Unified { +// subtract two unified diffs from each other. +func subtract(a, b gotextdiff.Unified) gotextdiff.Unified { return gotextdiff.Unified{ From: a.From, To: a.To, diff --git a/ignite/pkg/diff/subtract_test.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/subtract_test.go similarity index 95% rename from ignite/pkg/diff/subtract_test.go rename to ignite/internal/tools/gen-mig-diffs/pkg/diff/subtract_test.go index 49a50c527d..78d2a64426 100644 --- a/ignite/pkg/diff/subtract_test.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/subtract_test.go @@ -1,12 +1,10 @@ -package diff_test +package diff import ( "reflect" "testing" "github.com/hexops/gotextdiff" - - "github.com/ignite/cli/v29/ignite/pkg/diff" ) func TestSubtract(t *testing.T) { @@ -172,8 +170,8 @@ func TestSubtract(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := diff.Subtract(tt.args.a, tt.args.b); !reflect.DeepEqual(got, tt.want) { - t.Errorf("Subtract() = %v, want %v", got, tt.want) + if got := subtract(tt.args.a, tt.args.b); !reflect.DeepEqual(got, tt.want) { + t.Errorf("subtract() = %v, want %v", got, tt.want) } }) } diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go index 9a67f7feb8..fe82676788 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go @@ -8,10 +8,11 @@ import ( "github.com/Masterminds/semver/v3" - "github.com/ignite/cli/v29/ignite/internal/tools/gen-mig-diffs/pkg/cache" "github.com/ignite/cli/v29/ignite/pkg/cmdrunner/exec" "github.com/ignite/cli/v29/ignite/pkg/errors" "github.com/ignite/cli/v29/ignite/pkg/randstr" + + "github.com/ignite/mig-diffs/pkg/cache" ) var v027 = semver.MustParse("v0.27.0") From d6cf7d73928777c65871000b298eea4293e3a034 Mon Sep 17 00:00:00 2001 From: Pantani Date: Sun, 7 Apr 2024 04:18:04 +0200 Subject: [PATCH 67/69] change the go.mod namespace --- .../internal/tools/gen-mig-diffs/cmd/root.go | 8 +- ignite/internal/tools/gen-mig-diffs/go.mod | 40 +++++----- ignite/internal/tools/gen-mig-diffs/go.sum | 80 +++++++++---------- ignite/internal/tools/gen-mig-diffs/main.go | 2 +- .../gen-mig-diffs/pkg/scaffold/scaffold.go | 2 +- 5 files changed, 65 insertions(+), 67 deletions(-) diff --git a/ignite/internal/tools/gen-mig-diffs/cmd/root.go b/ignite/internal/tools/gen-mig-diffs/cmd/root.go index 8ced9ee4fe..70c9aea268 100644 --- a/ignite/internal/tools/gen-mig-diffs/cmd/root.go +++ b/ignite/internal/tools/gen-mig-diffs/cmd/root.go @@ -11,10 +11,10 @@ import ( "github.com/ignite/cli/v29/ignite/pkg/errors" "github.com/ignite/cli/v29/ignite/pkg/xgenny" - "github.com/ignite/mig-diffs/pkg/diff" - "github.com/ignite/mig-diffs/pkg/repo" - "github.com/ignite/mig-diffs/pkg/scaffold" - "github.com/ignite/mig-diffs/templates/doc" + "github.com/ignite/cli/ignite/internal/tools/gen-mig-diffs/pkg/diff" + "github.com/ignite/cli/ignite/internal/tools/gen-mig-diffs/pkg/repo" + "github.com/ignite/cli/ignite/internal/tools/gen-mig-diffs/pkg/scaffold" + "github.com/ignite/cli/ignite/internal/tools/gen-mig-diffs/templates/doc" ) const ( diff --git a/ignite/internal/tools/gen-mig-diffs/go.mod b/ignite/internal/tools/gen-mig-diffs/go.mod index 0f29fe5d19..931888d888 100644 --- a/ignite/internal/tools/gen-mig-diffs/go.mod +++ b/ignite/internal/tools/gen-mig-diffs/go.mod @@ -1,4 +1,4 @@ -module github.com/ignite/mig-diffs +module github.com/ignite/cli/ignite/internal/tools/gen-mig-diffs go 1.22.2 @@ -24,7 +24,7 @@ require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/briandowns/spinner v1.23.0 // indirect - github.com/charmbracelet/lipgloss v0.6.0 // indirect + github.com/charmbracelet/lipgloss v0.10.0 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/cockroachdb/errors v1.11.1 // indirect @@ -32,15 +32,15 @@ require ( github.com/cockroachdb/redact v1.1.5 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/proto v1.12.2 // indirect - github.com/emicklei/proto-contrib v0.15.0 // indirect + github.com/emicklei/proto v1.13.2 // indirect + github.com/emicklei/proto-contrib v0.16.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.15.0 // indirect + github.com/fatih/color v1.16.0 // indirect github.com/fatih/structs v1.1.0 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.5.0 // indirect - github.com/gobuffalo/flect v0.3.0 // indirect + github.com/gobuffalo/flect v1.0.2 // indirect github.com/gobuffalo/github_flavored_markdown v1.1.4 // indirect github.com/gobuffalo/helpers v0.6.7 // indirect github.com/gobuffalo/logger v1.0.7 // indirect @@ -50,7 +50,7 @@ require ( github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/css v1.0.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect @@ -62,15 +62,15 @@ require ( github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect - github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect - github.com/microcosm-cc/bluemonday v1.0.23 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect github.com/muesli/reflow v0.3.0 // indirect - github.com/muesli/termenv v0.15.1 // indirect + github.com/muesli/termenv v0.15.2 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect @@ -79,15 +79,15 @@ require ( github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect - golang.org/x/mod v0.15.0 // indirect - golang.org/x/net v0.22.0 // indirect - golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/term v0.18.0 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/term v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.18.0 // indirect + golang.org/x/tools v0.20.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/ignite/internal/tools/gen-mig-diffs/go.sum b/ignite/internal/tools/gen-mig-diffs/go.sum index bfde45b02a..0587461407 100644 --- a/ignite/internal/tools/gen-mig-diffs/go.sum +++ b/ignite/internal/tools/gen-mig-diffs/go.sum @@ -22,8 +22,8 @@ github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd3 github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A= github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/charmbracelet/lipgloss v0.6.0 h1:1StyZB9vBSOyuZxQUcUwGr17JmojPNm87inij9N3wJY= -github.com/charmbracelet/lipgloss v0.6.0/go.mod h1:tHh2wr34xcHjC2HCXIlGSG1jaDF0S0atAUvBMP6Ppuk= +github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s= +github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= @@ -54,14 +54,14 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= -github.com/emicklei/proto v1.12.2 h1:ZDyDzrfMt7ncmyor/j07uoOCGLKtU5F87vTPwIzLe/o= -github.com/emicklei/proto v1.12.2/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= -github.com/emicklei/proto-contrib v0.15.0 h1:5D8JKpV1qekMDFwEJp8NVJGY1We6t14dn9D4G05fpyo= -github.com/emicklei/proto-contrib v0.15.0/go.mod h1:p6zmoy14hFYiwUb35X7nJ4u4l1vfvjc1mWrIt8QB3kw= +github.com/emicklei/proto v1.13.2 h1:z/etSFO3uyXeuEsVPzfl56WNgzcvIr42aQazXaQmFZY= +github.com/emicklei/proto v1.13.2/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= +github.com/emicklei/proto-contrib v0.16.0 h1:I0rAHhIVfI6j6GC3ojlFHXH3wNH8gvxtBOjlp64UQ0o= +github.com/emicklei/proto-contrib v0.16.0/go.mod h1:fzL/hybgHb6PA60EnSS2WnYoR4SPTD8sF5FpUa+Ay/Q= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= @@ -78,8 +78,9 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMj github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= -github.com/gobuffalo/flect v0.3.0 h1:erfPWM+K1rFNIQeRPdeEXxo8yFr/PO17lhRnS8FUrtk= github.com/gobuffalo/flect v0.3.0/go.mod h1:5pf3aGnsvqvCj50AVni7mJJF8ICxGZ8HomberC3pXLE= +github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA= +github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/gobuffalo/genny/v2 v2.1.0 h1:cCRBbqzo3GfNvj3UetD16zRgUvWFEyyl0qTqquuIqOM= github.com/gobuffalo/genny/v2 v2.1.0/go.mod h1:4yoTNk4bYuP3BMM6uQKYPvtP6WsXFGm2w2EFYZdRls8= github.com/gobuffalo/github_flavored_markdown v1.1.3/go.mod h1:IzgO5xS6hqkDmUh91BW/+Qxo/qYnvfzoz3A7uLkg77I= @@ -109,8 +110,9 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= +github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= @@ -142,27 +144,23 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/microcosm-cc/bluemonday v1.0.20/go.mod h1:yfBmMi8mxvaZut3Yytv+jTXRY8mxyjJ0/kQBTElld50= github.com/microcosm-cc/bluemonday v1.0.22/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM= -github.com/microcosm-cc/bluemonday v1.0.23 h1:SMZe2IGa0NuHvnVNAZ+6B38gsTbi5e4sViiWJyDDqFY= -github.com/microcosm-cc/bluemonday v1.0.23/go.mod h1:mN70sk7UkkF8TUr2IGBpNN0jAgStuPzlK76QuruE/z4= -github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= -github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= -github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs= -github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ= +github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= +github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= @@ -177,8 +175,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= @@ -210,6 +208,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= @@ -225,16 +224,16 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -248,8 +247,8 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -257,8 +256,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -269,7 +268,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -280,16 +278,16 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -305,8 +303,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= -golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/ignite/internal/tools/gen-mig-diffs/main.go b/ignite/internal/tools/gen-mig-diffs/main.go index 7b10252d29..11de0ee9fb 100644 --- a/ignite/internal/tools/gen-mig-diffs/main.go +++ b/ignite/internal/tools/gen-mig-diffs/main.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/ignite/mig-diffs/cmd" + "github.com/ignite/cli/ignite/internal/tools/gen-mig-diffs/cmd" ) func main() { diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go index fe82676788..db7affe7eb 100644 --- a/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go +++ b/ignite/internal/tools/gen-mig-diffs/pkg/scaffold/scaffold.go @@ -12,7 +12,7 @@ import ( "github.com/ignite/cli/v29/ignite/pkg/errors" "github.com/ignite/cli/v29/ignite/pkg/randstr" - "github.com/ignite/mig-diffs/pkg/cache" + "github.com/ignite/cli/ignite/internal/tools/gen-mig-diffs/pkg/cache" ) var v027 = semver.MustParse("v0.27.0") From c3b422a866a08667d74bbdf70bba5785008634e3 Mon Sep 17 00:00:00 2001 From: Pantani Date: Wed, 17 Apr 2024 16:15:41 +0200 Subject: [PATCH 68/69] rollback go.mod --- .github/workflows/gen-docs-migration.yml | 8 +++---- go.mod | 16 +++++++------- go.sum | 28 ++++++++++-------------- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/.github/workflows/gen-docs-migration.yml b/.github/workflows/gen-docs-migration.yml index f51b95f2fc..7ee442396d 100644 --- a/.github/workflows/gen-docs-migration.yml +++ b/.github/workflows/gen-docs-migration.yml @@ -7,18 +7,18 @@ jobs: cli: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.21' + go-version: 'stable' - name: Generate Scaffold Migration Docs run: ./scripts/gen-mig-diffs - name: Create Pull Request id: cpr - uses: peter-evans/create-pull-request@v4 + uses: peter-evans/create-pull-request@v6 with: title: "docs(migration): update generated docs" commit-message: "docs(migration): update generated docs" diff --git a/go.mod b/go.mod index 3341358a8d..73cf9d666c 100644 --- a/go.mod +++ b/go.mod @@ -57,7 +57,7 @@ require ( github.com/ignite/ignite-files/nodetime v0.0.4 github.com/ignite/ignite-files/protoc v0.0.1 github.com/ignite/web v0.6.1 - github.com/imdario/mergo v0.3.15 + github.com/imdario/mergo v0.3.13 github.com/jpillora/chisel v1.9.1 github.com/lib/pq v1.10.9 github.com/manifoldco/promptui v0.9.0 @@ -133,8 +133,8 @@ require ( github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 // indirect github.com/ashanbrown/forbidigo v1.6.0 // indirect github.com/ashanbrown/makezero v1.1.1 // indirect - github.com/atotto/clipboard v0.1.4 // indirect - github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/atotto/clipboard v0.1.2 // indirect + github.com/aymanbagabas/go-osc52 v1.2.1 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect @@ -160,7 +160,7 @@ require ( github.com/charmbracelet/charm v0.8.6 // indirect github.com/charmbracelet/glamour v0.2.1-0.20210402234443-abe9cda419ba // indirect github.com/chavacava/garif v0.1.0 // indirect - github.com/chigopher/pathlib v1.0.0 // indirect + github.com/chigopher/pathlib v0.19.1 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cilium/ebpf v0.11.0 // indirect github.com/ckaznocha/intrange v0.1.1 // indirect @@ -351,12 +351,12 @@ require ( github.com/moricho/tparallel v0.3.1 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/mtibben/percent v0.2.1 // indirect - github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect + github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/gitcha v0.2.0 // indirect github.com/muesli/go-app-paths v0.2.1 // indirect github.com/muesli/sasquatch v0.0.0-20200811221207-66979d92330a // indirect - github.com/muesli/termenv v0.15.1 // indirect + github.com/muesli/termenv v0.14.0 // indirect github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect @@ -383,7 +383,7 @@ require ( github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.2.0 // indirect github.com/rs/zerolog v1.32.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/ryancurrah/gomodguard v1.3.1 // indirect @@ -435,7 +435,7 @@ require ( github.com/vbatts/tar-split v0.11.5 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xen0n/gosmopolitan v1.2.2 // indirect - github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.2.0 // indirect github.com/ykadowak/zerologlint v0.1.5 // indirect diff --git a/go.sum b/go.sum index bd6abddf7b..0b26c74595 100644 --- a/go.sum +++ b/go.sum @@ -183,17 +183,15 @@ github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8ger github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= +github.com/atotto/clipboard v0.1.2 h1:YZCtFu5Ie8qX2VmVTBnrqLSiU9XOWwqNRmdT3gIQzbY= github.com/atotto/clipboard v0.1.2/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= -github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.44.224 h1:09CiaaF35nRmxrzWZ2uRq5v6Ghg/d2RiPjZnSgtt+RQ= github.com/aws/aws-sdk-go v1.44.224/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/aymanbagabas/go-osc52 v1.2.1 h1:q2sWUyDcozPLcLabEMd+a+7Ea2DitxZVN9hTxab9L4E= github.com/aymanbagabas/go-osc52 v1.2.1/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4= -github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= -github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -282,8 +280,8 @@ github.com/charmbracelet/lipgloss v0.6.0 h1:1StyZB9vBSOyuZxQUcUwGr17JmojPNm87ini github.com/charmbracelet/lipgloss v0.6.0/go.mod h1:tHh2wr34xcHjC2HCXIlGSG1jaDF0S0atAUvBMP6Ppuk= github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= -github.com/chigopher/pathlib v1.0.0 h1:SbsCrFX4vDf4M2d8mT/RTzuVlKOjTKoPHK0HidsQFak= -github.com/chigopher/pathlib v1.0.0/go.mod h1:3+YPPV21mU9vyw8Mjp+F33CyCfE6iOzinpiqBcccv7I= +github.com/chigopher/pathlib v0.19.1 h1:RoLlUJc0CqBGwq239cilyhxPNLXTK+HXoASGyGznx5A= +github.com/chigopher/pathlib v0.19.1/go.mod h1:tzC1dZLW8o33UQpWkNkhvPwL5n4yyFRFm/jL1YGWFvY= github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= @@ -900,8 +898,8 @@ github.com/ignite/ignite-files/protoc v0.0.1/go.mod h1:cVCHJbEHPIeKHMPk3ZoPS0Xw4 github.com/ignite/web v0.6.1 h1:kHG+T7NnR8cCPjAGxEFQD+njVYM08toeG57iYRXzpwo= github.com/ignite/web v0.6.1/go.mod h1:WZWBaBYF8RazN7dE462BLpvXDY8ScacxcJ07BKwX/jY= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -1122,9 +1120,8 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b h1:1XF24mVaiu7u+CFywTdcDo2ie1pzzhwjt6RHqzpMU34= github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= -github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= -github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/muesli/gitcha v0.2.0 h1:+wOgT2dI9s2Tznj1t1rb/qkK5e0cb6qD8c4IX2TR/YY= @@ -1142,9 +1139,8 @@ github.com/muesli/termenv v0.7.2/go.mod h1:ct2L5N2lmix82RaY3bMWwVu/jUFc9Ule0KGDC github.com/muesli/termenv v0.7.4/go.mod h1:pZ7qY9l3F7e5xsAOS0zCew2tME+p7bWeBkotCEcIIcc= github.com/muesli/termenv v0.8.1/go.mod h1:kzt/D/4a88RoheZmwfqorY3A+tnsSMA9HJC/fQSFKo0= github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= +github.com/muesli/termenv v0.14.0 h1:8x9NFfOe8lmIWK4pgy3IfVEy47f+ppe3tUqdPZG2Uy0= github.com/muesli/termenv v0.14.0/go.mod h1:kG/pF1E7fh949Xhe156crRUrHNyK221IuGO7Ez60Uc8= -github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs= -github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -1311,9 +1307,8 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1510,8 +1505,8 @@ github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= -github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= @@ -2103,6 +2098,7 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= From 550eb2cd57208ab32a63bbe12641076929cbb5e9 Mon Sep 17 00:00:00 2001 From: Pantani Date: Fri, 19 Apr 2024 01:47:04 +0200 Subject: [PATCH 69/69] break the compute function and add unit tests --- .../tools/gen-mig-diffs/pkg/diff/testdata/modified/bar.txt | 1 + .../tools/gen-mig-diffs/pkg/diff/testdata/modified/foo.txt | 1 + .../tools/gen-mig-diffs/pkg/diff/testdata/modified/new.txt | 1 + .../tools/gen-mig-diffs/pkg/diff/testdata/modified/pkg/main.go | 3 +++ .../tools/gen-mig-diffs/pkg/diff/testdata/origin/bar.txt | 1 + .../tools/gen-mig-diffs/pkg/diff/testdata/origin/foo.txt | 1 + .../tools/gen-mig-diffs/pkg/diff/testdata/origin/pkg/main.go | 1 + 7 files changed, 9 insertions(+) create mode 100644 ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/bar.txt create mode 100644 ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/foo.txt create mode 100644 ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/new.txt create mode 100644 ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/pkg/main.go create mode 100644 ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/origin/bar.txt create mode 100644 ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/origin/foo.txt create mode 100644 ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/origin/pkg/main.go diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/bar.txt b/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/bar.txt new file mode 100644 index 0000000000..bd03c683ce --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/bar.txt @@ -0,0 +1 @@ +unmodified \ No newline at end of file diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/foo.txt b/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/foo.txt new file mode 100644 index 0000000000..04fea06420 --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/foo.txt @@ -0,0 +1 @@ +world \ No newline at end of file diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/new.txt b/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/new.txt new file mode 100644 index 0000000000..1271944b7e --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/new.txt @@ -0,0 +1 @@ +new file \ No newline at end of file diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/pkg/main.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/pkg/main.go new file mode 100644 index 0000000000..38dd16da61 --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/modified/pkg/main.go @@ -0,0 +1,3 @@ +package main + +func main() {} diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/origin/bar.txt b/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/origin/bar.txt new file mode 100644 index 0000000000..bd03c683ce --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/origin/bar.txt @@ -0,0 +1 @@ +unmodified \ No newline at end of file diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/origin/foo.txt b/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/origin/foo.txt new file mode 100644 index 0000000000..b6fc4c620b --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/origin/foo.txt @@ -0,0 +1 @@ +hello \ No newline at end of file diff --git a/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/origin/pkg/main.go b/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/origin/pkg/main.go new file mode 100644 index 0000000000..06ab7d0f9a --- /dev/null +++ b/ignite/internal/tools/gen-mig-diffs/pkg/diff/testdata/origin/pkg/main.go @@ -0,0 +1 @@ +package main