diff --git a/.gitignore b/.gitignore index 829ad8a..070eb2c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ *.test *.out .idea/ +vendor diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..8b8d27b --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,377 @@ +# v1.2.0. Created based on golangci-lint v1.57.1 + +run: + timeout: 5m + modules-download-mode: readonly + allow-serial-runners: true + +output: + sort-results: true + uniq-by-line: false + +linters-settings: + depguard: + rules: + all: + list-mode: lax + deny: + - pkg: "flag" + desc: '`flag` package is only allowed in main.go' + - pkg: "log" + desc: 'logging is provided by `pkg/log`' + - pkg: "io/ioutil" + desc: '`io/ioutil` package is deprecated, use the `io` and `os` package instead' + # TODO: Prevent using these without a reason + # - pkg: "reflect" + # desc: '`reflect` package is dangerous to use' + # - pkg: "unsafe" + # desc: '`unsafe` package is dangerous to use' + + errcheck: + check-type-assertions: true + check-blank: true + disable-default-exclusions: true + exclude-functions: + - '(*bytes.Buffer).Write' # always returns nil error + - '(*github.com/valyala/bytebufferpool.ByteBuffer).Write' # always returns nil error + - '(*github.com/valyala/bytebufferpool.ByteBuffer).WriteByte' # always returns nil error + - '(*github.com/valyala/bytebufferpool.ByteBuffer).WriteString' # always returns nil error + + errchkjson: + report-no-exported: true + + exhaustive: + check-generated: true + default-signifies-exhaustive: true + + forbidigo: + forbid: + - ^print(ln)?$ + - ^fmt\.Print(f|ln)?$ + - ^http\.Default(Client|ServeMux|Transport)$ + # TODO: Eventually enable these patterns + # - ^panic$ + # - ^time\.Sleep$ + analyze-types: true + + gci: + sections: + - standard + - prefix(github.com/gofiber/fiber) + - default + - blank + - dot + # - alias + custom-order: true + + goconst: + numbers: true + + gocritic: + # TODO: Uncomment the following lines + enabled-tags: + - diagnostic + # - style + # - performance + # - experimental + # - opinionated + settings: + captLocal: + paramsOnly: false + elseif: + skipBalanced: false + underef: + skipRecvDeref: false + # NOTE: Set this option to false if other projects rely on this project's code + # unnamedResult: + # checkExported: false + + gofumpt: + module-path: github.com/gofiber/fiber + extra-rules: true + + gosec: + excludes: + - G104 # TODO: Enable this again. Mostly provided by errcheck + config: + global: + # show-ignored: true # TODO: Enable this + audit: true + + govet: + enable-all: true + disable: + - shadow + + grouper: + # const-require-grouping: true # TODO: Enable this + import-require-single-import: true + import-require-grouping: true + # var-require-grouping: true # TODO: Conflicts with gofumpt + + loggercheck: + require-string-key: true + no-printf-like: true + + misspell: + locale: US + + nolintlint: + require-explanation: true + require-specific: true + + nonamedreturns: + report-error-in-defer: true + + perfsprint: + err-error: true + + predeclared: + q: true + + promlinter: + strict: true + + # TODO: Enable this + # reassign: + # patterns: + # - '.*' + + revive: + enable-all-rules: true + rules: + # Provided by gomnd linter + - name: add-constant + disabled: true + - name: argument-limit + disabled: true + # Provided by bidichk + - name: banned-characters + disabled: true + - name: cognitive-complexity + disabled: true + - name: comment-spacings + arguments: + - nolint + disabled: true # TODO: Do not disable + - name: cyclomatic + disabled: true + # TODO: Enable this check. Currently disabled due to upstream bug. + # - name: enforce-repeated-arg-type-style + # arguments: + # - short + - name: enforce-slice-style + arguments: + - make + disabled: true # TODO: Do not disable + - name: exported + disabled: true + - name: file-header + disabled: true + - name: function-result-limit + arguments: [3] + - name: function-length + disabled: true + - name: line-length-limit + disabled: true + - name: max-public-structs + disabled: true + - name: modifies-parameter + disabled: true + - name: nested-structs + disabled: true # TODO: Do not disable + - name: package-comments + disabled: true + - name: optimize-operands-order + disabled: true + - name: unchecked-type-assertion + disabled: true # TODO: Do not disable + - name: unhandled-error + arguments: ['bytes\.Buffer\.Write'] + + stylecheck: + checks: + - all + - -ST1000 + - -ST1020 + - -ST1021 + - -ST1022 + + tagalign: + strict: true + + tagliatelle: + case: + rules: + json: snake + + tenv: + all: true + + testifylint: + enable-all: true + + testpackage: + skip-regexp: "^$" + + unparam: + # NOTE: Set this option to false if other projects rely on this project's code + check-exported: false + + unused: + # TODO: Uncomment these two lines + # parameters-are-used: false + # local-variables-are-used: false + # NOTE: Set these options to true if other projects rely on this project's code + field-writes-are-uses: true + # exported-is-used: true # TODO: Fix issues with this option (upstream) + exported-fields-are-used: true + + usestdlibvars: + http-method: true + http-status-code: true + time-weekday: false # TODO: Set to true + time-month: false # TODO: Set to true + time-layout: false # TODO: Set to true + crypto-hash: true + default-rpc-path: true + sql-isolation-level: true + tls-signature-scheme: true + constant-kind: true + + wrapcheck: + ignorePackageGlobs: + - github.com/gofiber/fiber/* + - github.com/valyala/fasthttp + +issues: + exclude-use-default: false + exclude-case-sensitive: true + max-issues-per-linter: 0 + max-same-issues: 0 + exclude-dirs: + - internal # TODO: Do not ignore interal packages + exclude-rules: + - linters: + - err113 + text: 'do not define dynamic errors, use wrapped static errors instead*' + - path: log/.*\.go + linters: + - depguard + # Exclude some linters from running on tests files. + - path: _test\.go + linters: + - bodyclose + - err113 + # fix: true + +linters: + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - containedctx + - contextcheck + # - cyclop + - decorder + - depguard + - dogsled + # - dupl + - dupword # TODO: Enable + - durationcheck + - errcheck + - errchkjson + - errname + - errorlint + - exhaustive + # - exhaustivestruct + # - exhaustruct + - copyloopvar + - forbidigo + - forcetypeassert + # - funlen + # - gci # TODO: Enable + - ginkgolinter + # - gocheckcompilerdirectives # TODO: Enable + # - gochecknoglobals # TODO: Enable + # - gochecknoinits # TODO: Enable + - gochecksumtype + # - gocognit + - goconst # TODO: Enable + - gocritic + # - gocyclo + # - godot + # - godox + - err113 + - gofmt + - gofumpt + # - goheader + - goimports + # - mnd # TODO: Enable + - gomoddirectives + # - gomodguard + - goprintffuncname + - gosec + - gosimple + # - gosmopolitan # TODO: Enable + - govet + - grouper + # - ifshort # TODO: Enable + # - importas + # - inamedparam + - ineffassign + # - interfacebloat + # - interfacer + # - ireturn + # - lll + - loggercheck + # - maintidx + - makezero + # - maligned + - mirror + - misspell + - musttag + - nakedret + # - nestif + - nilerr + - nilnil + # - nlreturn + - noctx + - nolintlint + - nonamedreturns + - nosprintfhostport + # - paralleltest # TODO: Enable + - perfsprint + # - prealloc + - predeclared + - promlinter + - protogetter + - reassign + - revive + - rowserrcheck + # - scopelint # TODO: Enable + - sloglint + - spancheck + - sqlclosecheck + - staticcheck + - stylecheck + # - tagalign # TODO: Enable + - tagliatelle + - tenv + - testableexamples + - testifylint + # - testpackage # TODO: Enable + - thelper + - tparallel + - typecheck + - unconvert + - unparam + - unused + - usestdlibvars + # - varnamelen + # - wastedassign # TODO: Enable + - whitespace + - wrapcheck + # - wsl + - zerologlint diff --git a/.markdownlint.yml b/.markdownlint.yml new file mode 100644 index 0000000..71d7b30 --- /dev/null +++ b/.markdownlint.yml @@ -0,0 +1,248 @@ +# Example markdownlint configuration with all properties set to their default value + +# Default state for all rules +default: true + +# Path to configuration file to extend +extends: null + +# MD001/heading-increment : Heading levels should only increment by one level at a time : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md001.md +MD001: true + +# MD003/heading-style : Heading style : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md003.md +MD003: + # Heading style + style: "consistent" + +# MD004/ul-style : Unordered list style : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md004.md +MD004: + # List style + style: "consistent" + +# MD005/list-indent : Inconsistent indentation for list items at the same level : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md005.md +MD005: true + +# MD007/ul-indent : Unordered list indentation : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md007.md +MD007: + # Spaces for indent + indent: + # Whether to indent the first level of the list + start_indented: false + # Spaces for first level indent (when start_indented is set) + start_indent: 2 + +# MD009/no-trailing-spaces : Trailing spaces : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md009.md +MD009: + # Spaces for line break + br_spaces: 2 + # Allow spaces for empty lines in list items + list_item_empty_lines: false + # Include unnecessary breaks + strict: true + +# MD010/no-hard-tabs : Hard tabs : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md010.md +MD010: + # Include code blocks + code_blocks: true + # Fenced code languages to ignore + ignore_code_languages: [] + # Number of spaces for each hard tab + spaces_per_tab: 4 + +# MD011/no-reversed-links : Reversed link syntax : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md011.md +MD011: true + +# MD012/no-multiple-blanks : Multiple consecutive blank lines : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md012.md +MD012: + # Consecutive blank lines + maximum: 1 + +# MD013/line-length : Line length : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md013.md +MD013: false + +# MD014/commands-show-output : Dollar signs used before commands without showing output : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md014.md +MD014: true + +# MD018/no-missing-space-atx : No space after hash on atx style heading : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md018.md +MD018: true + +# MD019/no-multiple-space-atx : Multiple spaces after hash on atx style heading : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md019.md +MD019: true + +# MD020/no-missing-space-closed-atx : No space inside hashes on closed atx style heading : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md020.md +MD020: true + +# MD021/no-multiple-space-closed-atx : Multiple spaces inside hashes on closed atx style heading : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md021.md +MD021: true + +# MD022/blanks-around-headings : Headings should be surrounded by blank lines : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md022.md +MD022: + # Blank lines above heading + lines_above: 1 + # Blank lines below heading + lines_below: 1 + +# MD023/heading-start-left : Headings must start at the beginning of the line : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md023.md +MD023: true + +# MD024/no-duplicate-heading : Multiple headings with the same content : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md024.md +MD024: false + +# MD025/single-title/single-h1 : Multiple top-level headings in the same document : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md025.md +MD025: + # Heading level + level: 1 + # RegExp for matching title in front matter + front_matter_title: "^\\s*title\\s*[:=]" + +# MD026/no-trailing-punctuation : Trailing punctuation in heading : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md026.md +MD026: + # Punctuation characters + punctuation: ".,;:!。,;:!" + +# MD027/no-multiple-space-blockquote : Multiple spaces after blockquote symbol : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md027.md +MD027: true + +# MD028/no-blanks-blockquote : Blank line inside blockquote : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md028.md +MD028: true + +# MD029/ol-prefix : Ordered list item prefix : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md029.md +MD029: + # List style + style: "one_or_ordered" + +# MD030/list-marker-space : Spaces after list markers : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md030.md +MD030: + # Spaces for single-line unordered list items + ul_single: 1 + # Spaces for single-line ordered list items + ol_single: 1 + # Spaces for multi-line unordered list items + ul_multi: 1 + # Spaces for multi-line ordered list items + ol_multi: 1 + +# MD031/blanks-around-fences : Fenced code blocks should be surrounded by blank lines : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md031.md +MD031: + # Include list items + list_items: true + +# MD032/blanks-around-lists : Lists should be surrounded by blank lines : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md032.md +MD032: true + +# MD033/no-inline-html : Inline HTML : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md033.md +MD033: false + +# MD034/no-bare-urls : Bare URL used : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md034.md +MD034: true + +# MD035/hr-style : Horizontal rule style : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md035.md +MD035: + # Horizontal rule style + style: "consistent" + +# MD036/no-emphasis-as-heading : Emphasis used instead of a heading : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md036.md +MD036: + # Punctuation characters + punctuation: ".,;:!?。,;:!?" + +# MD037/no-space-in-emphasis : Spaces inside emphasis markers : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md037.md +MD037: true + +# MD038/no-space-in-code : Spaces inside code span elements : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md038.md +MD038: true + +# MD039/no-space-in-links : Spaces inside link text : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md039.md +MD039: true + +# MD040/fenced-code-language : Fenced code blocks should have a language specified : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md040.md +MD040: + # List of languages + allowed_languages: [] + # Require language only + language_only: false + +# MD041/first-line-heading/first-line-h1 : First line in a file should be a top-level heading : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md041.md +MD041: + # Heading level + level: 1 + # RegExp for matching title in front matter + front_matter_title: "^\\s*title\\s*[:=]" + +# MD042/no-empty-links : No empty links : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md042.md +MD042: true + +# MD043/required-headings : Required heading structure : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md043.md +MD043: false + +# MD044/proper-names : Proper names should have the correct capitalization : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md044.md +MD044: + # List of proper names + names: [] + # Include code blocks + code_blocks: true + # Include HTML elements + html_elements: true + +# MD045/no-alt-text : Images should have alternate text (alt text) : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md045.md +MD045: false + +# MD046/code-block-style : Code block style : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md046.md +MD046: + # Block style + style: "fenced" + +# MD047/single-trailing-newline : Files should end with a single newline character : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md047.md +MD047: true + +# MD048/code-fence-style : Code fence style : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md048.md +MD048: + # Code fence style + style: "backtick" + +# MD049/emphasis-style : Emphasis style : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md049.md +MD049: + # Emphasis style + style: "consistent" + +# MD050/strong-style : Strong style : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md050.md +MD050: + # Strong style + style: "consistent" + +# MD051/link-fragments : Link fragments should be valid : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md051.md +MD051: true + +# MD052/reference-links-images : Reference links and images should use a label that is defined : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md052.md +MD052: + # Include shortcut syntax + shortcut_syntax: false + +# MD053/link-image-reference-definitions : Link and image reference definitions should be needed : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md053.md +MD053: + # Ignored definitions + ignored_definitions: + - "//" + +# MD054/link-image-style : Link and image style : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md054.md +MD054: + # Allow autolinks + autolink: false + # Allow inline links and images + inline: true + # Allow full reference links and images + full: true + # Allow collapsed reference links and images + collapsed: true + # Allow shortcut reference links and images + shortcut: true + # Allow URLs as inline links + url_inline: true + +# MD055/table-pipe-style : Table pipe style : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md055.md +MD055: + # Table pipe style + style: "consistent" + +# MD056/table-column-count : Table column count : https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md056.md +MD056: true diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..41eb8f5 --- /dev/null +++ b/Makefile @@ -0,0 +1,65 @@ +## help: 💡 Display available commands +.PHONY: help +help: + @echo '⚡️ GoFiber/Cli Development:' + @sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /' + +## audit: 🚀 Conduct quality checks +.PHONY: audit +audit: + go mod verify + go vet ./... + go run golang.org/x/vuln/cmd/govulncheck@latest ./... + +## benchmark: 📈 Benchmark code performance +.PHONY: benchmark +benchmark: + go test ./... -benchmem -bench=. -run=^Benchmark_$ + +## coverage: ☂️ Generate coverage report +.PHONY: coverage +coverage: + go run gotest.tools/gotestsum@latest -f testname -- ./... -race -count=1 -coverprofile=/tmp/coverage.out -covermode=atomic + go tool cover -html=/tmp/coverage.out + +## format: 🎨 Fix code format issues +.PHONY: format +format: + go run mvdan.cc/gofumpt@latest -w -l . + +## markdown: 🎨 Find markdown format issues (Requires markdownlint-cli) +.PHONY: markdown +markdown: + markdownlint-cli2 "**/*.md" "#vendor" + +## lint: 🚨 Run lint checks +.PHONY: lint +lint: + go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.0 run ./... + +## test: 🚦 Execute all tests +.PHONY: test +test: + go run gotest.tools/gotestsum@latest -f testname -- ./... -race -count=1 -shuffle=on + +## longtest: 🚦 Execute all tests 10x +.PHONY: longtest +longtest: + go run gotest.tools/gotestsum@latest -f testname -- ./... -race -count=15 -shuffle=on + +## tidy: 📌 Clean and tidy dependencies +.PHONY: tidy +tidy: + go mod tidy -v + +## betteralign: 📐 Optimize alignment of fields in structs +.PHONY: betteralign +betteralign: + go run github.com/dkorunic/betteralign/cmd/betteralign@latest -test_files -generated_files -apply ./... + +## generate: ⚡️ Generate msgp && interface implementations +.PHONY: generate +generate: + go install github.com/tinylib/msgp@latest + go install github.com/vburenin/ifacemaker@975a95966976eeb2d4365a7fb236e274c54da64c + go generate ./... diff --git a/cmd/internal/helpers.go b/cmd/internal/helpers.go index 3453ca9..77f81e3 100644 --- a/cmd/internal/helpers.go +++ b/cmd/internal/helpers.go @@ -2,6 +2,9 @@ package internal import ( "fmt" + "os" + "path/filepath" + "strings" tea "github.com/charmbracelet/bubbletea" "github.com/containerd/console" @@ -27,3 +30,41 @@ func errCmd(err error) tea.Cmd { return finishedMsg{err} } } + +type FileProcessor func(content string) string + +func ChangeFileContent(cwd string, processorFn FileProcessor) error { + // change go files in project + err := filepath.Walk(cwd, func(path string, info os.FileInfo, err error) error { + if err != nil { + //fmt.Printf("Error while traversing %s: %v\n", path, err) + return err + } + + // Skip directories named "vendor" + if info.IsDir() && info.Name() == "vendor" { + //fmt.Printf("Skipping directory: %s\n", path) + return filepath.SkipDir + } + + // Check if the file is a Go file (ending with ".go") + if info.IsDir() || !strings.HasSuffix(info.Name(), ".go") { + return nil + } + //fmt.Printf("Processing Go file: %s\n", path) + fileContent, err := os.ReadFile(path) + + // update go.mod file + if err2 := os.WriteFile(path, []byte(processorFn(string(fileContent))), 0644); err != nil { + return err2 + } + + return nil + }) + + if err != nil { + return fmt.Errorf("Error while traversing the directory tree: %v\n", err) + } + + return nil +} diff --git a/cmd/internal/migrations/common.go b/cmd/internal/migrations/common.go new file mode 100644 index 0000000..74e041c --- /dev/null +++ b/cmd/internal/migrations/common.go @@ -0,0 +1,53 @@ +package migrations + +import ( + "fmt" + semver "github.com/Masterminds/semver/v3" + "github.com/spf13/cobra" + "os" + "regexp" + "strconv" + "strings" + + "github.com/gofiber/cli/cmd/internal" +) + +var ( + pkgRegex = regexp.MustCompile(`(github\.com\/gofiber\/fiber\/)(v\d+)( *?)(v[\w.-]+)`) +) + +func MigrateGoPkgs(cmd *cobra.Command, cwd string, curr *semver.Version, target *semver.Version) error { + pkgReplacer := strings.NewReplacer( + "github.com/gofiber/fiber/v"+strconv.FormatUint(curr.Major(), 10), + "github.com/gofiber/fiber/v"+strconv.FormatUint(target.Major(), 10), + ) + + err := internal.ChangeFileContent(cwd, func(content string) string { + return pkgReplacer.Replace(content) + }) + if err != nil { + return fmt.Errorf("failed to migrate Go packages: %v", err) + } + + // get go.mod file + modFile := "go.mod" + fileContent, err := os.ReadFile(modFile) + if err != nil { + return err + } + + // replace old version with new version in go.mod file + fileContentStr := pkgRegex.ReplaceAllString( + string(fileContent), + "${1}v"+strconv.FormatUint(target.Major(), 10)+"${3}v"+target.String(), + ) + + // update go.mod file + if err := os.WriteFile(modFile, []byte(fileContentStr), 0644); err != nil { + return err + } + + cmd.Println("Migrating Go packages") + + return nil +} diff --git a/cmd/internal/migrations/lists.go b/cmd/internal/migrations/lists.go new file mode 100644 index 0000000..6029642 --- /dev/null +++ b/cmd/internal/migrations/lists.go @@ -0,0 +1,54 @@ +package migrations + +import ( + "fmt" + semver "github.com/Masterminds/semver/v3" + "github.com/spf13/cobra" + + "github.com/gofiber/cli/cmd/internal/migrations/v3" +) + +// MigrationFn is a function that will be called during migration +type MigrationFn func(cmd *cobra.Command, cwd string, curr *semver.Version, target *semver.Version) error + +// Migration is a single migration +type Migration struct { + From string + To string + Functions []MigrationFn +} + +// Migrations is a list of all migrations +// Example structure: +// {"from": ">=2.0.0", "to": "<=3.*.*", "fn": [MigrateFN, MigrateFN]} +var Migrations = []Migration{ + {From: ">=2.0.0", To: "<4.0.0-0", Functions: []MigrationFn{v3.MigrateHandlerSignatures}}, + {From: ">=1.0.0", To: ">=0.0.0-0", Functions: []MigrationFn{MigrateGoPkgs}}, +} + +// DoMigration runs all migrations +// It will run all migrations that match the current and target version +func DoMigration(cmd *cobra.Command, cwd string, curr *semver.Version, target *semver.Version) error { + for _, m := range Migrations { + toC, err := semver.NewConstraint(m.To) + if err != nil { + return err + } + fromC, err := semver.NewConstraint(m.From) + if err != nil { + return err + } + + if fromC.Check(curr) && toC.Check(target) { + for _, fn := range m.Functions { + if err := fn(cmd, cwd, curr, target); err != nil { + return err + } + } + } else { + fmt.Printf("Skipping migration from %s to %s\n", m.From, m.To) + } + } + + return nil +} diff --git a/cmd/internal/migrations/v3/common.go b/cmd/internal/migrations/v3/common.go new file mode 100644 index 0000000..4a8fc42 --- /dev/null +++ b/cmd/internal/migrations/v3/common.go @@ -0,0 +1,24 @@ +package v3 + +import ( + "fmt" + "github.com/spf13/cobra" + "strings" + + "github.com/gofiber/cli/cmd/internal" +) + +func MigrateHandlerSignatures(cmd *cobra.Command, cwd string, _ *semver.Version, _ *semver.Version) error { + sigReplacer := strings.NewReplacer("*fiber.Ctx", "fiber.Ctx") + + err := internal.ChangeFileContent(cwd, func(content string) string { + return sigReplacer.Replace(content) + }) + if err != nil { + return fmt.Errorf("failed to migrate handler signatures: %v", err) + } + + cmd.Println("Migrating handler signatures") + + return nil +} diff --git a/cmd/migrate.go b/cmd/migrate.go new file mode 100644 index 0000000..b46f3f0 --- /dev/null +++ b/cmd/migrate.go @@ -0,0 +1,64 @@ +package cmd + +import ( + "fmt" + "github.com/Masterminds/semver/v3" + "github.com/gofiber/cli/cmd/internal/migrations" + "github.com/muesli/termenv" + "github.com/spf13/cobra" + "os" + "strings" +) + +var ( + targetVersionS string + latestFiberVersion string +) + +func init() { + latestFiberVersion, _ := latestVersion(false) + + migrateCmd.Flags().StringVarP(&targetVersionS, "to", "t", "", "Migrate to a specific version e.g: "+latestFiberVersion+" Format: X.Y.Z") + migrateCmd.MarkFlagRequired("to") +} + +var migrateCmd = &cobra.Command{ + Use: "migrate", + Short: "Migrate Fiber project version to a newer version", + RunE: migrateRunE, +} + +func migrateRunE(cmd *cobra.Command, _ []string) error { + currentVersionS, err := currentVersion() + if err != nil { + return fmt.Errorf("current fiber project version not found: %v", err) + } + currentVersionS = strings.TrimPrefix(currentVersionS, "v") + currentVersion := semver.MustParse(currentVersionS) + + targetVersionS = strings.TrimPrefix(targetVersionS, "v") + targetVersion, err := semver.NewVersion(targetVersionS) + if err != nil { + return fmt.Errorf("invalid version for \"%s\": %v", targetVersionS, err) + } + + if !targetVersion.GreaterThan(currentVersion) { + return fmt.Errorf("target version v%s is not greater than current version v%s", targetVersionS, currentVersionS) + } + + wd, err := os.Getwd() + if err != nil { + return fmt.Errorf("cannot get current working directory: %v", err) + } + + err = migrations.DoMigration(cmd, wd, currentVersion, targetVersion) + if err != nil { + return fmt.Errorf("migration failed %v", err) + } + + msg := fmt.Sprintf("Migration from Fiber %s to %s", currentVersionS, targetVersionS) + cmd.Println(termenv.String(msg). + Foreground(termenv.ANSIBrightBlue)) + + return nil +} diff --git a/cmd/root.go b/cmd/root.go index 2d5d16d..30cd557 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -25,7 +25,7 @@ type rootConfig struct { func init() { rootCmd.AddCommand( - versionCmd, newCmd, devCmd, upgradeCmd, + versionCmd, newCmd, devCmd, upgradeCmd, migrateCmd, ) } diff --git a/cmd/version.go b/cmd/version.go index b94a107..1c0c93c 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -3,8 +3,9 @@ package cmd import ( "errors" "fmt" - "io/ioutil" + "io" "net/http" + "os" "regexp" "github.com/spf13/cobra" @@ -39,7 +40,7 @@ var currentVersionRegexp = regexp.MustCompile(`github\.com/gofiber/fiber[^\n]*? var currentVersionFile = "go.mod" func currentVersion() (string, error) { - b, err := ioutil.ReadFile(currentVersionFile) + b, err := os.ReadFile(currentVersionFile) if err != nil { return "", err } @@ -73,7 +74,7 @@ func latestVersion(isCli bool) (v string, err error) { _ = res.Body.Close() }() - if b, err = ioutil.ReadAll(res.Body); err != nil { + if b, err = io.ReadAll(res.Body); err != nil { return } diff --git a/development.md b/development.md new file mode 100644 index 0000000..39895eb --- /dev/null +++ b/development.md @@ -0,0 +1,17 @@ +# Local Development + +Install [air](github.com/cosmtrek/air) +```bash +go install github.com/cosmtrek/air@latest +``` + +Use air to watch for changes in the project and recompile the binary +```bash +air --build.cmd="go install ./fiber" +``` + +Test the binary in fiber project +```bash +cd my-fiber-project +fiber version +``` \ No newline at end of file diff --git a/go.mod b/go.mod index 1b2adae..d84271d 100644 --- a/go.mod +++ b/go.mod @@ -1,40 +1,42 @@ module github.com/gofiber/cli -go 1.21 +go 1.22 require ( - github.com/charmbracelet/bubbles v0.18.0 - github.com/charmbracelet/bubbletea v0.25.0 + github.com/Masterminds/semver/v3 v3.3.1 + github.com/charmbracelet/bubbles v0.20.0 + github.com/charmbracelet/bubbletea v1.2.4 github.com/containerd/console v1.0.4 - github.com/fsnotify/fsnotify v1.7.0 + github.com/fsnotify/fsnotify v1.8.0 github.com/jarcoal/httpmock v1.3.1 github.com/muesli/termenv v0.15.2 - github.com/spf13/cobra v1.8.0 - github.com/stretchr/testify v1.9.0 + github.com/spf13/cobra v1.8.1 + github.com/stretchr/testify v1.10.0 ) require ( github.com/atotto/clipboard v0.1.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/charmbracelet/lipgloss v0.9.1 // indirect + github.com/charmbracelet/lipgloss v1.0.0 // indirect + github.com/charmbracelet/x/ansi v0.5.2 // indirect + github.com/charmbracelet/x/term v0.2.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kr/text v0.2.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - github.com/mattn/go-isatty v0.0.18 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-localereader v0.0.1 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect - github.com/muesli/reflow v0.3.0 // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rivo/uniseg v0.4.6 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/term v0.6.0 // indirect - golang.org/x/text v0.3.8 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 76f7888..8fb4e8f 100644 --- a/go.sum +++ b/go.sum @@ -1,21 +1,29 @@ +github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= +github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= 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/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= -github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= -github.com/charmbracelet/bubbletea v0.25.0 h1:bAfwk7jRz7FKFl9RzlIULPkStffg5k6pNt5dywy4TcM= -github.com/charmbracelet/bubbletea v0.25.0/go.mod h1:EN3QDR1T5ZdWmdfDzYcqOCAps45+QIJbLOBxmVNWNNg= -github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg= -github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I= +github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE= +github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU= +github.com/charmbracelet/bubbletea v1.2.4 h1:KN8aCViA0eps9SCOThb2/XPIlea3ANJLUkv3KnQRNCE= +github.com/charmbracelet/bubbletea v1.2.4/go.mod h1:Qr6fVQw+wX7JkWWkVyXYk/ZUQ92a6XNekLXa3rR18MM= +github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg= +github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo= +github.com/charmbracelet/x/ansi v0.5.2 h1:dEa1x2qdOZXD/6439s+wF7xjV+kZLu/iN00GuXXrU9E= +github.com/charmbracelet/x/ansi v0.5.2/go.mod h1:KBUFw1la39nl0dLl10l5ORDAqGXaeurTQmwyyVKse/Q= +github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= +github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jarcoal/httpmock v1.3.1 h1:iUx3whfZWVf3jT01hQTO/Eo5sAYtB2/rqaUuOtpInww= @@ -26,48 +34,43 @@ 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/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +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-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= -github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -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/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/maxatome/go-testdeep v1.12.0 h1:Ql7Go8Tg0C1D/uMMX59LAoYK7LffeJQ6X2T04nTH68g= github.com/maxatome/go-testdeep v1.12.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM= -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/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.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/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.6 h1:Sovz9sDSwbOz9tgUy8JpT+KgCkPYJEN/oYzlJiYTNLg= -github.com/rivo/uniseg v0.4.6/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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= 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/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=