diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..07562a6
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,21 @@
+# EditorConfig is awesome: https://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = false
+insert_final_newline = false
+
+[*.yml]
+indent_size = 2
+
+[*.yaml]
+indent_size = 2
+
+[*.md]
+trim_trailing_whitespace = true
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..5ace460
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,6 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
deleted file mode 100644
index b6e6d42..0000000
--- a/.github/workflows/lint.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-name: golangci-lint
-on:
- push:
- tags:
- - v*
- branches:
- - master
- - main
- pull_request:
-permissions:
- contents: read
-jobs:
- golangci:
- name: lint
- runs-on: ubuntu-latest
- steps:
- - uses: actions/setup-go@v3
- with:
- go-version: ~1.17.0
- - uses: actions/checkout@v3
- - name: golangci-lint
- uses: golangci/golangci-lint-action@v3
- with:
- version: v1.45
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
new file mode 100644
index 0000000..f606f9b
--- /dev/null
+++ b/.github/workflows/pre-commit.yml
@@ -0,0 +1,19 @@
+name: golangci-lint
+on:
+ pull_request:
+ push:
+ branches: [main]
+
+permissions:
+ contents: read
+jobs:
+ golangci:
+ name: lint
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: jdx/mise-action@v2
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.11.4"
+ - uses: pre-commit/action@v3.0.1
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 5a02803..feaa1d0 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,28 +1,56 @@
name: boss-release
+
on:
push:
- branches: [ main ]
+ branches:
+ - main
tags:
- - 'v*'
+ - v*
+
+permissions:
+ contents: write
jobs:
- build:
+ goreleaser:
runs-on: ubuntu-latest
steps:
- - name: checkout
- uses: actions/checkout@v3
- - name: setup go
- uses: actions/setup-go@v3
- with:
- go-version: ~1.17.0
- - name: build
- run: |
- make dist && echo $(pwd)
-
- - name: Release
- uses: softprops/action-gh-release@v1
- if: startsWith(github.ref, 'refs/tags/')
- with:
- files: |
- _dist/*.zip
- _dist/*.tar.gz`
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Set up tooling
+ uses: jdx/mise-action@v2
+
+ - name: Run GoReleaser
+ uses: goreleaser/goreleaser-action@v6
+ with:
+ distribution: goreleaser
+ version: "~> v2"
+ args: release --clean --auto-snapshot
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - uses: actions/upload-artifact@v4
+ with:
+ path: dist/boss_windows_amd64_v1/boss.exe
+ if-no-files-found: warn
+
+ build-setup:
+ runs-on: windows-latest
+ needs: goreleaser
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ - uses: actions/download-artifact@v4
+
+ - name: Compile .ISS to .EXE Installer
+ uses: Minionguyjpro/Inno-Setup-Action@v1.2.5
+ env:
+ VERSION: ${{ github.ref }}
+ BIN_DIR: dist/boss_windows_amd64_v1/boss.exe
+ with:
+ path: ./assets/installer/boss.iss
+ options: /O+
diff --git a/.gitignore b/.gitignore
index 120c754..29855f6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,3 +37,7 @@ boss.json
_dist
bin/
.env
+# Added by goreleaser init:
+dist/
+test_dir/
+.vscode/settings.json
diff --git a/.golangci.yml b/.golangci.yml
new file mode 100644
index 0000000..d47e3f3
--- /dev/null
+++ b/.golangci.yml
@@ -0,0 +1,406 @@
+# This file is licensed under the terms of the MIT license https://opensource.org/license/mit
+# Copyright (c) 2021-2025 Marat Reymers
+
+## Golden config for golangci-lint v1.64.7
+#
+# This is the best config for golangci-lint based on my experience and opinion.
+# It is very strict, but not extremely strict.
+# Feel free to adapt it to suit your needs.
+# If this config helps you, please consider keeping a link to this file (see the next comment).
+
+# Based on https://gist.github.com/maratori/47a4d00457a92aa426dbd48a18776322
+
+run:
+ # Timeout for analysis, e.g. 30s, 5m.
+ # Default: 1m
+ timeout: 3m
+
+ # The mode used to evaluate relative paths.
+ # It's used by exclusions, Go plugins, and some linters.
+ # The value can be:
+ # - `gomod`: the paths will be relative to the directory of the `go.mod` file.
+ # - `gitroot`: the paths will be relative to the git root (the parent directory of `.git`).
+ # - `cfg`: the paths will be relative to the configuration file.
+ # - `wd` (NOT recommended): the paths will be relative to the place where golangci-lint is run.
+ # Default: wd
+ relative-path-mode: gomod
+
+
+# This file contains only configs which differ from defaults.
+# All possible options can be found here https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.reference.yml
+linters-settings:
+ cyclop:
+ # The maximal code complexity to report.
+ # Default: 10
+ max-complexity: 30
+ # The maximal average package complexity.
+ # If it's higher than 0.0 (float) the check is enabled
+ # Default: 0.0
+ package-average: 10.0
+
+ depguard:
+ # Rules to apply.
+ #
+ # Variables:
+ # - File Variables
+ # Use an exclamation mark `!` to negate a variable.
+ # Example: `!$test` matches any file that is not a go test file.
+ #
+ # `$all` - matches all go files
+ # `$test` - matches all go test files
+ #
+ # - Package Variables
+ #
+ # `$gostd` - matches all of go's standard library (Pulled from `GOROOT`)
+ #
+ # Default (applies if no custom rules are defined): Only allow $gostd in all files.
+ rules:
+ "deprecated":
+ # List of file globs that will match this list of settings to compare against.
+ # Default: $all
+ files:
+ - "$all"
+ # List of packages that are not allowed.
+ # Entries can be a variable (starting with $), a string prefix, or an exact match (if ending with $).
+ # Default: []
+ deny:
+ - pkg: "github.com/golang/protobuf"
+ desc: "Use google.golang.org/protobuf instead, see https://developers.google.com/protocol-buffers/docs/reference/go/faq#modules"
+ - pkg: "github.com/satori/go.uuid"
+ desc: "Use github.com/google/uuid instead, satori's package is not maintained"
+ - pkg: "github.com/gofrs/uuid$"
+ desc: "Use github.com/gofrs/uuid/v5 or later, it was not a go module before v5"
+ "non-test files":
+ files:
+ - "!$test"
+ deny:
+ - pkg: "math/rand$"
+ desc: "Use math/rand/v2 instead, see https://go.dev/blog/randv2"
+ "non-main files":
+ files:
+ - "!**/main.go"
+ deny:
+ - pkg: "log$"
+ desc: "Use log/slog instead, see https://go.dev/blog/slog"
+
+ errcheck:
+ # Report about not checking of errors in type assertions: `a := b.(MyStruct)`.
+ # Such cases aren't reported by default.
+ # Default: false
+ check-type-assertions: true
+
+ exhaustive:
+ # Program elements to check for exhaustiveness.
+ # Default: [ switch ]
+ check:
+ - switch
+ - map
+
+ exhaustruct:
+ # List of regular expressions to exclude struct packages and their names from checks.
+ # Regular expressions must match complete canonical struct package/name/structname.
+ # Default: []
+ exclude:
+ # std libs
+ - "^net/http.Client$"
+ - "^net/http.Cookie$"
+ - "^net/http.Request$"
+ - "^net/http.Response$"
+ - "^net/http.Server$"
+ - "^net/http.Transport$"
+ - "^net/url.URL$"
+ - "^os/exec.Cmd$"
+ - "^reflect.StructField$"
+ # public libs
+ - "^github.com/Shopify/sarama.Config$"
+ - "^github.com/Shopify/sarama.ProducerMessage$"
+ - "^github.com/mitchellh/mapstructure.DecoderConfig$"
+ - "^github.com/prometheus/client_golang/.+Opts$"
+ - "^github.com/spf13/cobra.Command$"
+ - "^github.com/spf13/cobra.CompletionOptions$"
+ - "^github.com/stretchr/testify/mock.Mock$"
+ - "^github.com/testcontainers/testcontainers-go.+Request$"
+ - "^github.com/testcontainers/testcontainers-go.FromDockerfile$"
+ - "^golang.org/x/tools/go/analysis.Analyzer$"
+ - "^google.golang.org/protobuf/.+Options$"
+ - "^gopkg.in/yaml.v3.Node$"
+
+ funlen:
+ # Checks the number of lines in a function.
+ # If lower than 0, disable the check.
+ # Default: 60
+ lines: 100
+ # Checks the number of statements in a function.
+ # If lower than 0, disable the check.
+ # Default: 40
+ statements: 50
+ # Ignore comments when counting lines.
+ # Default false
+ ignore-comments: true
+
+ gochecksumtype:
+ # Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed.
+ # Default: true
+ default-signifies-exhaustive: false
+
+ gocognit:
+ # Minimal code complexity to report.
+ # Default: 30 (but we recommend 10-20)
+ min-complexity: 20
+
+ gocritic:
+ # Settings passed to gocritic.
+ # The settings key is the name of a supported gocritic checker.
+ # The list of supported checkers can be find in https://go-critic.github.io/overview.
+ settings:
+ captLocal:
+ # Whether to restrict checker to params only.
+ # Default: true
+ paramsOnly: false
+ underef:
+ # Whether to skip (*x).method() calls where x is a pointer receiver.
+ # Default: true
+ skipRecvDeref: false
+
+ govet:
+ # Enable all analyzers.
+ # Default: false
+ enable-all: true
+ # Disable analyzers by name.
+ # Run `go tool vet help` to see all analyzers.
+ # Default: []
+ disable:
+ - fieldalignment # too strict
+ # Settings per analyzer.
+ settings:
+ shadow:
+ # Whether to be strict about shadowing; can be noisy.
+ # Default: false
+ strict: false
+
+ inamedparam:
+ # Skips check for interface methods with only a single parameter.
+ # Default: false
+ skip-single-param: true
+
+ mnd:
+ # List of function patterns to exclude from analysis.
+ # Values always ignored: `time.Date`,
+ # `strconv.FormatInt`, `strconv.FormatUint`, `strconv.FormatFloat`,
+ # `strconv.ParseInt`, `strconv.ParseUint`, `strconv.ParseFloat`.
+ # Default: []
+ ignored-functions:
+ - args.Error
+ - flag.Arg
+ - flag.Duration.*
+ - flag.Float.*
+ - flag.Int.*
+ - flag.Uint.*
+ - os.Chmod
+ - os.Mkdir.*
+ - os.OpenFile
+ - os.WriteFile
+ - prometheus.ExponentialBuckets.*
+ - prometheus.LinearBuckets
+
+ nakedret:
+ # Make an issue if func has more lines of code than this setting, and it has naked returns.
+ # Default: 30
+ max-func-lines: 0
+
+ nolintlint:
+ # Exclude following linters from requiring an explanation.
+ # Default: []
+ allow-no-explanation: [ funlen, gocognit, lll ]
+ # Enable to require an explanation of nonzero length after each nolint directive.
+ # Default: false
+ require-explanation: true
+ # Enable to require nolint directives to mention the specific linter being suppressed.
+ # Default: false
+ require-specific: true
+
+ perfsprint:
+ # Optimizes into strings concatenation.
+ # Default: true
+ strconcat: false
+
+ reassign:
+ # Patterns for global variable names that are checked for reassignment.
+ # See https://github.com/curioswitch/go-reassign#usage
+ # Default: ["EOF", "Err.*"]
+ patterns:
+ - ".*"
+
+ rowserrcheck:
+ # database/sql is always checked
+ # Default: []
+ packages:
+ - github.com/jmoiron/sqlx
+
+ sloglint:
+ # Enforce not using global loggers.
+ # Values:
+ # - "": disabled
+ # - "all": report all global loggers
+ # - "default": report only the default slog logger
+ # https://github.com/go-simpler/sloglint?tab=readme-ov-file#no-global
+ # Default: ""
+ no-global: "all"
+ # Enforce using methods that accept a context.
+ # Values:
+ # - "": disabled
+ # - "all": report all contextless calls
+ # - "scope": report only if a context exists in the scope of the outermost function
+ # https://github.com/go-simpler/sloglint?tab=readme-ov-file#context-only
+ # Default: ""
+ context: "scope"
+
+ usetesting:
+ # Enable/disable `os.TempDir()` detections.
+ # Default: false
+ os-temp-dir: true
+
+
+linters:
+ disable-all: true
+ enable:
+ ## enabled by default
+ - errcheck # checking for unchecked errors, these unchecked errors can be critical bugs in some cases
+ - gosimple # specializes in simplifying a code
+ - govet # reports suspicious constructs, such as Printf calls whose arguments do not align with the format string
+ - ineffassign # detects when assignments to existing variables are not used
+ - staticcheck # is a go vet on steroids, applying a ton of static analysis checks
+ - typecheck # like the front-end of a Go compiler, parses and type-checks Go code
+ - unused # checks for unused constants, variables, functions and types
+ ## disabled by default
+ - asasalint # checks for pass []any as any in variadic func(...any)
+ - asciicheck # checks that your code does not contain non-ASCII identifiers
+ - bidichk # checks for dangerous unicode character sequences
+ - bodyclose # checks whether HTTP response body is closed successfully
+ - canonicalheader # checks whether net/http.Header uses canonical header
+ - copyloopvar # detects places where loop variables are copied (Go 1.22+)
+ - cyclop # checks function and package cyclomatic complexity
+ - depguard # checks if package imports are in a list of acceptable packages
+ - dupl # tool for code clone detection
+ - durationcheck # checks for two durations multiplied together
+ - errname # checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error
+ - errorlint # finds code that will cause problems with the error wrapping scheme introduced in Go 1.13
+ - exhaustive # checks exhaustiveness of enum switch statements
+ - exptostd # detects functions from golang.org/x/exp/ that can be replaced by std functions
+ - fatcontext # detects nested contexts in loops
+ - forbidigo # forbids identifiers
+ - funlen # tool for detection of long functions
+ - gocheckcompilerdirectives # validates go compiler directive comments (//go:)
+ - gochecknoglobals # checks that no global variables exist
+ - gochecknoinits # checks that no init functions are present in Go code
+ - gochecksumtype # checks exhaustiveness on Go "sum types"
+ - gocognit # computes and checks the cognitive complexity of functions
+ - goconst # finds repeated strings that could be replaced by a constant
+ - gocritic # provides diagnostics that check for bugs, performance and style issues
+ - gocyclo # computes and checks the cyclomatic complexity of functions
+ - godot # checks if comments end in a period
+ - goimports # in addition to fixing imports, goimports also formats your code in the same style as gofmt
+ - gomoddirectives # manages the use of 'replace', 'retract', and 'excludes' directives in go.mod
+ - goprintffuncname # checks that printf-like functions are named with f at the end
+ - gosec # inspects source code for security problems
+ - iface # checks the incorrect use of interfaces, helping developers avoid interface pollution
+ - intrange # finds places where for loops could make use of an integer range
+ - lll # reports long lines
+ - loggercheck # checks key value pairs for common logger libraries (kitlog,klog,logr,zap)
+ - makezero # finds slice declarations with non-zero initial length
+ - mirror # reports wrong mirror patterns of bytes/strings usage
+ # - mnd # detects magic numbers
+ - musttag # enforces field tags in (un)marshaled structs
+ - nakedret # finds naked returns in functions greater than a specified function length
+ - nestif # reports deeply nested if statements
+ - nilerr # finds the code that returns nil even if it checks that the error is not nil
+ - nilnesserr # reports that it checks for err != nil, but it returns a different nil value error (powered by nilness and nilerr)
+ - nilnil # checks that there is no simultaneous return of nil error and an invalid value
+ - noctx # finds sending http request without context.Context
+ - nolintlint # reports ill-formed or insufficient nolint directives
+ - nonamedreturns # reports all named returns
+ - nosprintfhostport # checks for misuse of Sprintf to construct a host with port in a URL
+ - perfsprint # checks that fmt.Sprintf can be replaced with a faster alternative
+ - predeclared # finds code that shadows one of Go's predeclared identifiers
+ - promlinter # checks Prometheus metrics naming via promlint
+ - protogetter # reports direct reads from proto message fields when getters should be used
+ - reassign # checks that package variables are not reassigned
+ - recvcheck # checks for receiver type consistency
+ - revive # fast, configurable, extensible, flexible, and beautiful linter for Go, drop-in replacement of golint
+ - rowserrcheck # checks whether Err of rows is checked successfully
+ - sloglint # ensure consistent code style when using log/slog
+ - spancheck # checks for mistakes with OpenTelemetry/Census spans
+ - sqlclosecheck # checks that sql.Rows and sql.Stmt are closed
+ - stylecheck # is a replacement for golint
+ - testableexamples # checks if examples are testable (have an expected output)
+ - testifylint # checks usage of github.com/stretchr/testify
+ - testpackage # makes you use a separate _test package
+ - tparallel # detects inappropriate usage of t.Parallel() method in your Go test codes
+ - unconvert # removes unnecessary type conversions
+ - unparam # reports unused function parameters
+ - usestdlibvars # detects the possibility to use variables/constants from the Go standard library
+ - usetesting # reports uses of functions with replacement inside the testing package
+ - wastedassign # finds wasted assignment statements
+ - whitespace # detects leading and trailing whitespace
+
+ ## you may want to enable
+ #- decorder # checks declaration order and count of types, constants, variables and functions
+ #- exhaustruct # [highly recommend to enable] checks if all structure fields are initialized
+ #- gci # controls golang package import order and makes it always deterministic
+ #- ginkgolinter # [if you use ginkgo/gomega] enforces standards of using ginkgo and gomega
+ #- godox # detects usage of FIXME, TODO and other keywords inside comments
+ #- goheader # checks is file header matches to pattern
+ #- inamedparam # [great idea, but too strict, need to ignore a lot of cases by default] reports interfaces with unnamed method parameters
+ #- interfacebloat # checks the number of methods inside an interface
+ #- ireturn # accept interfaces, return concrete types
+ #- prealloc # [premature optimization, but can be used in some cases] finds slice declarations that could potentially be preallocated
+ #- tagalign # checks that struct tags are well aligned
+ #- varnamelen # [great idea, but too many false positives] checks that the length of a variable's name matches its scope
+ #- wrapcheck # checks that errors returned from external packages are wrapped
+ #- zerologlint # detects the wrong usage of zerolog that a user forgets to dispatch zerolog.Event
+
+ ## disabled
+ #- containedctx # detects struct contained context.Context field
+ #- contextcheck # [too many false positives] checks the function whether use a non-inherited context
+ #- dogsled # checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())
+ #- dupword # [useless without config] checks for duplicate words in the source code
+ #- err113 # [too strict] checks the errors handling expressions
+ #- errchkjson # [don't see profit + I'm against of omitting errors like in the first example https://github.com/breml/errchkjson] checks types passed to the json encoding functions. Reports unsupported types and optionally reports occasions, where the check for the returned error can be omitted
+ #- forcetypeassert # [replaced by errcheck] finds forced type assertions
+ #- gofmt # [replaced by goimports] checks whether code was gofmt-ed
+ #- gofumpt # [replaced by goimports, gofumports is not available yet] checks whether code was gofumpt-ed
+ #- gomodguard # [use more powerful depguard] allow and block lists linter for direct Go module dependencies
+ #- gosmopolitan # reports certain i18n/l10n anti-patterns in your Go codebase
+ #- grouper # analyzes expression groups
+ #- importas # enforces consistent import aliases
+ #- maintidx # measures the maintainability index of each function
+ #- misspell # [useless] finds commonly misspelled English words in comments
+ #- nlreturn # [too strict and mostly code is not more readable] checks for a new line before return and branch statements to increase code clarity
+ #- paralleltest # [too many false positives] detects missing usage of t.Parallel() method in your Go test
+ #- tagliatelle # checks the struct tags
+ #- tenv # [deprecated, replaced by usetesting] detects using os.Setenv instead of t.Setenv since Go1.17
+ #- thelper # detects golang test helpers without t.Helper() call and checks the consistency of test helpers
+ #- wsl # [too strict and mostly code is not more readable] whitespace linter forces you to use empty lines
+
+
+issues:
+ # Maximum count of issues with the same text.
+ # Set to 0 to disable.
+ # Default: 3
+ max-same-issues: 50
+
+ exclude-rules:
+ - source: "(noinspection|TODO)"
+ linters: [ godot ]
+ - source: "//noinspection"
+ linters: [ gocritic ]
+ - path: "_test\\.go"
+ linters:
+ - bodyclose
+ - dupl
+ - errcheck
+ - funlen
+ - goconst
+ - gosec
+ - noctx
+ - wrapcheck
diff --git a/.goreleaser.yaml b/.goreleaser.yaml
new file mode 100644
index 0000000..c41b186
--- /dev/null
+++ b/.goreleaser.yaml
@@ -0,0 +1,45 @@
+version: 2
+
+before:
+ hooks:
+ - go mod tidy
+ - go generate ./...
+
+builds:
+ - env:
+ - CGO_ENABLED=0
+ goos:
+ - linux
+ - windows
+ - darwin
+ ldflags:
+ - github.com/hashload/boss/internal/version.metadata={{.Version}}
+ - github.com/hashload/boss/internal/version.gitCommit={{.Commit}}
+
+archives:
+ - formats: [ tar.gz ]
+ name_template: >-
+ {{ .ProjectName }}_
+ {{- title .Os }}_
+ {{- if eq .Arch "amd64" }}x86_64
+ {{- else if eq .Arch "386" }}i386
+ {{- else }}{{ .Arch }}{{ end }}
+ {{- if .Arm }}v{{ .Arm }}{{ end }}
+ # use zip for windows archives
+ format_overrides:
+ - goos: windows
+ formats: [ zip ]
+
+changelog:
+ sort: asc
+ filters:
+ exclude:
+ - "^docs:"
+ - "^test:"
+
+release:
+ footer: >-
+
+ ---
+
+ Released by [GoReleaser](https://github.com/goreleaser/goreleaser).
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 622c094..1f84ed7 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,35 +1,24 @@
---
- repos:
+repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.1.0
+ rev: v5.0.0
hooks:
- - id: check-added-large-files
- - id: check-byte-order-marker
- - id: check-executables-have-shebangs
- - id: check-merge-conflict
- - id: end-of-file-fixer
- - id: mixed-line-ending
- - id: check-yaml
- - id: detect-private-key
- - id: check-symlinks
- - id: detect-aws-credentials
- - id: trailing-whitespace
- args: [--markdown-linebreak-ext=md]
+ - id: check-added-large-files
+ - id: check-byte-order-marker
+ - id: check-executables-have-shebangs
+ - id: check-merge-conflict
+ - id: end-of-file-fixer
+ - id: mixed-line-ending
+ - id: check-yaml
+ - id: detect-private-key
+ - id: check-symlinks
+ - id: trailing-whitespace
+ args: [--markdown-linebreak-ext=md]
- - repo: https://github.com/dnephin/pre-commit-golang
- rev: v0.5.0
+ - repo: https://github.com/golangci/golangci-lint
+ rev: v1.64.5
hooks:
- - id: go-fmt
- # - id: go-vet
- - id: go-imports
- - id: go-cyclo
- args: [-over=15]
- - id: validate-toml
- - id: no-go-testing
- - id: golangci-lint
- args:
- - "--go=1.18"
- - id: go-critic
- # - id: go-unit-tests
- - id: go-build
- - id: go-mod-tidy
+ - id: golangci-lint-config-verify
+ entry: go tool golangci-lint config verify
+ - id: golangci-lint-full
+ entry: go tool golangci-lint run --fix
diff --git a/.vscode/launch.json b/.vscode/launch.json
index e2c348c..2a5f28b 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -10,7 +10,8 @@
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}",
- "args": ["upgrade"],
+ "cwd": "${workspaceFolder}/test_dir",
+ "args": ["install", "jhonson"],
}
]
}
diff --git a/Makefile b/Makefile
index 1bb3014..a587dba 100644
--- a/Makefile
+++ b/Makefile
@@ -39,7 +39,6 @@ endif
LDFLAGS += -X github.com/hashload/boss/internal/version.metadata=${VERSION_METADATA}
LDFLAGS += -X github.com/hashload/boss/internal/version.gitCommit=${GIT_COMMIT}
-LDFLAGS += -X github.com/hashload/boss/internal/version.gitTreeState=${GIT_DIRTY}
.PHONY: all
run:
@GO111MODULE=on go run $(word 2, $(MAKECMDGOALS) )
diff --git a/README.md b/README.md
index 35174e3..00ed9d0 100644
--- a/README.md
+++ b/README.md
@@ -1,133 +1,181 @@
-
-
-
-
-
-
- Boss is an open source dependency manager inspired by npm for projects developed in Delphi and Lazarus .
-
-
-
-
-
-
-
-
-
-### [Getting started](https://medium.com/@matheusarendthunsche/come%C3%A7ando-com-o-boss-72aad9bcc13)
-
-Installation:
- * Download [setup](https://github.com/hashload/boss/releases)
- * Just type `boss` in cmd
- * (Optional) Install a [Boss Delphi IDE complement](https://github.com/hashload/boss-ide)
-
-## Available Commands
+# Boss
+
+![Boss][bossLogo]
+![GitHub release (latest by date)][latestReleaseBadge]
+![GitHub Release Date][releaseDateBadge]
+![GitHub repo size][repoSizeBadge]
+![GitHub All Releases][totalDownloadsBadge]
+![GitHub][githubLicenseBadge]
+![GitHub issues][githubIssuesBadge]
+![GitHub pull requests][githubPullRequestsBadge]
+![GitHub contributors][githubContributorsBadge]
+![Github Stars][repoStarsBadge]
+
+_Boss_ is an open source dependency manager inspired by [npm](https://www.npmjs.com/) for projects developed in _Delphi_ and _Lazarus_.
+
+[![Boss][telegramBadge]][telegramLink]
+
+
+
+## 🚀 Getting started
+
+We have a [Getting Started](https://medium.com/@matheusarendthunsche/come%C3%A7ando-com-o-boss-72aad9bcc13) article to help you get started with Boss.
+
+## 📦 Installation
+
+- Download [setup](https://github.com/hashload/boss/releases)
+- Just type `boss` in the terminal
+- (Optional) Install a [Boss Delphi IDE complement](https://github.com/hashload/boss-ide)
+
+Or you can use the following the steps below:
+
+- Download the latest version of the [Boss](https://github.com/hashload/boss/releases)
+- Extract the files to a folder
+- Add the folder to the system path
+- Run the command `boss` in the terminal
+
+## 📚 Available Commands
### > Init
+
This command initialize a new project. Add `-q` or `--quiet` to initialize the boss with default values.
-```
+
+```shell
boss init
boss init -q
boss init --quiet
```
### > Install
+
This command install a new dependency
-```
+
+```shell
boss install
```
+
The dependency is case insensitive. For example, `boss install horse` is the same as the `boss install HORSE` command.
+
```pascal
boss install horse // By default, look for the Horse project within the GitHub Hashload organization.
boss install fake/horse // By default, look for the Horse project within the Fake GitHub organization.
boss install gitlab.com/fake/horse // By default, searches for the Horse project within the Fake GitLab organization.
boss install https://gitlab.com/fake/horse // You can also pass the full URL for installation
```
-###### Aliases: i, add
+
+> Aliases: i, add
### > Uninstall
+
This command uninstall a dependency
-```
+
+```sh
boss uninstall
```
-###### Aliases: remove, rm, r, un, unlink
+
+> Aliases: remove, rm, r, un, unlink
### > Cache
+
This command removes the cache
-```
+
+```sh
boss config cache rm
```
-###### Aliases: remove, rm, r
+
+> Aliases: remove, rm, r
### > Dependencies
+
This command print all dependencies and your versions. To see versions, add aliases `-v`
-```
+
+```shell
boss dependencies
boss dependencies -v
```
-###### Aliases: dep, ls, list, ll, la
+
+> Aliases: dep, ls, list, ll, la
### > Version
+
This command show the client version
-```
+
+```shell
boss v
boss version
boss -v
boss --version
```
-###### Aliases: v
+
+> Aliases: v
### > Update
+
This command update installed dependencies
-```
+
+```sh
boss update
```
-###### Aliases: up
+
+> Aliases: up
### > Upgrade
+
This command upgrade the client latest version. Add `--dev` to upgrade to the latest pre-release.
-```
+
+```sh
boss upgrade
boss upgrade --dev
```
### > login
+
This command Register login to repo
-```
+
+```sh
boss login
boss adduser
boss add-user
boss login -u UserName -p Password
boss login -k PrivateKey -p PassPhrase
```
-###### Aliases: adduser, add-user
+
+> Aliases: adduser, add-user
## Flags
### > Global
+
This flag defines a global environment
-```
+
+```sh
boss --global
```
-###### Aliases: -g
+
+> Aliases: -g
### > Help
+
This is a helper for boss. Use `boss --help` for more information about a command.
-```
+
+```sh
boss --help
```
-###### Aliases: -h
+
+> Aliases: -h
## Another commands
-```
+
+```sh
delphi Configure Delphi version
-gc Garbage collector
+gc Garbage collector
publish Publish package to registry
run Run cmd script
```
## Samples
-```
+
+```sh
boss install horse
boss install horse:1.0.0
boss install -g delphi-docker
@@ -136,16 +184,27 @@ boss install -g boss-ide
## Using [semantic versioning](https://semver.org/) to specify update types your package can accept
-You can specify which update types your package can accept from dependencies in your package’s boss.json file.
+You can specify which update types your package can accept from dependencies in your package's boss.json file.
For example, to specify acceptable version ranges up to 1.0.4, use the following syntax:
- * Patch releases: 1.0 or 1.0.x or ~1.0.4
- * Minor releases: 1 or 1.x or ^1.0.4
- * Major releases: * or x
-## 💻 Code Contributors
+- Patch releases: 1.0 or 1.0.x or ~1.0.4
+- Minor releases: 1 or 1.x or ^1.0.4
+- Major releases: \* or x
-
-
-
+## 💻 Code Contributors
+
+
+[githubContributorsBadge]: https://img.shields.io/github/contributors/hashload/boss
+[bossLogo]: ./assets/png/sized/boss-logo-128px.png
+[latestReleaseBadge]: https://img.shields.io/github/v/release/hashload/boss
+[releaseDateBadge]: https://img.shields.io/github/release-date/hashload/boss
+[repoSizeBadge]: https://img.shields.io/github/repo-size/hashload/boss
+[totalDownloadsBadge]: https://img.shields.io/github/downloads/hashload/boss/total
+[githubLicenseBadge]: https://img.shields.io/github/license/hashload/boss
+[githubIssuesBadge]: https://img.shields.io/github/issues/hashload/boss
+[githubPullRequestsBadge]: https://img.shields.io/github/issues-pr/hashload/boss
+[telegramBadge]: https://img.shields.io/badge/telegram-join%20channel-7289DA?style=flat-square
+[telegramLink]: https://t.me/hashload
+[repoStarsBadge]: https://img.shields.io/github/stars/hashload/boss?style=social
diff --git a/app.go b/app.go
index 92b8d71..9d19f5e 100644
--- a/app.go
+++ b/app.go
@@ -2,8 +2,11 @@ package main
import (
"github.com/hashload/boss/cmd"
+ "github.com/hashload/boss/pkg/msg"
)
func main() {
- cmd.Execute()
+ if err := cmd.Execute(); err != nil {
+ msg.Die(err.Error())
+ }
}
diff --git a/img/ai/Boss Icon.ai b/assets/ai/boss-icon.ai
similarity index 100%
rename from img/ai/Boss Icon.ai
rename to assets/ai/boss-icon.ai
diff --git a/img/ai/Boss Logo - white text.ai b/assets/ai/boss-logo-white-text.ai
similarity index 100%
rename from img/ai/Boss Logo - white text.ai
rename to assets/ai/boss-logo-white-text.ai
diff --git a/img/ai/Boss Logo.ai b/assets/ai/boss-logo.ai
similarity index 100%
rename from img/ai/Boss Logo.ai
rename to assets/ai/boss-logo.ai
diff --git a/installer/LICENSE.txt b/assets/installer/LICENSE.txt
similarity index 100%
rename from installer/LICENSE.txt
rename to assets/installer/LICENSE.txt
diff --git a/installer/boss.iss b/assets/installer/boss.iss
similarity index 96%
rename from installer/boss.iss
rename to assets/installer/boss.iss
index a6fe3a6..582e4b3 100644
--- a/installer/boss.iss
+++ b/assets/installer/boss.iss
@@ -1,5 +1,5 @@
#define BossName "Boss"
-#define BossVersion "3.0.5"
+#define BossVersion "{%VERSION|0.0.1}"
#define BossPublisher "Hashload"
#define BossURL "https://github.com/hashload/boss"
@@ -74,7 +74,7 @@ end;
Name: "{app}"; Permissions: everyone-full
[Files]
-Source: "boss.exe"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{%BIN_DIR|boss.exe}"; DestDir: "{app}"; Flags: ignoreversion
[Registry]
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}"; Check: NeedsAddPath('{app}')
diff --git a/img/png/Boss Icon - white.png b/assets/png/boss-icon-white.png
similarity index 100%
rename from img/png/Boss Icon - white.png
rename to assets/png/boss-icon-white.png
diff --git a/img/png/Boss Icon.png b/assets/png/boss-icon.png
similarity index 100%
rename from img/png/Boss Icon.png
rename to assets/png/boss-icon.png
diff --git a/img/png/Boss Logo.png b/assets/png/boss-log.png
similarity index 100%
rename from img/png/Boss Logo.png
rename to assets/png/boss-log.png
diff --git a/img/png/Boss Logo - white helmet.png b/assets/png/boss-logo-white-helmet.png
similarity index 100%
rename from img/png/Boss Logo - white helmet.png
rename to assets/png/boss-logo-white-helmet.png
diff --git a/img/png/Boss Logo - white text and helmet.png b/assets/png/boss-logo-white-text-helmet.png
similarity index 100%
rename from img/png/Boss Logo - white text and helmet.png
rename to assets/png/boss-logo-white-text-helmet.png
diff --git a/img/png/Boss Logo - white text.png b/assets/png/boss-logo-white-text.png
similarity index 100%
rename from img/png/Boss Logo - white text.png
rename to assets/png/boss-logo-white-text.png
diff --git a/img/png/sized/Boss Icon - 1024px.png b/assets/png/sized/boss-icon-1024px.png
similarity index 100%
rename from img/png/sized/Boss Icon - 1024px.png
rename to assets/png/sized/boss-icon-1024px.png
diff --git a/img/png/sized/Boss Icon - 256px.png b/assets/png/sized/boss-icon-256px.png
similarity index 100%
rename from img/png/sized/Boss Icon - 256px.png
rename to assets/png/sized/boss-icon-256px.png
diff --git a/img/png/sized/Boss Logo - 1024px.png b/assets/png/sized/boss-logo-1024px.png
similarity index 100%
rename from img/png/sized/Boss Logo - 1024px.png
rename to assets/png/sized/boss-logo-1024px.png
diff --git a/img/png/sized/Boss Logo - 128px.png b/assets/png/sized/boss-logo-128px.png
similarity index 100%
rename from img/png/sized/Boss Logo - 128px.png
rename to assets/png/sized/boss-logo-128px.png
diff --git a/img/png/sized/Boss Logo - white helmet - 1024px.png b/assets/png/sized/boss-logo-white-helmet-1024px.png
similarity index 100%
rename from img/png/sized/Boss Logo - white helmet - 1024px.png
rename to assets/png/sized/boss-logo-white-helmet-1024px.png
diff --git a/img/png/sized/Boss Logo - white helmet - 128px.png b/assets/png/sized/boss-logo-white-helmet-128px.png
similarity index 100%
rename from img/png/sized/Boss Logo - white helmet - 128px.png
rename to assets/png/sized/boss-logo-white-helmet-128px.png
diff --git a/img/png/sized/Boss Logo - white helmet - 256px.png b/assets/png/sized/boss-logo-white-helmet-256px.png
similarity index 100%
rename from img/png/sized/Boss Logo - white helmet - 256px.png
rename to assets/png/sized/boss-logo-white-helmet-256px.png
diff --git a/img/png/sized/Boss Logo - white text - 1024px.png b/assets/png/sized/boss-logo-white-text-1024px.png
similarity index 100%
rename from img/png/sized/Boss Logo - white text - 1024px.png
rename to assets/png/sized/boss-logo-white-text-1024px.png
diff --git a/img/png/sized/Boss Logo - white text - 128px.png b/assets/png/sized/boss-logo-white-text-128px.png
similarity index 100%
rename from img/png/sized/Boss Logo - white text - 128px.png
rename to assets/png/sized/boss-logo-white-text-128px.png
diff --git a/img/png/sized/Boss Logo - white text and helmet - 1024px.png b/assets/png/sized/boss-logo-white-text-and-helmet-1024px.png
similarity index 100%
rename from img/png/sized/Boss Logo - white text and helmet - 1024px.png
rename to assets/png/sized/boss-logo-white-text-and-helmet-1024px.png
diff --git a/img/png/sized/Boss Logo - white text and helmet - 128px.png b/assets/png/sized/boss-logo-white-text-and-helmet-128px.png
similarity index 100%
rename from img/png/sized/Boss Logo - white text and helmet - 128px.png
rename to assets/png/sized/boss-logo-white-text-and-helmet-128px.png
diff --git a/img/readme.md b/assets/readme.md
similarity index 77%
rename from img/readme.md
rename to assets/readme.md
index fe96ce2..4a68d8b 100644
--- a/img/readme.md
+++ b/assets/readme.md
@@ -1,17 +1,24 @@
+# Assets
+
The following logos and graphics are for the promption of the Boss project.
-* [Spartan Helmet](https://thenounproject.com/icon/spartan-helmet-1732608/) logo by [Jon Ramadhan](https://thenounproject.com/joni45/) via [The Noun Project](https://thenounproject.com/), via Royalty-Free, non-attribution, pro license only for use in this logo.
-* Font is [Good Times](https://fonts.adobe.com/fonts/good-times) Heavy, designed by [Ray Larabie](https://fonts.adobe.com/designers/ray-larabie), [Typodermic](https://fonts.adobe.com/foundries/typodermic) via [Adobe Fonts](https://fonts.adobe.com/)
-* AI source files created using [Adobe Illustrator](https://www.adobe.com/products/illustrator.html) v26.3.1 Creative Cloud 2022.
-* PNG files optimized by [TinyPNG](https://tinypng.com/)
-* SVG files otpimized with [Jake Archibald's SVGOMG](https://jakearchibald.github.io/svgomg/)
-* Tested and compatible in [InkScape](https://inkscape.org/) 1.2
+- [Spartan Helmet](https://thenounproject.com/icon/spartan-helmet-1732608/) logo by [Jon Ramadhan](https://thenounproject.com/joni45/) via [The Noun Project](https://thenounproject.com/), via Royalty-Free, non-attribution, pro license only for use in this logo.
+- Font is [Good Times](https://fonts.adobe.com/fonts/good-times) Heavy, designed by [Ray Larabie](https://fonts.adobe.com/designers/ray-larabie), [Typodermic](https://fonts.adobe.com/foundries/typodermic) via [Adobe Fonts](https://fonts.adobe.com/)
+- AI source files created using [Adobe Illustrator](https://www.adobe.com/products/illustrator.html) v26.3.1 Creative Cloud 2022.
+- PNG files optimized by [TinyPNG](https://tinypng.com/)
+- SVG files otpimized with [Jake Archibald's SVGOMG](https://jakearchibald.github.io/svgomg/)
+- Tested and compatible in [InkScape](https://inkscape.org/) 1.2
## [Boss Logo](./svg/Boss Logo.svg)
+

+
## [Boss Icon](./svg/Boss Icon.svg)
+

+
## Variations
+
[Boss Logo - white text](./svg/Boss Logo - white text.svg)

@@ -26,4 +33,4 @@ The following logos and graphics are for the promption of the Boss project.
[Boss Logo - without text](./svg/boss Logo - wo text.svg)

[Boss Icon - open face](./svg/boss Icon - open.svg)
-
\ No newline at end of file
+
diff --git a/img/svg/Boss Icon - open.svg b/assets/svg/boss-icon-open.svg
similarity index 99%
rename from img/svg/Boss Icon - open.svg
rename to assets/svg/boss-icon-open.svg
index 0421d83..d4692ca 100644
--- a/img/svg/Boss Icon - open.svg
+++ b/assets/svg/boss-icon-open.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/img/svg/Boss Icon - white.svg b/assets/svg/boss-icon-white.svg
similarity index 99%
rename from img/svg/Boss Icon - white.svg
rename to assets/svg/boss-icon-white.svg
index 0b15780..f4bda93 100644
--- a/img/svg/Boss Icon - white.svg
+++ b/assets/svg/boss-icon-white.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/img/svg/Boss Icon.svg b/assets/svg/boss-icon.svg
similarity index 99%
rename from img/svg/Boss Icon.svg
rename to assets/svg/boss-icon.svg
index 0f733a0..bb295e6 100644
--- a/img/svg/Boss Icon.svg
+++ b/assets/svg/boss-icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/img/svg/Boss Logo - white helmet wo text.svg b/assets/svg/boss-logo-white-helmet-wo-text.svg
similarity index 95%
rename from img/svg/Boss Logo - white helmet wo text.svg
rename to assets/svg/boss-logo-white-helmet-wo-text.svg
index f5cbad7..5215492 100644
--- a/img/svg/Boss Logo - white helmet wo text.svg
+++ b/assets/svg/boss-logo-white-helmet-wo-text.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/img/svg/Boss Logo - white helmet.svg b/assets/svg/boss-logo-white-helmet.svg
similarity index 99%
rename from img/svg/Boss Logo - white helmet.svg
rename to assets/svg/boss-logo-white-helmet.svg
index 84336d3..627a548 100644
--- a/img/svg/Boss Logo - white helmet.svg
+++ b/assets/svg/boss-logo-white-helmet.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/img/svg/Boss Logo - white text and helmet.svg b/assets/svg/boss-logo-white-text-and-helmet.svg
similarity index 99%
rename from img/svg/Boss Logo - white text and helmet.svg
rename to assets/svg/boss-logo-white-text-and-helmet.svg
index 7d1916f..c6df7ba 100644
--- a/img/svg/Boss Logo - white text and helmet.svg
+++ b/assets/svg/boss-logo-white-text-and-helmet.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/img/svg/Boss Logo - white text.svg b/assets/svg/boss-logo-white-text.svg
similarity index 99%
rename from img/svg/Boss Logo - white text.svg
rename to assets/svg/boss-logo-white-text.svg
index f668f64..bdea748 100644
--- a/img/svg/Boss Logo - white text.svg
+++ b/assets/svg/boss-logo-white-text.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/img/svg/Boss Logo - wo text.svg b/assets/svg/boss-logo-wo-text.svg
similarity index 96%
rename from img/svg/Boss Logo - wo text.svg
rename to assets/svg/boss-logo-wo-text.svg
index 3c489fc..1679ef6 100644
--- a/img/svg/Boss Logo - wo text.svg
+++ b/assets/svg/boss-logo-wo-text.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/img/svg/Boss Logo.svg b/assets/svg/boss-logo.svg
similarity index 99%
rename from img/svg/Boss Logo.svg
rename to assets/svg/boss-logo.svg
index f0644c6..5921343 100644
--- a/img/svg/Boss Logo.svg
+++ b/assets/svg/boss-logo.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/cmd/config/config.go b/cmd/config/config.go
index b6b29d0..13c4300 100644
--- a/cmd/config/config.go
+++ b/cmd/config/config.go
@@ -4,14 +4,13 @@ import (
"github.com/spf13/cobra"
)
-var CmdConfig = &cobra.Command{
- Use: "config",
- Short: "Configurations",
- Run: func(cmd *cobra.Command, args []string) {
- _ = cmd.Help()
- },
-}
+func RegisterConfigCommand(root *cobra.Command) {
+ configCmd := &cobra.Command{
+ Use: "config",
+ Short: "Configurations",
+ }
-func InitializeConfig(root *cobra.Command) {
- root.AddCommand(CmdConfig)
+ root.AddCommand(configCmd)
+ delphiCmd(configCmd)
+ registryGitCmd(configCmd)
}
diff --git a/cmd/config/delphi.go b/cmd/config/delphi.go
index a068dce..bdb1518 100644
--- a/cmd/config/delphi.go
+++ b/cmd/config/delphi.go
@@ -5,73 +5,74 @@ import (
"os"
"strconv"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/msg"
"github.com/hashload/boss/utils/dcc32"
"github.com/spf13/cobra"
)
-var cmdDelphi = &cobra.Command{
- Use: "delphi",
- Short: "Configure Delphi version",
- Long: `Configure Delphi version to compile modules`,
- Run: func(cmd *cobra.Command, args []string) {
- msg.Info("Running in path %s", env.GlobalConfiguration.DelphiPath)
- _ = cmd.Usage()
- },
-}
+func delphiCmd(root *cobra.Command) {
+ delphiCmd := &cobra.Command{
+ Use: "delphi",
+ Short: "Configure Delphi version",
+ Long: `Configure Delphi version to compile modules`,
+ Run: func(cmd *cobra.Command, _ []string) {
+ msg.Info("Running in path %s", env.GlobalConfiguration().DelphiPath)
+ _ = cmd.Usage()
+ },
+ }
+
+ list := &cobra.Command{
+ Use: "list",
+ Short: "List Delphi versions",
+ Long: `List Delphi versions to compile modules`,
+ Run: func(_ *cobra.Command, _ []string) {
+ paths := dcc32.GetDcc32DirByCmd()
+ if len(paths) == 0 {
+ msg.Warn("Installations not found in $PATH")
+ return
+ }
-var cmdDelphiList = &cobra.Command{
- Use: "list",
- Short: "List Delphi versions",
- Long: `List Delphi versions to compile modules`,
- Run: func(cmd *cobra.Command, args []string) {
- paths := dcc32.GetDcc32DirByCmd()
- if len(paths) == 0 {
- msg.Warn("Installations not found in $PATH")
- return
- } else {
msg.Warn("Installations found:")
for index, path := range paths {
msg.Info(" [%d] %s", index, path)
}
- }
- },
-}
+ },
+ }
-var cmdDelphiUse = &cobra.Command{
- Use: "use [path]",
- Short: "Use Delphi version",
- Long: `Use Delphi version to compile modules`,
- Args: func(cmd *cobra.Command, args []string) error {
- if err := cobra.ExactArgs(1)(cmd, args); err != nil {
- return err
- }
- if _, err := strconv.Atoi(args[0]); err != nil {
- if _, err = os.Stat(args[0]); os.IsNotExist(err) {
- return errors.New("invalid path")
+ use := &cobra.Command{
+ Use: "use [path]",
+ Short: "Use Delphi version",
+ Long: `Use Delphi version to compile modules`,
+ Args: func(cmd *cobra.Command, args []string) error {
+ if err := cobra.ExactArgs(1)(cmd, args); err != nil {
+ return err
+ }
+ if _, err := strconv.Atoi(args[0]); err != nil {
+ if _, err = os.Stat(args[0]); os.IsNotExist(err) {
+ return errors.New("invalid path")
+ }
+ }
+
+ return nil
+ },
+ Run: func(_ *cobra.Command, args []string) {
+ var path = args[0]
+ config := env.GlobalConfiguration()
+ if index, err := strconv.Atoi(path); err == nil {
+ delphiPaths := dcc32.GetDcc32DirByCmd()
+ config.DelphiPath = delphiPaths[index]
+ } else {
+ config.DelphiPath = args[0]
}
- }
- return nil
- },
- Run: func(cmd *cobra.Command, args []string) {
- var path = args[0]
- config := env.GlobalConfiguration
- if index, err := strconv.Atoi(path); err == nil {
- delphiPaths := dcc32.GetDcc32DirByCmd()
- config.DelphiPath = delphiPaths[index]
- } else {
- config.DelphiPath = args[0]
- }
+ config.SaveConfiguration()
+ msg.Info("Successful!")
+ },
+ }
- config.SaveConfiguration()
- msg.Info("Successful!")
- },
-}
+ root.AddCommand(delphiCmd)
-func init() {
- CmdConfig.AddCommand(cmdDelphi)
- cmdDelphi.AddCommand(cmdDelphiList)
- cmdDelphi.AddCommand(cmdDelphiUse)
+ delphiCmd.AddCommand(list)
+ delphiCmd.AddCommand(use)
}
diff --git a/cmd/config/git.go b/cmd/config/git.go
index 93ad822..18b2180 100644
--- a/cmd/config/git.go
+++ b/cmd/config/git.go
@@ -1,73 +1,54 @@
package config
import (
- "fmt"
"strings"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/msg"
"github.com/spf13/cobra"
)
-var gitCmd = &cobra.Command{
- Use: "git",
- Short: "Configure Git",
- Example: "boss config git mode",
- Run: func(cmd *cobra.Command, args []string) {
- _ = cmd.Help()
-
- },
-}
-
func boolToMode(embedded bool) string {
if embedded {
return "embedded"
- } else {
- return "native"
}
+
+ return "native"
}
-var gitModeCmd = &cobra.Command{
- Use: "mode [type]",
- Short: "Configure Git mode",
- ValidArgs: []string{"native", "embedded", "default"},
- SilenceErrors: true,
- Args: func(cmd *cobra.Command, args []string) error {
- err := cobra.OnlyValidArgs(cmd, args)
- if err == nil {
- err = cobra.ExactArgs(1)(cmd, args)
- }
- if err != nil {
- println(err.Error())
- println()
- println("Current: ", boolToMode(env.GlobalConfiguration.GitEmbedded))
- println()
- fmt.Printf("Valid args:\n\t%s\n", strings.Join(cmd.ValidArgs, "\n\t"))
- println()
- return err
- }
- return nil
- },
- Run: func(cmd *cobra.Command, args []string) {
- switch args[0] {
- case "native":
- {
- env.GlobalConfiguration.GitEmbedded = false
+func registryGitCmd(root *cobra.Command) {
+ gitCmd := &cobra.Command{
+ Use: "git",
+ Short: "Configure Git",
+ Example: "boss config git mode",
+ }
+ gitModeCmd := &cobra.Command{
+ Use: "mode [type]",
+ Short: "Configure Git mode",
+ ValidArgs: []string{"native", "embedded", "default"},
+ Args: func(cmd *cobra.Command, args []string) error {
+ err := cobra.OnlyValidArgs(cmd, args)
+ if err == nil {
+ err = cobra.ExactArgs(1)(cmd, args)
}
- case "embedded", "default":
- {
- env.GlobalConfiguration.GitEmbedded = true
+ if err != nil {
+ msg.Warn(err.Error())
+ msg.Info("Current: %s\n\nValid args:\n\t%s\n",
+ boolToMode(env.GlobalConfiguration().GitEmbedded),
+ strings.Join(cmd.ValidArgs, "\n\t"))
+ return err
}
+ return nil
+ },
+ Run: func(_ *cobra.Command, args []string) {
+ env.GlobalConfiguration().GitEmbedded = args[0] != "native"
+
+ msg.Info("Using %s git", boolToMode(env.GlobalConfiguration().GitEmbedded))
+ env.GlobalConfiguration().SaveConfiguration()
+ },
+ }
- }
- msg.Info("Using %s git", boolToMode(env.GlobalConfiguration.GitEmbedded))
- env.GlobalConfiguration.SaveConfiguration()
-
- },
-}
-
-func init() {
- CmdConfig.AddCommand(gitCmd)
+ root.AddCommand(gitCmd)
gitCmd.AddCommand(gitModeCmd)
}
diff --git a/cmd/config/purgeCache.go b/cmd/config/purgeCache.go
index 9245f4b..3f73254 100644
--- a/cmd/config/purgeCache.go
+++ b/cmd/config/purgeCache.go
@@ -1,40 +1,25 @@
package config
import (
- "fmt"
- "strings"
-
- "github.com/hashload/boss/core"
- "github.com/hashload/boss/utils"
+ "github.com/hashload/boss/pkg/gc"
"github.com/spf13/cobra"
)
-var purgeCacheCmd = &cobra.Command{
- Use: "cache",
- Short: "Configure cache",
- ValidArgs: []string{"rm"},
- SilenceErrors: true,
- Args: func(cmd *cobra.Command, args []string) error {
- err := cobra.OnlyValidArgs(cmd, args)
- if err == nil {
- err = cobra.ExactArgs(1)(cmd, args)
- }
- if err != nil {
- println(err.Error())
- println()
- fmt.Printf("Valid args:\n\t%s\n", strings.Join(cmd.ValidArgs, "\n\t"))
- println()
- return err
- }
- return nil
- },
- Run: func(cmd *cobra.Command, args []string) {
- if utils.Contains(args, "rm") {
- core.RunGC(true)
- }
- },
-}
+func RegisterCmd(cmd *cobra.Command) {
+ purgeCacheCmd := &cobra.Command{
+ Use: "cache",
+ Short: "Configure cache",
+ }
+
+ rmCacheCmd := &cobra.Command{
+ Use: "rm",
+ Short: "Remove cache",
+ RunE: func(_ *cobra.Command, _ []string) error {
+ return gc.RunGC(true)
+ },
+ }
+
+ purgeCacheCmd.AddCommand(rmCacheCmd)
-func init() {
- CmdConfig.AddCommand(purgeCacheCmd)
+ cmd.AddCommand(purgeCacheCmd)
}
diff --git a/cmd/dependencies.go b/cmd/dependencies.go
index ecc3b7e..c975fd1 100644
--- a/cmd/dependencies.go
+++ b/cmd/dependencies.go
@@ -4,32 +4,35 @@ import (
"os"
"path/filepath"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/core/installer"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/installer"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
"github.com/hashload/boss/utils"
"github.com/masterminds/semver"
"github.com/spf13/cobra"
"github.com/xlab/treeprint"
)
+type dependencyStatus int
+
const (
- updated = 0
- outdated = 1
- usingMaster = 2
+ updated dependencyStatus = iota
+ outdated
+ usingBranch
+ branchOutdated
)
-var showVersion bool
-var tree = treeprint.New()
+func dependenciesCmdRegister(root *cobra.Command) {
+ var showVersion bool
-var dependenciesCmd = &cobra.Command{
- Use: "dependencies",
- Short: "Print all project dependencies",
- Long: "Print all project dependencies with or without version control",
- Aliases: []string{"dep", "ls", "list", "ll", "la"},
- Example: ` Listing all dependencies:
+ var dependenciesCmd = &cobra.Command{
+ Use: "dependencies",
+ Short: "Print all project dependencies",
+ Long: "Print all project dependencies with or without version control",
+ Aliases: []string{"dep", "ls", "list", "ll", "la", "dependency"},
+ Example: ` Listing all dependencies:
boss dependencies
Listing all dependencies with version control:
@@ -40,17 +43,17 @@ var dependenciesCmd = &cobra.Command{
List package dependencies with version control:
boss dependencies --version`,
- Run: func(cmd *cobra.Command, args []string) {
- printDependencies(showVersion)
- },
-}
+ Run: func(_ *cobra.Command, _ []string) {
+ printDependencies(showVersion)
+ },
+ }
-func init() {
- RootCmd.AddCommand(dependenciesCmd)
+ root.AddCommand(dependenciesCmd)
dependenciesCmd.Flags().BoolVarP(&showVersion, "version", "v", false, "show dependency version")
}
func printDependencies(showVersion bool) {
+ var tree = treeprint.New()
pkg, err := models.LoadPackage(false)
if err != nil {
if os.IsNotExist(err) {
@@ -60,13 +63,17 @@ func printDependencies(showVersion bool) {
}
}
- master := tree.AddBranch(pkg.Name + ":")
+ main := tree.AddBranch(pkg.Name + ":")
deps := pkg.GetParsedDependencies()
- printDeps(nil, deps, pkg.Lock, master, showVersion)
- print(tree.String())
+ printDeps(nil, deps, pkg.Lock, main, showVersion)
+ msg.Info(tree.String())
}
-func printDeps(dep *models.Dependency, deps []models.Dependency, lock models.PackageLock, tree treeprint.Tree, showVersion bool) {
+func printDeps(dep *models.Dependency,
+ deps []models.Dependency,
+ lock models.PackageLock,
+ tree treeprint.Tree,
+ showVersion bool) {
var localTree treeprint.Tree
if dep != nil {
@@ -76,51 +83,62 @@ func printDeps(dep *models.Dependency, deps []models.Dependency, lock models.Pac
}
for _, dep := range deps {
- pkgModule, err := models.LoadPackageOther(filepath.Join(env.GetModulesDir(), dep.GetName(), consts.FilePackage))
+ pkgModule, err := models.LoadPackageOther(filepath.Join(env.GetModulesDir(), dep.Name(), consts.FilePackage))
if err != nil {
printSingleDependency(&dep, lock, localTree, showVersion)
} else {
- deps := pkgModule.GetParsedDependencies()
- printDeps(&dep, deps, lock, localTree, showVersion)
+ subDeps := pkgModule.GetParsedDependencies()
+ printDeps(&dep, subDeps, lock, localTree, showVersion)
}
}
}
-func printSingleDependency(dep *models.Dependency, lock models.PackageLock, tree treeprint.Tree, showVersion bool) treeprint.Tree {
- var output = dep.GetName()
+func printSingleDependency(
+ dep *models.Dependency,
+ lock models.PackageLock,
+ tree treeprint.Tree,
+ showVersion bool) treeprint.Tree {
+ var output = dep.Name()
if showVersion {
output += "@"
output += lock.GetInstalled(*dep).Version
}
- switch isOutdated(*dep, lock.GetInstalled(*dep).Version) {
+ status, version := isOutdated(*dep, lock.GetInstalled(*dep).Version)
+
+ switch status {
case outdated:
- output += " outdated"
- case usingMaster:
- output += " using master"
+ output += " <- outdated (" + version + ")"
+ case usingBranch:
+ output += " <- branch based"
+ case branchOutdated:
+ output += " <- branch outdated"
+ case updated:
+ output += ""
}
return tree.AddBranch(output)
}
-func isOutdated(dependency models.Dependency, version string) int {
+func isOutdated(dependency models.Dependency, version string) (dependencyStatus, string) {
installer.GetDependency(dependency)
- info, err := models.RepoData(dependency.GetHashName())
+ info, err := models.RepoData(dependency.HashName())
if err != nil {
utils.HandleError(err)
} else {
+ //TODO: Check if the branch is outdated by comparing the hash
locked, err := semver.NewVersion(version)
if err != nil {
- return usingMaster
+ return usingBranch, ""
}
constraint, _ := semver.NewConstraint(dependency.GetVersion())
for _, value := range info.Versions {
version, err := semver.NewVersion(value)
if err == nil && version.GreaterThan(locked) && constraint.Check(version) {
- return outdated
+ return outdated, version.String()
}
}
}
- return updated
+ return updated, ""
}
diff --git a/cmd/init.go b/cmd/init.go
index f829dd4..11a8c13 100644
--- a/cmd/init.go
+++ b/cmd/init.go
@@ -1,37 +1,37 @@
package cmd
import (
- "bufio"
- "fmt"
"os"
"path/filepath"
"regexp"
- "strings"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
+ "github.com/pterm/pterm"
"github.com/spf13/cobra"
)
-var quiet bool
+func initCmdRegister(root *cobra.Command) {
+ var quiet bool
-var initCmd = &cobra.Command{
- Use: "init",
- Short: "Initialize a new project",
- Long: "Initialize a new project and creates a boss.json file",
- Example: ` Initialize a new project:
+ var initCmd = &cobra.Command{
+ Use: "init",
+ Short: "Initialize a new project",
+ Long: "Initialize a new project and creates a boss.json file",
+ Example: ` Initialize a new project:
boss init
Initialize a new project without having it ask any questions:
boss init --quiet`,
- Run: func(cmd *cobra.Command, args []string) {
- doInitialization(quiet)
- },
-}
+ Run: func(_ *cobra.Command, _ []string) {
+ doInitialization(quiet)
+ },
+ }
-func init() {
- RootCmd.AddCommand(initCmd)
initCmd.Flags().BoolVarP(&quiet, "quiet", "q", false, "without asking questions")
+
+ root.AddCommand(initCmd)
}
func doInitialization(quiet bool) {
@@ -39,7 +39,10 @@ func doInitialization(quiet bool) {
printHead()
}
- pkgJson, _ := models.LoadPackage(true)
+ packageData, err := models.LoadPackage(true)
+ if err != nil && !os.IsNotExist(err) {
+ msg.Die("Fail on open dependencies file: %s", err)
+ }
rxp := regexp.MustCompile(`^.+\` + string(filepath.Separator) + `([^\\]+)$`)
@@ -47,39 +50,35 @@ func doInitialization(quiet bool) {
folderName := allString[0][1]
if quiet {
- pkgJson.Name = folderName
- pkgJson.Version = "1.0.0"
- pkgJson.MainSrc = "./src"
+ packageData.Name = folderName
+ packageData.Version = "1.0.0"
+ packageData.MainSrc = "./src"
} else {
- pkgJson.Name = getParamOrDef("Package name ("+folderName+")", folderName)
- pkgJson.Homepage = getParamOrDef("Homepage", "")
- pkgJson.Version = getParamOrDef("Version (1.0.0)", "1.0.0")
- pkgJson.Description = getParamOrDef("Description", "")
- pkgJson.MainSrc = getParamOrDef("Source folder (./src)", "./src")
+ packageData.Name = getParamOrDef("Package name ("+folderName+")", folderName)
+ packageData.Homepage = getParamOrDef("Homepage", "")
+ packageData.Version = getParamOrDef("Version (1.0.0)", "1.0.0")
+ packageData.Description = getParamOrDef("Description", "")
+ packageData.MainSrc = getParamOrDef("Source folder (./src)", "./src")
}
- json := pkgJson.Save()
- fmt.Println("\n" + string([]byte(json)))
+ json := packageData.Save()
+ msg.Info("\n" + string(json))
}
-func getParamOrDef(msg string, def string) string {
- fmt.Print(msg + ": ")
- rr := bufio.NewReader(os.Stdin)
- if res, e := rr.ReadString('\n'); e == nil && res != "\n" {
- res = strings.ReplaceAll(res, "\t", "")
- res = strings.ReplaceAll(res, "\n", "")
- res = strings.ReplaceAll(res, "\r", "")
- if res == "" {
- return def
- } else {
- return res
- }
+func getParamOrDef(msg string, def ...string) string {
+ input := &pterm.DefaultInteractiveTextInput
+
+ if len(def) > 0 {
+ input = input.WithDefaultValue(def[0])
}
- return def
+
+ result, _ := input.Show(msg)
+
+ return result
}
func printHead() {
- println(`
+ msg.Info(`
This utility will walk you through creating a boss.json file.
It only covers the most common items, and tries to guess sensible defaults.
diff --git a/cmd/install.go b/cmd/install.go
index 1508375..ea86ac0 100644
--- a/cmd/install.go
+++ b/cmd/install.go
@@ -1,18 +1,19 @@
package cmd
import (
- "github.com/hashload/boss/core"
+ "github.com/hashload/boss/pkg/installer"
"github.com/spf13/cobra"
)
-var noSaveInstall bool
+func installCmdRegister(root *cobra.Command) {
+ var noSaveInstall bool
-var installCmd = &cobra.Command{
- Use: "install",
- Short: "Install a new dependency",
- Long: `This command install a new dependency on your project`,
- Aliases: []string{"i", "add"},
- Example: ` Add a new dependency:
+ var installCmd = &cobra.Command{
+ Use: "install",
+ Short: "Install a new dependency",
+ Long: `This command install a new dependency on your project`,
+ Aliases: []string{"i", "add"},
+ Example: ` Add a new dependency:
boss install
Add a new version-specific dependency:
@@ -20,12 +21,11 @@ var installCmd = &cobra.Command{
Install a dependency without add it from the boss.json file:
boss install --no-save`,
- Run: func(cmd *cobra.Command, args []string) {
- core.InstallModules(args, true, noSaveInstall)
- },
-}
+ Run: func(_ *cobra.Command, args []string) {
+ installer.InstallModules(args, true, noSaveInstall)
+ },
+ }
-func init() {
- RootCmd.AddCommand(installCmd)
+ root.AddCommand(installCmd)
installCmd.Flags().BoolVar(&noSaveInstall, "no-save", false, "prevents saving to dependencies")
}
diff --git a/cmd/login.go b/cmd/login.go
index 1ddefc0..2bd1acc 100644
--- a/cmd/login.go
+++ b/cmd/login.go
@@ -1,47 +1,55 @@
package cmd
import (
- "fmt"
- "log"
"os/user"
"path/filepath"
- "syscall"
-
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/msg"
+
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/msg"
+ "github.com/pterm/pterm"
"github.com/spf13/cobra"
- "golang.org/x/term"
)
-var removeLogin bool
-var useSsh bool
-var privateKey string
-var userName string
-var password string
+func loginCmdRegister(root *cobra.Command) {
+ var removeLogin bool
+ var useSSH bool
+ var privateKey string
+ var userName string
+ var password string
-var loginCmd = &cobra.Command{
- Use: "login",
- Short: "Add a registry user account",
- Example: ` Adding a new user account:
+ var loginCmd = &cobra.Command{
+ Use: "login",
+ Short: "Add a registry user account",
+ Example: ` Adding a new user account:
boss login `,
- Aliases: []string{"adduser", "add-user"},
- Run: func(cmd *cobra.Command, args []string) {
- login(removeLogin, useSsh, privateKey, userName, password, args)
- },
-}
+ Aliases: []string{"adduser", "add-user"},
+ Run: func(_ *cobra.Command, args []string) {
+ login(removeLogin, useSSH, privateKey, userName, password, args)
+ },
+ }
+
+ var logoutCmd = &cobra.Command{
+ Use: "logout",
+ Short: "Remove a registry user account",
+ Example: ` Remove a new user account:
+ boss login `,
+ Run: func(_ *cobra.Command, args []string) {
+ login(removeLogin, false, "", "", "", args)
+ },
+ }
-func init() {
- // TODO add example to remove login or add a new command to logout (equals branch refact-steroids)
loginCmd.Flags().BoolVarP(&removeLogin, "rm", "r", false, "remove login")
- loginCmd.Flags().BoolVarP(&useSsh, "ssh", "s", false, "Use SSH")
+ loginCmd.Flags().BoolVarP(&useSSH, "ssh", "s", false, "Use SSH")
loginCmd.Flags().StringVarP(&privateKey, "key", "k", "", "Path of ssh private key")
loginCmd.Flags().StringVarP(&userName, "username", "u", "", "Username")
loginCmd.Flags().StringVarP(&password, "password", "p", "", "Password or PassPhrase(with SSH)")
- RootCmd.AddCommand(loginCmd)
+ root.AddCommand(loginCmd)
+
+ root.AddCommand(logoutCmd)
}
-func login(removeLogin bool, useSsh bool, privateKey string, userName string, password string, args []string) {
- configuration := env.GlobalConfiguration
+func login(removeLogin bool, useSSH bool, privateKey string, userName string, password string, args []string) {
+ configuration := env.GlobalConfiguration()
if removeLogin {
delete(configuration.Auth, args[0])
@@ -65,53 +73,58 @@ func login(removeLogin bool, useSsh bool, privateKey string, userName string, pa
if auth == nil {
auth = &env.Auth{}
}
-
+
if (userName != "") || (privateKey != "") {
- auth.UseSsh = useSsh
- if auth.UseSsh || (privateKey != "") {
- auth.UseSsh = true
- auth.Path = privateKey
- auth.SetPassPhrase(password)
- } else {
- auth.SetUser(userName)
- auth.SetPass(password)
- }
+ setAuthWithParams(auth, useSSH, privateKey, userName, password)
} else {
- auth.UseSsh = getParamBoolean("Use SSH")
-
- if auth.UseSsh {
- auth.Path = getParamOrDef("Path of ssh private key("+getSshKeyPath()+")", getSshKeyPath())
- auth.SetPassPhrase(getPass("PassPhrase"))
- } else {
- auth.SetUser(getParamOrDef("Username", ""))
- auth.SetPass(getPass("Password"))
- }
+ setAuthInteractively(auth)
}
configuration.Auth[repo] = auth
configuration.SaveConfiguration()
+}
+func setAuthWithParams(auth *env.Auth, useSSH bool, privateKey, userName, password string) {
+ auth.UseSSH = useSSH
+ if auth.UseSSH || (privateKey != "") {
+ auth.UseSSH = true
+ auth.Path = privateKey
+ auth.SetPassPhrase(password)
+ } else {
+ auth.SetUser(userName)
+ auth.SetPass(password)
+ }
}
-func getPass(description string) string {
- fmt.Print(description + ": ")
+func setAuthInteractively(auth *env.Auth) {
+ auth.UseSSH = getParamBoolean("Use SSH")
+
+ if auth.UseSSH {
+ auth.Path = getParamOrDef("Path of ssh private key("+getSSHKeyPath()+")", getSSHKeyPath())
+ auth.SetPassPhrase(getPass("PassPhrase"))
+ } else {
+ auth.SetUser(getParamOrDef("Username", ""))
+ auth.SetPass(getPass("Password"))
+ }
+}
- bytePassword, err := term.ReadPassword(int(syscall.Stdin))
+func getPass(description string) string {
+ pass, err := pterm.DefaultInteractiveTextInput.WithMask("•").Show(description)
if err != nil {
msg.Die("Error on get pass: %s", err)
}
- return string(bytePassword)
+ return pass
}
-func getSshKeyPath() string {
- usr, e := user.Current()
- if e != nil {
- log.Fatal(e)
+func getSSHKeyPath() string {
+ usr, err := user.Current()
+ if err != nil {
+ msg.Die(err.Error())
}
return filepath.Join(usr.HomeDir, ".ssh", "id_rsa")
}
-func getParamBoolean(msgS string) bool {
- msg.Print(msgS + "(y or n): ")
- return msg.PromptUntilYorN()
+func getParamBoolean(msg string) bool {
+ result, _ := pterm.DefaultInteractiveConfirm.Show(msg)
+ return result
}
diff --git a/cmd/root.go b/cmd/root.go
index 8d398a1..a97240f 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -4,45 +4,66 @@ import (
"os"
"github.com/hashload/boss/cmd/config"
- "github.com/hashload/boss/core"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/gc"
+ "github.com/hashload/boss/pkg/msg"
"github.com/hashload/boss/setup"
- "github.com/hashload/boss/utils"
"github.com/spf13/cobra"
)
-var versionPrint bool
-
-var RootCmd = &cobra.Command{
- Use: "boss",
- Short: "Dependency Manager for Delphi",
- Long: "Dependency Manager for Delphi",
- RunE: func(cmd *cobra.Command, args []string) error {
- if versionPrint {
- printVersion(false)
- } else {
- return cmd.Help()
- }
- return nil
- },
-}
+func Execute() error {
+ var versionPrint bool
+ var global bool
+ var debug bool
+
+ var root = &cobra.Command{
+ Use: "boss",
+ Short: "Dependency Manager for Delphi",
+ Long: "Dependency Manager for Delphi",
+ PersistentPreRun: func(_ *cobra.Command, _ []string) {
+ if debug {
+ msg.LogLevel(msg.DEBUG)
+ msg.Debug("Debug mode enabled")
+ }
-func Execute() {
- RootCmd.PersistentFlags().BoolVarP(&env.Global, "global", "g", false, "global environment")
- RootCmd.PersistentFlags().BoolVarP(&msg.DebugEnable, "debug", "d", false, "debug")
- RootCmd.Flags().BoolVarP(&versionPrint, "version", "v", false, "show cli version")
+ env.SetGlobal(global)
+ },
+ RunE: func(cmd *cobra.Command, _ []string) error {
+ if versionPrint {
+ printVersion()
+ } else {
+ return cmd.Help()
+ }
+ return nil
+ },
+ }
- msg.DebugEnable = utils.Contains(os.Args, "-d")
+ root.PersistentFlags().BoolVarP(&global, "global", "g", false, "global environment")
+ root.PersistentFlags().BoolVarP(&debug, "debug", "d", false, "debug")
+ root.Flags().BoolVarP(&versionPrint, "version", "v", false, "show cli version")
setup.Initialize()
- config.InitializeConfig(RootCmd)
+ config.RegisterConfigCommand(root)
+ initCmdRegister(root)
+ installCmdRegister(root)
+ loginCmdRegister(root)
+ runCmdRegister(root)
+ uninstallCmdRegister(root)
+ updateCmdRegister(root)
+ upgradeCmdRegister(root)
+ dependenciesCmdRegister(root)
+ versionCmdRegister(root)
- core.RunGC(false)
+ if err := gc.RunGC(false); err != nil {
+ return err
+ }
- if err := RootCmd.Execute(); err != nil {
+ config.RegisterCmd(root)
+ if err := root.Execute(); err != nil {
os.Exit(1)
}
+
+ return nil
}
diff --git a/cmd/run.go b/cmd/run.go
index 950c375..e7f1ed2 100644
--- a/cmd/run.go
+++ b/cmd/run.go
@@ -1,19 +1,19 @@
package cmd
import (
- "github.com/hashload/boss/core/scripts"
+ "github.com/hashload/boss/pkg/scripts"
"github.com/spf13/cobra"
)
-var runScript = &cobra.Command{
- Use: "run",
- Short: "Run cmd script",
- Long: `Run cmd script`,
- Run: func(cmd *cobra.Command, args []string) {
- scripts.Run(args)
- },
-}
+func runCmdRegister(root *cobra.Command) {
+ var runScript = &cobra.Command{
+ Use: "run",
+ Short: "Run cmd script",
+ Long: `Run cmd script`,
+ Run: func(_ *cobra.Command, args []string) {
+ scripts.Run(args)
+ },
+ }
-func init() {
- RootCmd.AddCommand(runScript)
+ root.AddCommand(runScript)
}
diff --git a/cmd/uninstall.go b/cmd/uninstall.go
index 3f3c1ef..356a4df 100644
--- a/cmd/uninstall.go
+++ b/cmd/uninstall.go
@@ -1,28 +1,33 @@
package cmd
import (
- "github.com/hashload/boss/core"
+ "github.com/hashload/boss/pkg/installer"
"github.com/spf13/cobra"
)
-var noSaveUninstall bool
+func uninstallCmdRegister(root *cobra.Command) {
+ var noSaveUninstall bool
-var uninstallCmd = &cobra.Command{
- Use: "uninstall",
- Short: "Uninstall a dependency",
- Long: "This uninstalls a package, completely removing everything boss installed on its behalf",
- Aliases: []string{"remove", "rm", "r", "un", "unlink"},
- Example: ` Uninstall a package:
+ var uninstallCmd = &cobra.Command{
+ Use: "uninstall",
+ Short: "Uninstall a dependency",
+ Long: "This uninstalls a package, completely removing everything boss installed on its behalf",
+ Aliases: []string{"remove", "rm", "r", "un", "unlink"},
+ Example: ` Uninstall a package:
boss uninstall
Uninstall a package without removing it from the boss.json file:
boss uninstall --no-save`,
- Run: func(cmd *cobra.Command, args []string) {
- core.UninstallModules(args, noSaveUninstall)
- },
-}
+ Run: func(_ *cobra.Command, args []string) {
+ installer.UninstallModules(args, noSaveUninstall)
+ },
+ }
-func init() {
- RootCmd.AddCommand(uninstallCmd)
- uninstallCmd.Flags().BoolVar(&noSaveUninstall, "no-save", false, "package will not be removed from your boss.json file")
+ root.AddCommand(uninstallCmd)
+ uninstallCmd.Flags().BoolVar(
+ &noSaveUninstall,
+ "no-save",
+ false,
+ "package will not be removed from your boss.json file",
+ )
}
diff --git a/cmd/update.go b/cmd/update.go
index 1eea093..e00f3d9 100644
--- a/cmd/update.go
+++ b/cmd/update.go
@@ -1,20 +1,20 @@
package cmd
import (
- "github.com/hashload/boss/core"
+ "github.com/hashload/boss/pkg/installer"
"github.com/spf13/cobra"
)
-var updateCmd = &cobra.Command{
- Use: "update",
- Short: "Update dependencies",
- Long: `This command update installed dependencies`,
- Aliases: []string{"up"},
- Run: func(cmd *cobra.Command, args []string) {
- core.InstallModules(args, false, false)
- },
-}
+func updateCmdRegister(root *cobra.Command) {
+ var updateCmd = &cobra.Command{
+ Use: "update",
+ Short: "Update dependencies",
+ Long: `This command update installed dependencies`,
+ Aliases: []string{"up"},
+ Run: func(_ *cobra.Command, args []string) {
+ installer.InstallModules(args, false, false)
+ },
+ }
-func init() {
- RootCmd.AddCommand(updateCmd)
+ root.AddCommand(updateCmd)
}
diff --git a/cmd/upgrade.go b/cmd/upgrade.go
index 6cca4a1..30a542f 100644
--- a/cmd/upgrade.go
+++ b/cmd/upgrade.go
@@ -5,22 +5,22 @@ import (
"github.com/spf13/cobra"
)
-var preRelease bool
+func upgradeCmdRegister(root *cobra.Command) {
+ var preRelease bool
-var upgradeCmd = &cobra.Command{
- Use: "upgrade",
- Short: "Upgrade the client version",
- Example: ` Upgrade boss:
+ var upgradeCmd = &cobra.Command{
+ Use: "upgrade",
+ Short: "Upgrade the client version",
+ Example: ` Upgrade boss:
boss upgrade
Upgrade boss with pre-release:
boss upgrade --dev`,
- RunE: func(cmd *cobra.Command, args []string) error {
- return upgrade.BossUpgrade(preRelease)
- },
-}
+ RunE: func(_ *cobra.Command, _ []string) error {
+ return upgrade.BossUpgrade(preRelease)
+ },
+ }
-func init() {
- RootCmd.AddCommand(upgradeCmd)
+ root.AddCommand(upgradeCmd)
upgradeCmd.Flags().BoolVar(&preRelease, "dev", false, "pre-release")
}
diff --git a/cmd/version.go b/cmd/version.go
index b49b5c7..2acc0e4 100644
--- a/cmd/version.go
+++ b/cmd/version.go
@@ -1,39 +1,31 @@
package cmd
import (
- "encoding/json"
- "fmt"
-
"github.com/hashload/boss/internal/version"
+ "github.com/hashload/boss/pkg/msg"
"github.com/spf13/cobra"
)
-var versionCmd = &cobra.Command{
- Use: "version",
- Short: "Show cli version",
- Long: `This command show the client version`,
- Aliases: []string{"v"},
- Example: ` Print version:
+func versionCmdRegister(root *cobra.Command) {
+ var versionCmd = &cobra.Command{
+ Use: "version",
+ Short: "Show cli version",
+ Long: `This command show the client version`,
+ Aliases: []string{"v"},
+ Example: ` Print version:
boss version`,
- Run: func(cmd *cobra.Command, args []string) {
- printVersion(true)
- },
-}
+ Run: func(_ *cobra.Command, _ []string) {
+ printVersion()
+ },
+ }
-func init() {
- RootCmd.AddCommand(versionCmd)
+ root.AddCommand(versionCmd)
}
-func printVersion(withDetails bool) {
+func printVersion() {
v := version.Get()
- if withDetails {
- jsonVersion, err := json.MarshalIndent(v, "", " ")
- if err != nil {
- fmt.Println(err)
- } else {
- fmt.Println(string(jsonVersion))
- }
- } else {
- fmt.Println(v.Version)
- }
+
+ msg.Info("Boss CLI Version: %s", v.Version)
+ msg.Info("Go Version: %s", v.GoVersion)
+ msg.Info("Git Commit: %s", v.GitCommit)
}
diff --git a/consts/consts.go b/consts/consts.go
deleted file mode 100644
index ae3c8d8..0000000
--- a/consts/consts.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package consts
-
-import "path/filepath"
-
-const FilePackage = "boss.json"
-const FilePackageLock = "boss-lock.json"
-const FileBplOrder = "bpl_order.txt"
-const FileExtensionBpl = ".bpl"
-const FileExtensionDcp = ".dcp"
-const FileExtensionDpk = ".dpk"
-
-const FilePackageLockOld = "boss.lock"
-const FolderDependencies = "modules"
-
-const FolderEnv = "env"
-
-var FolderEnvBpl = filepath.Join(FolderEnv, "bpl")
-var FolderEnvDcp = filepath.Join(FolderEnv, "dcp")
-var FolderEnvDcu = filepath.Join(FolderEnv, "dcu")
-
-const FolderBossHome = ".boss"
-
-const BinFolder string = ".bin"
-const BplFolder string = ".bpl"
-const DcpFolder string = ".dcp"
-const DcuFolder string = ".dcu"
-
-const BossConfigFile = "boss.cfg.json"
-
-const MinimalDependencyVersion string = ">0.0.0"
-
-const EnvBossBin = "." + string(filepath.Separator) + FolderDependencies + string(filepath.Separator) + BinFolder
-
-const XmlTagNameProperty string = "PropertyGroup"
-const XmlValueAttribute = "value"
-const XmlTagNamePropertyAttribute string = "Condition"
-const XmlTagNamePropertyAttributeValue string = "'$(Base)'!=''"
-
-const XmlTagNameLibraryPath string = "DCC_UnitSearchPath"
-
-const XmlTagNameCompilerOptions string = "CompilerOptions"
-const XmlTagNameSearchPaths string = "SearchPaths"
-const XmlTagNameOtherUnitFiles string = "OtherUnitFiles"
-const XmlTagNameProjectOptions string = "ProjectOptions"
-const XmlTagNameBuildModes string = "BuildModes"
-const XmlTagNameItem string = "Item"
-const XmlNameAttribute = "Name"
-
-const BossInternalDir = "internal."
-const BossInternalDirOld = "{internal}"
-
-const BplIdentifierName = "BplIdentifier.exe"
-
-const RegexArtifacts = "(.*.inc$|.*.pas$|.*.dfm$|.*.fmx$|.*.dcu$|.*.bpl$|.*.dcp$|.*.res$)"
-
-const RegistryBasePath = `Software\Embarcadero\BDS\`
-
-var DefaultPaths = []string{BplFolder, DcuFolder, DcpFolder, BinFolder}
diff --git a/core/compiler/artifacts.go b/core/compiler/artifacts.go
deleted file mode 100644
index 8f25fac..0000000
--- a/core/compiler/artifacts.go
+++ /dev/null
@@ -1,84 +0,0 @@
-package compiler
-
-import (
- "io/ioutil"
- "os"
- "path/filepath"
-
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/utils"
-)
-
-func moveArtifacts(dep models.Dependency, rootPath string) {
- var moduleName = dep.GetName()
- movePath(filepath.Join(rootPath, moduleName, consts.BplFolder), filepath.Join(rootPath, consts.BplFolder))
- movePath(filepath.Join(rootPath, moduleName, consts.DcpFolder), filepath.Join(rootPath, consts.DcpFolder))
- movePath(filepath.Join(rootPath, moduleName, consts.BinFolder), filepath.Join(rootPath, consts.BinFolder))
- movePath(filepath.Join(rootPath, moduleName, consts.DcuFolder), filepath.Join(rootPath, consts.DcuFolder))
-}
-
-func movePath(old string, new string) {
- files, err := ioutil.ReadDir(old)
- var hasError = false
- if err == nil {
- for _, file := range files {
- if !file.IsDir() {
- err = os.Rename(filepath.Join(old, file.Name()), filepath.Join(new, file.Name()))
- if err != nil {
- hasError = true
- }
- utils.HandleError(err)
- }
- }
- }
- if !hasError {
- err = os.RemoveAll(old)
- if !os.IsNotExist(err) {
- utils.HandleError(err)
- }
- }
-
-}
-
-func ensureArtifacts(lockedDependency *models.LockedDependency, dep models.Dependency, rootPath string) {
-
- var moduleName = dep.GetName()
- lockedDependency.Artifacts.Clean()
-
- files, err := ioutil.ReadDir(filepath.Join(rootPath, moduleName, consts.BplFolder))
- if err == nil {
- for _, file := range files {
- if !file.IsDir() {
- lockedDependency.Artifacts.Bpl = append(lockedDependency.Artifacts.Bpl, file.Name())
- }
- }
- }
-
- files, err = ioutil.ReadDir(filepath.Join(rootPath, moduleName, consts.DcuFolder))
- if err == nil {
- for _, file := range files {
- if !file.IsDir() {
- lockedDependency.Artifacts.Dcu = append(lockedDependency.Artifacts.Dcu, file.Name())
- }
- }
- }
-
- files, err = ioutil.ReadDir(filepath.Join(rootPath, moduleName, consts.BinFolder))
- if err == nil {
- for _, file := range files {
- if !file.IsDir() {
- lockedDependency.Artifacts.Bin = append(lockedDependency.Artifacts.Bin, file.Name())
- }
- }
- }
-
- files, err = ioutil.ReadDir(filepath.Join(rootPath, moduleName, consts.DcpFolder))
- if err == nil {
- for _, file := range files {
- if !file.IsDir() {
- lockedDependency.Artifacts.Dcp = append(lockedDependency.Artifacts.Dcp, file.Name())
- }
- }
- }
-}
diff --git a/core/garbage_collector.go b/core/garbage_collector.go
deleted file mode 100644
index 2f53828..0000000
--- a/core/garbage_collector.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package core
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "strings"
- "time"
-
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
-)
-
-func RunGC(ignoreLastUpdate bool) {
- _ = filepath.Walk(filepath.Join(env.GetCacheDir(), "info"), func(path string, info os.FileInfo, err error) error {
- if info == nil || info.IsDir() {
- return nil
- }
-
- var extension = filepath.Ext(info.Name())
- base := filepath.Base(info.Name())
- var name = strings.TrimRight(base, extension)
- repoInfo, e := models.RepoData(name)
- if e != nil {
- msg.Warn("Fail to parse repo info in GC: ", e)
- return nil
- }
-
- lastUpdate := repoInfo.LastUpdate.AddDate(0, 0, env.GlobalConfiguration.PurgeTime)
- if lastUpdate.Before(time.Now()) || ignoreLastUpdate {
- _ = os.RemoveAll(filepath.Join(env.GetCacheDir(), repoInfo.Key))
- _ = os.RemoveAll(filepath.Join(env.GetCacheDir(), fmt.Sprintf("%s_wt", repoInfo.Key)))
- _ = os.RemoveAll(filepath.Join(env.GetCacheDir(), "info", info.Name()))
- }
-
- return nil
- })
- env.GlobalConfiguration.LastPurge = time.Now()
- env.GlobalConfiguration.SaveConfiguration()
-}
diff --git a/core/gitWrapper/git.go b/core/gitWrapper/git.go
deleted file mode 100644
index 3f35b89..0000000
--- a/core/gitWrapper/git.go
+++ /dev/null
@@ -1,108 +0,0 @@
-package gitWrapper
-
-import (
- "path/filepath"
-
- "github.com/go-git/go-billy/v5/osfs"
- "github.com/go-git/go-git/v5"
- "github.com/go-git/go-git/v5/config"
- "github.com/go-git/go-git/v5/plumbing"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
-)
-
-func CloneCache(dep models.Dependency) *git.Repository {
- if env.GlobalConfiguration.GitEmbedded {
- return CloneCacheEmbedded(dep)
- } else {
- return CloneCacheNative(dep)
- }
-}
-
-func UpdateCache(dep models.Dependency) *git.Repository {
- if env.GlobalConfiguration.GitEmbedded {
- return UpdateCacheEmbedded(dep)
- } else {
- return UpdateCacheNative(dep)
- }
-}
-
-func initSubmodules(dep models.Dependency, repository *git.Repository) {
- worktree, err := repository.Worktree()
- if err != nil {
- msg.Err("... %s", err)
- }
- submodules, err := worktree.Submodules()
- if err != nil {
- msg.Err("On get submodules... %s", err)
- }
-
- err = submodules.Update(&git.SubmoduleUpdateOptions{
- Init: true,
- RecurseSubmodules: git.DefaultSubmoduleRecursionDepth,
- Auth: env.GlobalConfiguration.GetAuth(dep.GetURLPrefix()),
- })
- if err != nil {
- msg.Err("Failed on update submodules from dependency %s: %s", dep.Repository, err.Error())
- }
-
-}
-
-func GetMaster(repository *git.Repository) (*config.Branch, error) {
- branch, err := repository.Branch("master")
- if err != nil {
- branch, err = repository.Branch("main")
- }
- return branch, err
-}
-
-func GetVersions(repository *git.Repository) []*plumbing.Reference {
- tags, err := repository.Tags()
- if err != nil {
- msg.Err("Fail to retrieve versions: %", err)
- }
- var result = make([]*plumbing.Reference, 0)
- for {
- reference, err := tags.Next()
- if err != nil {
- return result
- }
- result = append(result, reference)
- }
-}
-
-func GetTagsShortName(repository *git.Repository) []string {
- tags, _ := repository.Tags()
- var result = []string{}
- _ = tags.ForEach(func(reference *plumbing.Reference) error {
- result = append(result, reference.Name().Short())
- return nil
- })
- return result
-}
-
-func GetByTag(repository *git.Repository, shortName string) *plumbing.Reference {
- tags, _ := repository.Tags()
-
- for {
- if reference, err := tags.Next(); err == nil {
- if reference.Name().Short() == shortName {
- return reference
- }
- } else {
- return nil
- }
- }
-}
-
-func GetRepository(dep models.Dependency) *git.Repository {
- cache := makeStorageCache(dep)
- dir := osfs.New(filepath.Join(env.GetModulesDir(), dep.GetName()))
- repository, e := git.Open(cache, dir)
- if e != nil {
- msg.Err("Error on open repository %s: %s", dep.Repository, e)
- }
-
- return repository
-}
diff --git a/core/installer.go b/core/installer.go
deleted file mode 100644
index de3b151..0000000
--- a/core/installer.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package core
-
-import (
- "os"
-
- "github.com/hashload/boss/core/installer"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
-)
-
-func InstallModules(args []string, lockedVersion bool, noSave bool) {
- _ = lockedVersion
- pkg, e := models.LoadPackage(env.Global)
- if e != nil {
- if os.IsNotExist(e) {
- msg.Die("boss.json not exists in " + env.GetCurrentDir())
- } else {
- msg.Die("Fail on open dependencies file: %s", e)
- }
- }
-
- if env.Global {
- installer.GlobalInstall(args, pkg, lockedVersion, noSave)
- } else {
- installer.LocalInstall(args, pkg, lockedVersion, noSave)
- }
-}
-
-func UninstallModules(args []string, noSave bool) {
- pkg, e := models.LoadPackage(false)
-
- if e != nil {
- msg.Err(e.Error())
- }
-
- if pkg == nil {
- return
- }
-
- for e := range args {
- dependencyRepository := installer.ParseDependency(args[e])
- pkg.UninstallDependency(dependencyRepository)
- }
-
- pkg.Save()
-
- // TODO noSave
- // TODO implement remove without reinstall process
-
- InstallModules([]string{}, false, false)
-}
diff --git a/core/installer/core.go b/core/installer/core.go
deleted file mode 100644
index 7733b7d..0000000
--- a/core/installer/core.go
+++ /dev/null
@@ -1,210 +0,0 @@
-package installer
-
-import (
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
-
- "github.com/go-git/go-git/v5"
- "github.com/go-git/go-git/v5/plumbing"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/core/compiler"
- "github.com/hashload/boss/core/gitWrapper"
- "github.com/hashload/boss/core/paths"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
- "github.com/hashload/boss/utils"
- "github.com/hashload/boss/utils/librarypath"
- "github.com/masterminds/semver"
-)
-
-var processed = []string{consts.BplFolder, consts.BinFolder, consts.DcpFolder, consts.DcuFolder}
-
-func DoInstall(pkg *models.Package, lockedVersion bool) {
- msg.Info("Installing modules in project path")
-
- dependencies := EnsureDependencies(pkg.Lock, pkg, lockedVersion)
- paths.EnsureCleanModulesDir(dependencies, pkg.Lock)
-
- pkg.Lock.CleanRemoved(dependencies)
- pkg.Save()
-
- librarypath.UpdateLibraryPath(pkg)
- msg.Info("Compiling units")
- compiler.Build(pkg)
- pkg.Save()
- msg.Info("Success!")
-}
-
-func EnsureDependencies(rootLock models.PackageLock, pkg *models.Package, lockedVersion bool) []models.Dependency {
- if pkg.Dependencies == nil {
- return []models.Dependency{}
- }
- deps := pkg.GetParsedDependencies()
-
- //makeCache(deps)
-
- ensureModules(rootLock, pkg, deps, lockedVersion)
-
- deps = append(deps, processOthers(rootLock, lockedVersion)...)
-
- return deps
-}
-
-func processOthers(rootLock models.PackageLock, lockedVersion bool) []models.Dependency {
- infos, e := ioutil.ReadDir(env.GetModulesDir())
- var lenProcessedInitial = len(processed)
- var result []models.Dependency
- if e != nil {
- msg.Err("Error on try load dir of modules: %s", e)
- }
-
- for _, info := range infos {
- if !info.IsDir() {
- continue
- }
-
- if utils.Contains(processed, info.Name()) {
- continue
- } else {
- processed = append(processed, info.Name())
- }
- msg.Info("Processing module %s", info.Name())
-
- fileName := filepath.Join(env.GetModulesDir(), info.Name(), consts.FilePackage)
-
- _, i := os.Stat(fileName)
- if os.IsNotExist(i) {
- msg.Warn(" boss.json not exists in %s", info.Name())
- }
-
- if packageOther, e := models.LoadPackageOther(fileName); e != nil {
- if os.IsNotExist(e) {
- continue
- }
- msg.Err(" Error on try load package %s: %s", fileName, e)
- } else {
- result = append(result, EnsureDependencies(rootLock, packageOther, lockedVersion)...)
- }
- }
- if lenProcessedInitial > len(processed) {
- result = append(result, processOthers(rootLock, lockedVersion)...)
- }
-
- return result
-}
-
-func ensureModules(rootLock models.PackageLock, pkg *models.Package, deps []models.Dependency, lockedVersion bool) {
- msg.Info("Installing modules")
- for _, dep := range deps {
- msg.Info("Processing dependency %s", dep.GetName())
-
- installed, exists := rootLock.Installed[strings.ToLower(dep.GetURL())]
-
- if lockedVersion && exists {
- depv := strings.Replace(strings.Replace(dep.GetVersion(), "^", "", -1), "~", "", -1)
- requiredVersion, err := semver.NewVersion(depv)
-
- if err != nil {
- msg.Warn(" Error '%s' on get required version. Updating...", err)
-
- } else {
- installedVersion, err := semver.NewVersion(installed.Version)
-
- if err != nil {
- msg.Warn(" Error '%s' on get installed version. Updating...", err)
- } else {
- if !installedVersion.LessThan(requiredVersion) {
- msg.Info("Dependency %s already installed", dep.GetName())
- continue
- } else {
- msg.Info("Dependency %s needs to update", dep.GetName())
- }
- }
- }
-
- }
- //git fetch only when necessary
- GetDependency(dep)
-
- repository := gitWrapper.GetRepository(dep)
- hasMatch, bestMatch := getVersion(rootLock, dep, repository, false)
-
- var referenceName plumbing.ReferenceName
-
- worktree, _ := repository.Worktree()
-
- if !hasMatch {
- if masterReference, err := gitWrapper.GetMaster(repository); err == nil {
- referenceName = plumbing.NewBranchReferenceName(masterReference.Name)
- }
- } else {
- referenceName = bestMatch.Name()
- if dep.GetVersion() == consts.MinimalDependencyVersion {
- pkg.Dependencies.(map[string]interface{})[dep.Repository] = "^" + referenceName.Short()
- }
- }
-
- switch {
- case !rootLock.NeedUpdate(dep, referenceName.Short()):
- msg.Info(" %s already updated", dep.GetName())
- continue
- case !hasMatch:
- msg.Warn(" No candidate to version for %s. Using master branch", dep.GetVersion())
- default:
- msg.Info(" Detected semantic version. Using version %s", bestMatch.Name().Short())
- }
-
- err := worktree.Checkout(&git.CheckoutOptions{
- Force: true,
- Branch: referenceName,
- })
-
- rootLock.AddInstalled(dep, referenceName.Short())
-
- if err != nil {
- msg.Die(" Error on switch to needed version from dependency %s\n%s", dep.Repository, err)
- }
- }
-}
-
-func getVersion(rootLock models.PackageLock, dep models.Dependency, repository *git.Repository, lockedVersion bool) (bool, *plumbing.Reference) {
- versions := gitWrapper.GetVersions(repository)
- constraints, e := semver.NewConstraint(dep.GetVersion())
- if e != nil {
- msg.Err(" Version type not supported! %s", e)
- }
- var bestVersion *semver.Version
- hasMatch := false
- var bestMatch *plumbing.Reference = nil
- if !lockedVersion {
-
- for _, version := range versions {
- short := version.Name().Short()
- newVersion, err := semver.NewVersion(short)
- if err != nil {
- continue
- }
- if constraints.Check(newVersion) {
- hasMatch = true
- if bestVersion == nil || newVersion.GreaterThan(bestVersion) {
- bestMatch = version
- bestVersion = newVersion
- }
- }
- }
- } else {
- lockedDependency := rootLock.GetInstalled(dep)
- if tag := gitWrapper.GetByTag(repository, lockedDependency.Version); tag != nil {
- return true, tag
- } else {
- msg.Warn("Tag not found %s, using semantic now...", lockedDependency.Version)
- return getVersion(rootLock, dep, repository, false)
- }
-
- }
-
- return hasMatch, bestMatch
-}
diff --git a/core/installer/vsc.go b/core/installer/vsc.go
deleted file mode 100644
index cd87ac0..0000000
--- a/core/installer/vsc.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package installer
-
-import (
- "os"
- "path/filepath"
-
- "github.com/go-git/go-git/v5"
- "github.com/hashload/boss/core/gitWrapper"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
- "github.com/hashload/boss/utils"
-)
-
-var updatedDependencies []string
-
-func GetDependency(dep models.Dependency) {
- if utils.Contains(updatedDependencies, dep.GetHashName()) {
- msg.Debug("Using cached of %s", dep.GetName())
- return
- } else {
- msg.Info("Updating cache of dependency %s", dep.GetName())
- }
-
- updatedDependencies = append(updatedDependencies, dep.GetHashName())
- var repository *git.Repository
- if hasCache(dep) {
- repository = gitWrapper.UpdateCache(dep)
- } else {
- _ = os.RemoveAll(filepath.Join(env.GetCacheDir(), dep.GetHashName()))
- repository = gitWrapper.CloneCache(dep)
- }
- tagsShortNames := gitWrapper.GetTagsShortName(repository)
- models.SaveRepoData(dep.GetHashName(), tagsShortNames)
-}
-
-func hasCache(dep models.Dependency) bool {
- dir := filepath.Join(env.GetCacheDir(), dep.GetHashName())
- info, err := os.Stat(dir)
- if err == nil {
- return true
- }
- if os.IsNotExist(err) {
- return false
- }
- if !info.IsDir() {
- _ = os.RemoveAll(dir)
- return false
- }
- _, err = os.Stat(dir)
- return !os.IsNotExist(err)
-
-}
diff --git a/core/paths/paths.go b/core/paths/paths.go
deleted file mode 100644
index 9eaf589..0000000
--- a/core/paths/paths.go
+++ /dev/null
@@ -1,96 +0,0 @@
-package paths
-
-import (
- "io/ioutil"
- "os"
- "path/filepath"
-
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
- "github.com/hashload/boss/utils"
-)
-
-func EnsureCleanModulesDir(dependencies []models.Dependency, lock models.PackageLock) {
- cacheDir := env.GetModulesDir()
- cacheDirInfo, err := os.Stat(cacheDir)
- switch {
- case os.IsNotExist(err):
- if err := os.MkdirAll(cacheDir, os.ModeDir|0755); err != nil {
- msg.Die("Could not create %s: %s", cacheDir, err)
- }
-
- case cacheDirInfo != nil && !cacheDirInfo.IsDir():
- msg.Die("modules is not a directory")
- default:
- fileInfos, err := ioutil.ReadDir(cacheDir)
- utils.HandleError(err)
- dependenciesNames := models.GetDependenciesNames(dependencies)
- for _, info := range fileInfos {
- if !info.IsDir() {
- err := os.Remove(info.Name())
- utils.HandleError(err)
- }
- if utils.Contains(consts.DefaultPaths, info.Name()) {
- cleanArtifacts(filepath.Join(cacheDir, info.Name()), lock)
- continue
- }
-
- if !utils.Contains(dependenciesNames, info.Name()) {
- remove:
- if err = os.RemoveAll(filepath.Join(cacheDir, info.Name())); err != nil {
- msg.Warn("Failed to remove old cache: %s", err.Error())
- goto remove
- }
- }
-
- }
- }
- createPath(filepath.Join(cacheDir, consts.BplFolder))
- createPath(filepath.Join(cacheDir, consts.DcuFolder))
- createPath(filepath.Join(cacheDir, consts.DcpFolder))
- createPath(filepath.Join(cacheDir, consts.BinFolder))
-}
-
-func EnsureCacheDir(dep models.Dependency) {
- if !env.GlobalConfiguration.GitEmbedded {
- return
- }
- cacheDir := filepath.Join(env.GetCacheDir(), dep.GetHashName())
-
- fi, err := os.Stat(cacheDir)
- if err != nil {
- msg.Debug("Creating %s", cacheDir)
- if err := os.MkdirAll(cacheDir, os.ModeDir|0755); err != nil {
- msg.Die("Could not create %s: %s", cacheDir, err)
- }
- } else if !fi.IsDir() {
- msg.Die("cache is not a directory")
- }
-}
-
-func createPath(path string) {
- utils.HandleError(os.MkdirAll(path, os.ModeDir|0755))
-}
-
-func cleanArtifacts(dir string, lock models.PackageLock) {
- fileInfos, err := ioutil.ReadDir(dir)
- utils.HandleError(err)
- artifactList := lock.GetArtifactList()
- for _, infoArtifact := range fileInfos {
- if infoArtifact.IsDir() {
- continue
- }
- if !utils.Contains(artifactList, infoArtifact.Name()) {
- for {
- err := os.Remove(filepath.Join(dir, infoArtifact.Name()))
- utils.HandleError(err)
- if err == nil {
- break
- }
- }
- }
-
- }
-}
diff --git a/go.mod b/go.mod
index 428d5e2..bada161 100644
--- a/go.mod
+++ b/go.mod
@@ -1,45 +1,236 @@
module github.com/hashload/boss
-go 1.17
+go 1.24.0
+
+toolchain go1.24.1
+
+tool github.com/golangci/golangci-lint/cmd/golangci-lint
require (
- github.com/beevik/etree v1.1.0
+ github.com/beevik/etree v1.5.0
github.com/denisbrodbeck/machineid v1.0.1
- github.com/go-git/go-billy/v5 v5.3.1
- github.com/go-git/go-git/v5 v5.4.2
- github.com/google/go-github/v45 v45.1.0
+ github.com/go-git/go-billy/v5 v5.6.2
+ github.com/go-git/go-git/v5 v5.14.0
+ github.com/google/go-github/v69 v69.2.0
github.com/masterminds/semver v1.5.0
- github.com/minio/selfupdate v0.4.0
+ github.com/mattn/go-isatty v0.0.20
+ github.com/minio/selfupdate v0.6.0
github.com/mitchellh/go-homedir v1.1.0
- github.com/snakeice/gogress v1.0.1
- github.com/spf13/cobra v1.4.0
- github.com/xlab/treeprint v1.1.0
- golang.org/x/crypto v0.35.0
- golang.org/x/sys v0.30.0
- golang.org/x/term v0.29.0
- golang.org/x/text v0.22.0
+ github.com/pterm/pterm v0.12.80
+ github.com/snakeice/gogress v1.0.3
+ github.com/spf13/cobra v1.9.1
+ github.com/xlab/treeprint v1.2.0
+ golang.org/x/crypto v0.36.0
+ golang.org/x/sys v0.31.0
+ golang.org/x/text v0.23.0
)
require (
- github.com/Masterminds/semver v1.4.2 // indirect
- github.com/Microsoft/go-winio v0.5.2 // indirect
- github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b // indirect
- github.com/acomagu/bufpipe v1.0.3 // indirect
+ 4d63.com/gocheckcompilerdirectives v1.3.0 // indirect
+ 4d63.com/gochecknoglobals v0.2.2 // indirect
+ aead.dev/minisign v0.3.0 // indirect
+ atomicgo.dev/cursor v0.2.0 // indirect
+ atomicgo.dev/keyboard v0.2.9 // indirect
+ atomicgo.dev/schedule v0.1.0 // indirect
+ dario.cat/mergo v1.0.1 // indirect
+ github.com/4meepo/tagalign v1.4.2 // indirect
+ github.com/Abirdcfly/dupword v0.1.3 // indirect
+ github.com/Antonboom/errname v1.0.0 // indirect
+ github.com/Antonboom/nilnil v1.0.1 // indirect
+ github.com/Antonboom/testifylint v1.5.2 // indirect
+ github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect
+ github.com/Crocmagnon/fatcontext v0.7.1 // indirect
+ github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect
+ github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 // indirect
+ github.com/Masterminds/semver v1.5.0 // indirect
+ github.com/Masterminds/semver/v3 v3.3.0 // indirect
+ github.com/Microsoft/go-winio v0.6.2 // indirect
+ github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect
+ github.com/ProtonMail/go-crypto v1.1.6 // indirect
+ github.com/alecthomas/go-check-sumtype v0.3.1 // indirect
+ github.com/alexkohler/nakedret/v2 v2.0.5 // indirect
+ github.com/alexkohler/prealloc v1.0.0 // indirect
+ github.com/alingse/asasalint v0.0.11 // indirect
+ github.com/alingse/nilnesserr v0.1.2 // indirect
+ github.com/ashanbrown/forbidigo v1.6.0 // indirect
+ github.com/ashanbrown/makezero v1.2.0 // indirect
+ github.com/beorn7/perks v1.0.1 // indirect
+ github.com/bkielbasa/cyclop v1.2.3 // indirect
+ github.com/blizzy78/varnamelen v0.8.0 // indirect
+ github.com/bombsimon/wsl/v4 v4.5.0 // indirect
+ github.com/breml/bidichk v0.3.2 // indirect
+ github.com/breml/errchkjson v0.4.0 // indirect
+ github.com/butuzov/ireturn v0.3.1 // indirect
+ github.com/butuzov/mirror v1.3.0 // indirect
+ github.com/catenacyber/perfsprint v0.8.2 // indirect
+ github.com/ccojocar/zxcvbn-go v1.0.2 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
+ github.com/charithe/durationcheck v0.0.10 // indirect
+ github.com/chavacava/garif v0.1.0 // indirect
+ github.com/ckaznocha/intrange v0.3.0 // indirect
+ github.com/cloudflare/circl v1.6.0 // indirect
+ github.com/containerd/console v1.0.4 // indirect
+ github.com/curioswitch/go-reassign v0.3.0 // indirect
+ github.com/cyphar/filepath-securejoin v0.4.1 // indirect
+ github.com/daixiang0/gci v0.13.5 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/denis-tingaikin/go-header v0.5.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
- github.com/fatih/color v1.13.0 // indirect
- github.com/go-git/gcfg v1.5.0 // indirect
+ github.com/ettle/strcase v0.2.0 // indirect
+ github.com/fatih/color v1.18.0 // indirect
+ github.com/fatih/structtag v1.2.0 // indirect
+ github.com/firefart/nonamedreturns v1.0.5 // indirect
+ github.com/fsnotify/fsnotify v1.5.4 // indirect
+ github.com/fzipp/gocyclo v0.6.0 // indirect
+ github.com/ghostiam/protogetter v0.3.9 // indirect
+ github.com/go-critic/go-critic v0.12.0 // indirect
+ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
+ github.com/go-toolsmith/astcast v1.1.0 // indirect
+ github.com/go-toolsmith/astcopy v1.1.0 // indirect
+ github.com/go-toolsmith/astequal v1.2.0 // indirect
+ github.com/go-toolsmith/astfmt v1.1.0 // indirect
+ github.com/go-toolsmith/astp v1.1.0 // indirect
+ github.com/go-toolsmith/strparse v1.1.0 // indirect
+ github.com/go-toolsmith/typep v1.1.0 // indirect
+ github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
+ github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect
+ github.com/gobwas/glob v0.2.3 // indirect
+ github.com/gofrs/flock v0.12.1 // indirect
+ github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
+ github.com/golang/protobuf v1.5.4 // indirect
+ github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect
+ github.com/golangci/go-printf-func-name v0.1.0 // indirect
+ github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect
+ github.com/golangci/golangci-lint v1.64.8 // indirect
+ github.com/golangci/misspell v0.6.0 // indirect
+ github.com/golangci/plugin-module-register v0.1.1 // indirect
+ github.com/golangci/revgrep v0.8.0 // indirect
+ github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // indirect
+ github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
- github.com/imdario/mergo v0.3.13 // indirect
- github.com/inconshreveable/mousetrap v1.0.0 // indirect
+ github.com/gookit/color v1.5.4 // indirect
+ github.com/gordonklaus/ineffassign v0.1.0 // indirect
+ github.com/gostaticanalysis/analysisutil v0.7.1 // indirect
+ github.com/gostaticanalysis/comment v1.5.0 // indirect
+ github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect
+ github.com/gostaticanalysis/nilerr v0.1.1 // indirect
+ github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect
+ github.com/hashicorp/go-version v1.7.0 // indirect
+ github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
+ github.com/hashicorp/hcl v1.0.0 // indirect
+ github.com/hexops/gotextdiff v1.0.3 // indirect
+ github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
+ github.com/jgautheron/goconst v1.7.1 // indirect
+ github.com/jingyugao/rowserrcheck v1.1.1 // indirect
+ github.com/jjti/go-spancheck v0.6.4 // indirect
+ github.com/julz/importas v0.2.0 // indirect
+ github.com/karamaru-alpha/copyloopvar v1.2.1 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
- github.com/mattn/go-colorable v0.1.12 // indirect
- github.com/mattn/go-isatty v0.0.14 // indirect
- github.com/mattn/go-runewidth v0.0.13 // indirect
- github.com/rivo/uniseg v0.2.0 // indirect
- github.com/sergi/go-diff v1.2.0 // indirect
- github.com/spf13/pflag v1.0.5 // indirect
- github.com/xanzy/ssh-agent v0.3.1 // indirect
- golang.org/x/net v0.36.0 // indirect
+ github.com/kisielk/errcheck v1.9.0 // indirect
+ github.com/kkHAIKE/contextcheck v1.1.6 // indirect
+ github.com/kulti/thelper v0.6.3 // indirect
+ github.com/kunwardeep/paralleltest v1.0.10 // indirect
+ github.com/lasiar/canonicalheader v1.1.2 // indirect
+ github.com/ldez/exptostd v0.4.2 // indirect
+ github.com/ldez/gomoddirectives v0.6.1 // indirect
+ github.com/ldez/grignotin v0.9.0 // indirect
+ github.com/ldez/tagliatelle v0.7.1 // indirect
+ github.com/ldez/usetesting v0.4.2 // indirect
+ github.com/leonklingele/grouper v1.1.2 // indirect
+ github.com/lithammer/fuzzysearch v1.1.8 // indirect
+ github.com/macabu/inamedparam v0.1.3 // indirect
+ github.com/magiconair/properties v1.8.6 // indirect
+ github.com/maratori/testableexamples v1.0.0 // indirect
+ github.com/maratori/testpackage v1.1.1 // indirect
+ github.com/matoous/godox v1.1.0 // indirect
+ github.com/mattn/go-colorable v0.1.14 // indirect
+ github.com/mattn/go-runewidth v0.0.16 // indirect
+ github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
+ github.com/mgechev/revive v1.7.0 // indirect
+ github.com/mitchellh/mapstructure v1.5.0 // indirect
+ github.com/moricho/tparallel v0.3.2 // 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
+ github.com/nunnatsa/ginkgolinter v0.19.1 // indirect
+ github.com/olekukonko/tablewriter v0.0.5 // indirect
+ github.com/pelletier/go-toml v1.9.5 // indirect
+ github.com/pelletier/go-toml/v2 v2.2.3 // indirect
+ github.com/pjbgf/sha1cd v0.3.2 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/polyfloyd/go-errorlint v1.7.1 // indirect
+ github.com/prometheus/client_golang v1.12.1 // indirect
+ github.com/prometheus/client_model v0.2.0 // indirect
+ github.com/prometheus/common v0.32.1 // indirect
+ github.com/prometheus/procfs v0.7.3 // indirect
+ github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect
+ github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect
+ github.com/quasilyte/gogrep v0.5.0 // indirect
+ github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect
+ github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect
+ github.com/raeperd/recvcheck v0.2.0 // indirect
+ github.com/rivo/uniseg v0.4.7 // indirect
+ github.com/rogpeppe/go-internal v1.14.1 // indirect
+ github.com/ryancurrah/gomodguard v1.3.5 // indirect
+ github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect
+ github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect
+ github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect
+ github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
+ github.com/sashamelentyev/usestdlibvars v1.28.0 // indirect
+ github.com/securego/gosec/v2 v2.22.2 // indirect
+ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
+ github.com/sirupsen/logrus v1.9.3 // indirect
+ github.com/sivchari/containedctx v1.0.3 // indirect
+ github.com/sivchari/tenv v1.12.1 // indirect
+ github.com/skeema/knownhosts v1.3.1 // indirect
+ github.com/sonatard/noctx v0.1.0 // indirect
+ github.com/sourcegraph/go-diff v0.7.0 // indirect
+ github.com/spf13/afero v1.12.0 // indirect
+ github.com/spf13/cast v1.5.0 // indirect
+ github.com/spf13/jwalterweatherman v1.1.0 // indirect
+ github.com/spf13/pflag v1.0.6 // indirect
+ github.com/spf13/viper v1.12.0 // indirect
+ github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
+ github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect
+ github.com/stretchr/objx v0.5.2 // indirect
+ github.com/stretchr/testify v1.10.0 // indirect
+ github.com/subosito/gotenv v1.4.1 // indirect
+ github.com/tdakkota/asciicheck v0.4.1 // indirect
+ github.com/tetafro/godot v1.5.0 // indirect
+ github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3 // indirect
+ github.com/timonwong/loggercheck v0.10.1 // indirect
+ github.com/tomarrell/wrapcheck/v2 v2.10.0 // indirect
+ github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect
+ github.com/ultraware/funlen v0.2.0 // indirect
+ github.com/ultraware/whitespace v0.2.0 // indirect
+ github.com/uudashr/gocognit v1.2.0 // indirect
+ github.com/uudashr/iface v1.3.1 // 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/yagipy/maintidx v1.0.0 // indirect
+ github.com/yeya24/promlinter v0.3.0 // indirect
+ github.com/ykadowak/zerologlint v0.1.5 // indirect
+ gitlab.com/bosi/decorder v0.4.2 // indirect
+ go-simpler.org/musttag v0.13.0 // indirect
+ go-simpler.org/sloglint v0.9.0 // indirect
+ go.uber.org/atomic v1.7.0 // indirect
+ go.uber.org/automaxprocs v1.6.0 // indirect
+ go.uber.org/multierr v1.6.0 // indirect
+ go.uber.org/zap v1.24.0 // indirect
+ golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect
+ golang.org/x/mod v0.24.0 // indirect
+ golang.org/x/net v0.37.0 // indirect
+ golang.org/x/sync v0.12.0 // indirect
+ golang.org/x/term v0.30.0 // indirect
+ golang.org/x/tools v0.31.0 // indirect
+ google.golang.org/protobuf v1.36.5 // indirect
+ gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
+ gopkg.in/yaml.v2 v2.4.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+ honnef.co/go/tools v0.6.1 // indirect
+ mvdan.cc/gofumpt v0.7.0 // indirect
+ mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect
)
diff --git a/go.sum b/go.sum
index dc11bd4..a2b88a9 100644
--- a/go.sum
+++ b/go.sum
@@ -1,240 +1,1106 @@
-github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc=
-github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
-github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
-github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
-github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
-github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
+4d63.com/gocheckcompilerdirectives v1.3.0 h1:Ew5y5CtcAAQeTVKUVFrE7EwHMrTO6BggtEj8BZSjZ3A=
+4d63.com/gocheckcompilerdirectives v1.3.0/go.mod h1:ofsJ4zx2QAuIP/NO/NAh1ig6R1Fb18/GI7RVMwz7kAY=
+4d63.com/gochecknoglobals v0.2.2 h1:H1vdnwnMaZdQW/N+NrkT1SZMTBmcwHe9Vq8lJcYYTtU=
+4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0=
+aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ=
+aead.dev/minisign v0.3.0 h1:8Xafzy5PEVZqYDNP60yJHARlW1eOQtsKNp/Ph2c0vRA=
+aead.dev/minisign v0.3.0/go.mod h1:NLvG3Uoq3skkRMDuc3YHpWUTMTrSExqm+Ij73W13F6Y=
+atomicgo.dev/assert v0.0.2 h1:FiKeMiZSgRrZsPo9qn/7vmr7mCsh5SZyXY4YGYiYwrg=
+atomicgo.dev/assert v0.0.2/go.mod h1:ut4NcI3QDdJtlmAxQULOmA13Gz6e2DWbSAS8RUOmNYQ=
+atomicgo.dev/cursor v0.2.0 h1:H6XN5alUJ52FZZUkI7AlJbUc1aW38GWZalpYRPpoPOw=
+atomicgo.dev/cursor v0.2.0/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU=
+atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8=
+atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ=
+atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs=
+atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU=
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
+cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
+cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
+cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
+cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
+cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
+cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
+cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
+cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
+cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
+cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
+cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
+cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
+cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
+cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
+cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
+dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E=
+github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI=
+github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE=
+github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw=
+github.com/Antonboom/errname v1.0.0 h1:oJOOWR07vS1kRusl6YRSlat7HFnb3mSfMl6sDMRoTBA=
+github.com/Antonboom/errname v1.0.0/go.mod h1:gMOBFzK/vrTiXN9Oh+HFs+e6Ndl0eTFbtsRTSRdXyGI=
+github.com/Antonboom/nilnil v1.0.1 h1:C3Tkm0KUxgfO4Duk3PM+ztPncTFlOf0b2qadmS0s4xs=
+github.com/Antonboom/nilnil v1.0.1/go.mod h1:CH7pW2JsRNFgEh8B2UaPZTEPhCMuFowP/e8Udp9Nnb0=
+github.com/Antonboom/testifylint v1.5.2 h1:4s3Xhuv5AvdIgbd8wOOEeo0uZG7PbDKQyKY5lGoQazk=
+github.com/Antonboom/testifylint v1.5.2/go.mod h1:vxy8VJ0bc6NavlYqjZfmp6EfqXMtBgQ4+mhCojwC1P8=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=
+github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/Crocmagnon/fatcontext v0.7.1 h1:SC/VIbRRZQeQWj/TcQBS6JmrXcfA+BU4OGSVUt54PjM=
+github.com/Crocmagnon/fatcontext v0.7.1/go.mod h1:1wMvv3NXEBJucFGfwOJBxSVWcoIO6emV215SMkW9MFU=
+github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM=
+github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs=
+github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 h1:Sz1JIXEcSfhz7fUi7xHnhpIE0thVASYjvosApmHuD2k=
+github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1/go.mod h1:n/LSCXNuIYqVfBlVXyHfMQkZDdp1/mmxfSjADd3z1Zg=
+github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs=
+github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8=
+github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII=
+github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k=
+github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI=
+github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c=
+github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE=
+github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4=
+github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY=
+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.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
+github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
-github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
-github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b h1:lcbBNuQhppsc7A5gjdHmdlqUqJfgGMylBdGyDs0j7G8=
-github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
-github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
-github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
-github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
-github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
+github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
+github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
+github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4=
+github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo=
+github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw=
+github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
+github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
+github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
+github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU=
+github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E=
+github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
+github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
+github.com/alexkohler/nakedret/v2 v2.0.5 h1:fP5qLgtwbx9EJE8dGEERT02YwS8En4r9nnZ71RK+EVU=
+github.com/alexkohler/nakedret/v2 v2.0.5/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU=
+github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw=
+github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE=
+github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw=
+github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I=
+github.com/alingse/nilnesserr v0.1.2 h1:Yf8Iwm3z2hUUrP4muWfW83DF4nE3r1xZ26fGWUKCZlo=
+github.com/alingse/nilnesserr v0.1.2/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg=
+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/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
-github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
-github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY=
+github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU=
+github.com/ashanbrown/makezero v1.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9IEUU=
+github.com/ashanbrown/makezero v1.2.0/go.mod h1:dxlPhHbDMC6N6xICzFBSK+4njQDdK8euNO0qjQMtGY4=
+github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
+github.com/beevik/etree v1.5.0 h1:iaQZFSDS+3kYZiGoc9uKeOkUY3nYMXOKLl6KIJxiJWs=
+github.com/beevik/etree v1.5.0/go.mod h1:gPNJNaBGVZ9AwsidazFZyygnd+0pAU38N4D+WemwKNs=
+github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
+github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5w=
+github.com/bkielbasa/cyclop v1.2.3/go.mod h1:kHTwA9Q0uZqOADdupvcFJQtp/ksSnytRMe8ztxG8Fuo=
+github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M=
+github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k=
+github.com/bombsimon/wsl/v4 v4.5.0 h1:iZRsEvDdyhd2La0FVi5k6tYehpOR/R7qIUjmKk7N74A=
+github.com/bombsimon/wsl/v4 v4.5.0/go.mod h1:NOQ3aLF4nD7N5YPXMruR6ZXDOAqLoM0GEpLwTdvmOSc=
+github.com/breml/bidichk v0.3.2 h1:xV4flJ9V5xWTqxL+/PMFF6dtJPvZLPsyixAoPe8BGJs=
+github.com/breml/bidichk v0.3.2/go.mod h1:VzFLBxuYtT23z5+iVkamXO386OB+/sVwZOpIj6zXGos=
+github.com/breml/errchkjson v0.4.0 h1:gftf6uWZMtIa/Is3XJgibewBm2ksAQSY/kABDNFTAdk=
+github.com/breml/errchkjson v0.4.0/go.mod h1:AuBOSTHyLSaaAFlWsRSuRBIroCh3eh7ZHh5YeelDIk8=
+github.com/butuzov/ireturn v0.3.1 h1:mFgbEI6m+9W8oP/oDdfA34dLisRFCj2G6o/yiI1yZrY=
+github.com/butuzov/ireturn v0.3.1/go.mod h1:ZfRp+E7eJLC0NQmk1Nrm1LOrn/gQlOykv+cVPdiXH5M=
+github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc=
+github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI=
+github.com/catenacyber/perfsprint v0.8.2 h1:+o9zVmCSVa7M4MvabsWvESEhpsMkhfE7k0sHNGL95yw=
+github.com/catenacyber/perfsprint v0.8.2/go.mod h1:q//VWC2fWbcdSLEY1R3l8n0zQCDPdE4IjZwyY1HMunM=
+github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg=
+github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4=
+github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ=
+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/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/ckaznocha/intrange v0.3.0 h1:VqnxtK32pxgkhJgYQEeOArVidIPg+ahLP7WBOXZd5ZY=
+github.com/ckaznocha/intrange v0.3.0/go.mod h1:+I/o2d2A1FBHgGELbGxzIcyd3/9l9DuwjM8FsbSS3Lo=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
+github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
+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.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
+github.com/curioswitch/go-reassign v0.3.0 h1:dh3kpQHuADL3cobV/sSGETA8DOv457dwl+fbBAhrQPs=
+github.com/curioswitch/go-reassign v0.3.0/go.mod h1:nApPCCTtqLJN/s8HfItCcKV0jIPwluBOvZP+dsJGA88=
+github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
+github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
+github.com/daixiang0/gci v0.13.5 h1:kThgmH1yBmZSBCh1EJVxQ7JsHpm5Oms0AMed/0LaH4c=
+github.com/daixiang0/gci v0.13.5/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8=
+github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY=
github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMSRhl4D7AQ=
github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI=
-github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
+github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
+github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
+github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
+github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
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.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
-github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
-github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
-github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
-github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
-github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
-github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
-github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
-github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
-github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34=
-github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
-github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8=
-github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
-github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4=
-github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q=
+github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A=
+github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
+github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
+github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
+github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
+github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA=
+github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw=
+github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
+github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
+github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
+github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
+github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
+github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
+github.com/ghostiam/protogetter v0.3.9 h1:j+zlLLWzqLay22Cz/aYwTHKQ88GE2DQ6GkWSYFOI4lQ=
+github.com/ghostiam/protogetter v0.3.9/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA=
+github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
+github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
+github.com/go-critic/go-critic v0.12.0 h1:iLosHZuye812wnkEz1Xu3aBwn5ocCPfc9yqmFG9pa6w=
+github.com/go-critic/go-critic v0.12.0/go.mod h1:DpE0P6OVc6JzVYzmM5gq5jMU31zLr4am5mB/VfFK64w=
+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.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
+github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
+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.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60=
+github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
+github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
+github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8=
+github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU=
+github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s=
+github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw=
+github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4=
+github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ=
+github.com/go-toolsmith/astequal v1.2.0 h1:3Fs3CYZ1k9Vo4FzFhwwewC3CHISHDnVUPC4x0bI2+Cw=
+github.com/go-toolsmith/astequal v1.2.0/go.mod h1:c8NZ3+kSFtFY/8lPso4v8LuJjdJiUFVnSuU3s0qrrDY=
+github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco=
+github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4=
+github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA=
+github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA=
+github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk=
+github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus=
+github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
+github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw=
+github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ=
+github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus=
+github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig=
+github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
+github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
+github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY=
+github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
+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/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
+github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
+github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 h1:WUvBfQL6EW/40l6OmeSBYQJNSif4O11+bmWEz+C7FYw=
+github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32/go.mod h1:NUw9Zr2Sy7+HxzdjIULge71wI6yEg1lWQr7Evcu8K0E=
+github.com/golangci/go-printf-func-name v0.1.0 h1:dVokQP+NMTO7jwO4bwsRwLWeudOVUPPyAKJuzv8pEJU=
+github.com/golangci/go-printf-func-name v0.1.0/go.mod h1:wqhWFH5mUdJQhweRnldEywnR5021wTdZSNgwYceV14s=
+github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE=
+github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY=
+github.com/golangci/golangci-lint v1.64.8 h1:y5TdeVidMtBGG32zgSC7ZXTFNHrsJkDnpO4ItB3Am+I=
+github.com/golangci/golangci-lint v1.64.8/go.mod h1:5cEsUQBSr6zi8XI8OjmcY2Xmliqc4iYL7YoPrL+zLJ4=
+github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs=
+github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo=
+github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c=
+github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc=
+github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s=
+github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k=
+github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs=
+github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
+github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-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/google/go-github/v45 v45.1.0 h1:SbUjHMRiCe9cHfu6Me4idWxLQEV8ZW9DLPz69zopyWo=
-github.com/google/go-github/v45 v45.1.0/go.mod h1:FObaZJEDSTa/WGCzZ2Z3eoCDXWJKMenWWTrd8jrta28=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/google/go-github/v69 v69.2.0 h1:wR+Wi/fN2zdUx9YxSmYE0ktiX9IAR/BeePzeaUUbEHE=
+github.com/google/go-github/v69 v69.2.0/go.mod h1:xne4jymxLR6Uj9b7J7PyTpkMYstEMMwGZa0Aehh1azM=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
-github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
-github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
-github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
-github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
-github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
+github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
+github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
+github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
+github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s=
+github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0=
+github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk=
+github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc=
+github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado=
+github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM=
+github.com/gostaticanalysis/comment v1.5.0 h1:X82FLl+TswsUMpMh17srGRuKaaXprTaytmEpgnKIDu8=
+github.com/gostaticanalysis/comment v1.5.0/go.mod h1:V6eb3gpCv9GNVqb6amXzEUX3jXLVK/AdA+IrAMSqvEc=
+github.com/gostaticanalysis/forcetypeassert v0.2.0 h1:uSnWrrUEYDr86OCxWa4/Tp2jeYDlogZiZHzGkWFefTk=
+github.com/gostaticanalysis/forcetypeassert v0.2.0/go.mod h1:M5iPavzE9pPqWyeiVXSFghQjljW1+l/Uke3PXHS6ILY=
+github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk=
+github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A=
+github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M=
+github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8=
+github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs=
+github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo=
+github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw=
+github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
+github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
+github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
+github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
+github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+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/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+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/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
-github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
+github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk=
+github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4=
+github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs=
+github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c=
+github.com/jjti/go-spancheck v0.6.4 h1:Tl7gQpYf4/TMU7AT84MN83/6PutY21Nb9fuQjFTpRRc=
+github.com/jjti/go-spancheck v0.6.4/go.mod h1:yAEYdKJ2lRkDA8g7X+oKUHXOWVAXSBJRv04OhF+QUjk=
+github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
+github.com/julz/importas v0.2.0 h1:y+MJN/UdL63QbFJHws9BVC5RpA2iq0kpjrFajTGivjQ=
+github.com/julz/importas v0.2.0/go.mod h1:pThlt589EnCYtMnmhmRYY/qn9lCf/frPOK+WMx3xiJY=
+github.com/karamaru-alpha/copyloopvar v1.2.1 h1:wmZaZYIjnJ0b5UoKDjUHrikcV0zuPyyxI4SVplLd2CI=
+github.com/karamaru-alpha/copyloopvar v1.2.1/go.mod h1:nFmMlFNlClC2BPvNaHMdkirmTJxVCY0lhxBtlfOypMM=
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.9.0 h1:9xt1zI9EBfcYBvdU1nVrzMzzUPUtPKs9bVSIM3TAb3M=
+github.com/kisielk/errcheck v1.9.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0D+/VL/i8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/kkHAIKE/contextcheck v1.1.6 h1:7HIyRcnyzxL9Lz06NGhiKvenXq7Zw6Q0UQu/ttjfJCE=
+github.com/kkHAIKE/contextcheck v1.1.6/go.mod h1:3dDbMRNBFaq8HFXWC1JyvDSPm43CmE6IuHam8Wr0rkg=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
+github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
+github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
+github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+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/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs=
+github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I=
+github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs=
+github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY=
+github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4=
+github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI=
+github.com/ldez/exptostd v0.4.2 h1:l5pOzHBz8mFOlbcifTxzfyYbgEmoUqjxLFHZkjlbHXs=
+github.com/ldez/exptostd v0.4.2/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ=
+github.com/ldez/gomoddirectives v0.6.1 h1:Z+PxGAY+217f/bSGjNZr/b2KTXcyYLgiWI6geMBN2Qc=
+github.com/ldez/gomoddirectives v0.6.1/go.mod h1:cVBiu3AHR9V31em9u2kwfMKD43ayN5/XDgr+cdaFaKs=
+github.com/ldez/grignotin v0.9.0 h1:MgOEmjZIVNn6p5wPaGp/0OKWyvq42KnzAt/DAb8O4Ow=
+github.com/ldez/grignotin v0.9.0/go.mod h1:uaVTr0SoZ1KBii33c47O1M8Jp3OP3YDwhZCmzT9GHEk=
+github.com/ldez/tagliatelle v0.7.1 h1:bTgKjjc2sQcsgPiT902+aadvMjCeMHrY7ly2XKFORIk=
+github.com/ldez/tagliatelle v0.7.1/go.mod h1:3zjxUpsNB2aEZScWiZTHrAXOl1x25t3cRmzfK1mlo2I=
+github.com/ldez/usetesting v0.4.2 h1:J2WwbrFGk3wx4cZwSMiCQQ00kjGR0+tuuyW0Lqm4lwA=
+github.com/ldez/usetesting v0.4.2/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ=
+github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY=
+github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA=
+github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
+github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
+github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk=
+github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I=
+github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
+github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
+github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI=
+github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE=
+github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04=
+github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc=
github.com/masterminds/semver v1.5.0 h1:hTxJTTY7tjvnWMrl08O6u3G6BLlKVwxSz01lVac9P8U=
github.com/masterminds/semver v1.5.0/go.mod h1:s7KNT9fnd7edGzwwP7RBX4H0v/CYd5qdOLfkL1V75yg=
-github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
-github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
-github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
-github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
-github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
-github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
-github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/matoous/godox v1.1.0 h1:W5mqwbyWrwZv6OQ5Z1a/DHGMOvXYCBP3+Ht7KMoJhq4=
+github.com/matoous/godox v1.1.0/go.mod h1:jgE/3fUXiTurkdHOLT5WEkThTSuE7yxHv5iWPa80afs=
+github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
+github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
+github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
+github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
+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.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
-github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
-github.com/minio/selfupdate v0.4.0 h1:A7t07pN4Ch1tBTIRStW0KhUVyykz+2muCqFsITQeEW8=
-github.com/minio/selfupdate v0.4.0/go.mod h1:mcDkzMgq8PRcpCRJo/NlPY7U45O5dfYl2Y0Rg7IustY=
+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/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/mgechev/revive v1.7.0 h1:JyeQ4yO5K8aZhIKf5rec56u0376h8AlKNQEmjfkjKlY=
+github.com/mgechev/revive v1.7.0/go.mod h1:qZnwcNhoguE58dfi96IJeSTPeZQejNeoMQLUZGi4SW4=
+github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU=
+github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
+github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI=
+github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U=
+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/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U=
+github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE=
+github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhKRf3Swg=
+github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs=
+github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk=
+github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c=
+github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ70NJ+c4=
+github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s=
+github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
+github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
+github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
+github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
+github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
+github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
+github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw=
+github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
+github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
+github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
+github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
+github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
+github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
+github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
+github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
+github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
+github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
+github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
+github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
+github.com/polyfloyd/go-errorlint v1.7.1 h1:RyLVXIbosq1gBdk/pChWA8zWYLsq9UEw7a1L5TVMCnA=
+github.com/polyfloyd/go-errorlint v1.7.1/go.mod h1:aXjNb1x2TNhoLsk26iv1yl7a+zTnXPhwEMtEXukiLR8=
+github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
+github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
+github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
+github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
+github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
+github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
+github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
+github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
+github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
+github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI=
+github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg=
+github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE=
+github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU=
+github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE=
+github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8=
+github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=
+github.com/pterm/pterm v0.12.80 h1:mM55B+GnKUnLMUSqhdINe4s6tOuVQIetQ3my8JGyAIg=
+github.com/pterm/pterm v0.12.80/go.mod h1:c6DeF9bSnOSeFPZlfs4ZRAFcf5SCoTwvwQ5xaKGQlHo=
+github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo=
+github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI=
+github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE=
+github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
+github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo=
+github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng=
+github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU=
+github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0=
+github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs=
+github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ=
+github.com/raeperd/recvcheck v0.2.0 h1:GnU+NsbiCqdC2XX5+vMZzP+jAJC5fht7rcVTAhX74UI=
+github.com/raeperd/recvcheck v0.2.0/go.mod h1:n04eYkwIR0JbgD73wT8wL4JjPC3wm0nFtzBnWNocnYU=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+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.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
+github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
-github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
+github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU=
+github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE=
+github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU=
+github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ=
+github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0=
+github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4=
+github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
+github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
+github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw=
+github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ=
+github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ=
+github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8=
+github.com/securego/gosec/v2 v2.22.2 h1:IXbuI7cJninj0nRpZSLCUlotsj8jGusohfONMrHoF6g=
+github.com/securego/gosec/v2 v2.22.2/go.mod h1:UEBGA+dSKb+VqM6TdehR7lnQtIIMorYJ4/9CW1KVQBE=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
-github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+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/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
+github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/snakeice/gogress v1.0.1 h1:/id5PLLYE1yqUOhi69yBLj+4dVcrsJ2OhiNZfETZ5ZM=
-github.com/snakeice/gogress v1.0.1/go.mod h1:98LwSCUhJghkALYLIRolhe9m5EvrkL175CumpMUeEUQ=
-github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
-github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE=
+github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4=
+github.com/sivchari/tenv v1.12.1 h1:+E0QzjktdnExv/wwsnnyk4oqZBUfuh89YMQT1cyuvSY=
+github.com/sivchari/tenv v1.12.1/go.mod h1:1LjSOUCc25snIr5n3DtGGrENhX3LuWefcplwVGC24mw=
+github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
+github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
+github.com/snakeice/gogress v1.0.3 h1://o3tnlEXOXhXY8hIvVGNSCJdIKbdJlfAU2eHABCbxs=
+github.com/snakeice/gogress v1.0.3/go.mod h1:96C8OC6R+Hva7emgj5QJuwv5klsQQsr4H/5L6BfHay4=
+github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM=
+github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c=
+github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0=
+github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs=
+github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
+github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
+github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
+github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
+github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
+github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
+github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
+github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
+github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ=
+github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI=
+github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0=
+github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I=
+github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4=
+github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/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/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+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/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
-github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo=
-github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w=
-github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
-github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
+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.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
+github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
+github.com/tdakkota/asciicheck v0.4.1 h1:bm0tbcmi0jezRA2b5kg4ozmMuGAFotKI3RZfrhfovg8=
+github.com/tdakkota/asciicheck v0.4.1/go.mod h1:0k7M3rCfRXb0Z6bwgvkEIMleKH3kXNz9UqJ9Xuqopr8=
+github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA=
+github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0=
+github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag=
+github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY=
+github.com/tetafro/godot v1.5.0 h1:aNwfVI4I3+gdxjMgYPus9eHmoBeJIbnajOyqZYStzuw=
+github.com/tetafro/godot v1.5.0/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio=
+github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3 h1:y4mJRFlM6fUyPhoXuFg/Yu02fg/nIPFMOY8tOqppoFg=
+github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460=
+github.com/timonwong/loggercheck v0.10.1 h1:uVZYClxQFpw55eh+PIoqM7uAOHMrhVcDoWDery9R8Lg=
+github.com/timonwong/loggercheck v0.10.1/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8=
+github.com/tomarrell/wrapcheck/v2 v2.10.0 h1:SzRCryzy4IrAH7bVGG4cK40tNUhmVmMDuJujy4XwYDg=
+github.com/tomarrell/wrapcheck/v2 v2.10.0/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo=
+github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw=
+github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw=
+github.com/ultraware/funlen v0.2.0 h1:gCHmCn+d2/1SemTdYMiKLAHFYxTYz7z9VIDRaTGyLkI=
+github.com/ultraware/funlen v0.2.0/go.mod h1:ZE0q4TsJ8T1SQcjmkhN/w+MceuatI6pBFSxxyteHIJA=
+github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSWoFa+g=
+github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8=
+github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA=
+github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU=
+github.com/uudashr/iface v1.3.1 h1:bA51vmVx1UIhiIsQFSNq6GZ6VPTk3WNMZgRiCe9R29U=
+github.com/uudashr/iface v1.3.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg=
+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/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU=
+github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg=
+github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
+github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
+github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
+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/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM=
+github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk=
+github.com/yeya24/promlinter v0.3.0 h1:JVDbMp08lVCP7Y6NP3qHroGAO6z2yGKQtS5JsjqtoFs=
+github.com/yeya24/promlinter v0.3.0/go.mod h1:cDfJQQYv9uYciW60QT0eeHlFodotkYZlL+YcPQN+mW4=
+github.com/ykadowak/zerologlint v0.1.5 h1:Gy/fMz1dFQN9JZTPjv1hxEk+sRWm05row04Yoolgdiw=
+github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg=
+github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo=
+gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8=
+go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ=
+go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28=
+go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE=
+go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM=
+go-simpler.org/sloglint v0.9.0 h1:/40NQtjRx9txvsB/RN022KsUJU+zaaSb/9q9BSefSrE=
+go-simpler.org/sloglint v0.9.0/go.mod h1:G/OrAF6uxj48sHahCzrbarVMptL2kjWTaUeC8+fOGww=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
+go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
+go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
+go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
+go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+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/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+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-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
-golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
-golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
-golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
-golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
+golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
+golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
+golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
+golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
+golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
+golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4=
+golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+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.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
+golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/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-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+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-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
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.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.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
-golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
-golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
-golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
-golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
+golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
+golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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.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/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
+golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/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-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/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.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.2.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.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
-golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
+golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/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.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
-golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
-golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
-golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
-golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
+golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
+golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
+golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
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.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
-golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
+golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
+golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU=
+golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU=
+golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
-golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
+golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
+golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
+golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
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=
-google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
+google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
+google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
+google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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-20200227125254-8fa46927fb4f/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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
+gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
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.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+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 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
-gopkg.in/yaml.v3 v3.0.0/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI=
+honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4=
+mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU=
+mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo=
+mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8XzX0u72NttUGVFjO3U=
+mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/internal/upgrade/github.go b/internal/upgrade/github.go
index 9862ad3..c0ce8c7 100644
--- a/internal/upgrade/github.go
+++ b/internal/upgrade/github.go
@@ -4,12 +4,13 @@ import (
"context"
"fmt"
"io"
- "io/ioutil"
"math"
"net/http"
"os"
- "github.com/google/go-github/v45/github"
+ "errors"
+
+ "github.com/google/go-github/v69/github"
"github.com/snakeice/gogress"
)
@@ -61,7 +62,7 @@ func findLatestRelease(releases []*github.RepositoryRelease, preRelease bool) (*
}
if bestRelease == nil {
- return nil, fmt.Errorf("no releases found")
+ return nil, errors.New("no releases found")
}
return bestRelease, nil
@@ -69,26 +70,30 @@ func findLatestRelease(releases []*github.RepositoryRelease, preRelease bool) (*
func findAsset(release *github.RepositoryRelease) (*github.ReleaseAsset, error) {
for _, asset := range release.Assets {
- if asset.GetName() == assetName {
+ if asset.GetName() == getAssetName() {
return asset, nil
}
}
- return nil, fmt.Errorf("no asset found")
+ return nil, errors.New("no asset found")
}
func downloadAsset(asset *github.ReleaseAsset) (*os.File, error) {
- resp, err := http.Get(asset.GetBrowserDownloadURL())
+ req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, asset.GetBrowserDownloadURL(), nil)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create request: %w", err)
+ }
+
+ resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to download asset: %w", err)
}
defer resp.Body.Close()
- file, err := ioutil.TempFile("", "boss")
+ file, err := os.CreateTemp("", "boss")
if err != nil {
return nil, fmt.Errorf("failed to create temp file: %w", err)
}
- // defer file.Close()
bar := gogress.New64(int64(math.Round(float64(asset.GetSize()))))
bar.Start()
diff --git a/internal/upgrade/upgrade.go b/internal/upgrade/upgrade.go
index 2784b98..96023a8 100644
--- a/internal/upgrade/upgrade.go
+++ b/internal/upgrade/upgrade.go
@@ -2,13 +2,14 @@ package upgrade
import (
"bytes"
+ "errors"
"fmt"
"os"
"path/filepath"
"runtime"
"github.com/hashload/boss/internal/version"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/msg"
"github.com/minio/selfupdate"
)
@@ -17,11 +18,6 @@ const (
githubRepository = "boss"
)
-var (
- assetName = fmt.Sprintf("boss-%s-%s.zip", runtime.GOOS, runtime.GOARCH)
- zipFolder = fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH)
-)
-
func BossUpgrade(preRelease bool) error {
releases, err := getBossReleases()
if err != nil {
@@ -37,7 +33,7 @@ func BossUpgrade(preRelease bool) error {
if err != nil {
return err
} else if asset == nil {
- return fmt.Errorf("no asset found")
+ return errors.New("no asset found")
}
if *asset.Name == version.Get().Version {
@@ -53,7 +49,7 @@ func BossUpgrade(preRelease bool) error {
defer file.Close()
defer os.Remove(file.Name())
- buff, err := getAssetFromZip(file, assetName)
+ buff, err := getAssetFromFile(file, getAssetName())
if err != nil {
return fmt.Errorf("failed to get asset from zip: %w", err)
}
@@ -61,14 +57,13 @@ func BossUpgrade(preRelease bool) error {
err = apply(buff)
if err != nil {
return fmt.Errorf("failed to apply update: %w", err)
- } else {
- msg.Info("Update applied successfully to %s", *release.TagName)
- return nil
}
+
+ msg.Info("Update applied successfully to %s", *release.TagName)
+ return nil
}
func apply(buff []byte) error {
-
ex, err := os.Executable()
if err != nil {
panic(err)
@@ -79,5 +74,13 @@ func apply(buff []byte) error {
OldSavePath: fmt.Sprintf("%s_bkp", exePath),
TargetPath: exePath,
})
+}
+
+func getAssetName() string {
+ ext := "zip"
+ if runtime.GOOS != "windows" {
+ ext = "tar.gz"
+ }
+ return fmt.Sprintf("boss-%s-%s.%s", runtime.GOOS, runtime.GOARCH, ext)
}
diff --git a/internal/upgrade/upgrade_test.go b/internal/upgrade/upgrade_test.go
deleted file mode 100644
index 36eefda..0000000
--- a/internal/upgrade/upgrade_test.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package upgrade
-
-import "testing"
-
-func TestBossUpgrade(t *testing.T) {
-
- if err := BossUpgrade(true); err != nil {
- t.Errorf("failed to upgrade boss: %s", err.Error())
- }
-
-}
diff --git a/internal/upgrade/zip.go b/internal/upgrade/zip.go
index da77961..235cf66 100644
--- a/internal/upgrade/zip.go
+++ b/internal/upgrade/zip.go
@@ -1,43 +1,77 @@
package upgrade
import (
+ "archive/tar"
"archive/zip"
+ "compress/gzip"
"fmt"
- "io/ioutil"
+ "io"
"os"
"path"
+ "runtime"
"strings"
)
-func getAssetFromZip(file *os.File, assetName string) ([]byte, error) {
+func getAssetFromFile(file *os.File, assetName string) ([]byte, error) {
stat, err := file.Stat()
if err != nil {
return nil, fmt.Errorf("failed to stat file: %w", err)
}
+ if strings.HasSuffix(assetName, ".zip") {
+ return readFileFromZip(file, assetName, stat)
+ }
+
+ return readFileFromTargz(file, assetName)
+}
+
+func readFileFromZip(file *os.File, assetName string, stat os.FileInfo) ([]byte, error) {
reader, err := zip.NewReader(file, stat.Size())
if err != nil {
return nil, fmt.Errorf("failed to create zip reader: %w", err)
}
- filePreffix := path.Join(zipFolder, "boss")
+ filePreffix := path.Join(fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH), "boss")
for _, file := range reader.File {
if strings.HasPrefix(file.Name, filePreffix) {
+ rc, err := file.Open()
+ if err != nil {
+ return nil, fmt.Errorf("failed to open file: %w", err)
+ }
+ defer rc.Close()
- return readZipFile(file)
+ return io.ReadAll(rc)
}
}
return nil, fmt.Errorf("failed to find asset %s in zip", assetName)
}
-func readZipFile(zfile *zip.File) ([]byte, error) {
- rc, err := zfile.Open()
+func readFileFromTargz(file *os.File, assetName string) ([]byte, error) {
+ gzipReader, err := gzip.NewReader(file)
if err != nil {
- return nil, fmt.Errorf("failed to open file: %w", err)
+ return nil, fmt.Errorf("failed to create gzip reader: %w", err)
+ }
+ defer gzipReader.Close()
+
+ tarReader := tar.NewReader(gzipReader)
+
+ filePreffix := path.Join(fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH), "boss")
+
+ for {
+ header, err := tarReader.Next()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return nil, fmt.Errorf("failed to read tar header: %w", err)
+ }
+
+ if strings.HasPrefix(header.Name, filePreffix) {
+ return io.ReadAll(tarReader)
+ }
}
- defer rc.Close()
- return ioutil.ReadAll(rc)
+ return nil, fmt.Errorf("failed to find asset %s in tar.gz", assetName)
}
diff --git a/internal/version/version.go b/internal/version/version.go
index 8d85d1b..0892ec9 100644
--- a/internal/version/version.go
+++ b/internal/version/version.go
@@ -8,7 +8,10 @@ import (
var (
version = "v0.0.1"
- metadata = ""
+ //nolint:gochecknoglobals // This is a variable that injects the build metadata during build.
+ metadata = ""
+
+ //nolint:gochecknoglobals // This is a variable that injects the git commit hash during build.
gitCommit = ""
)
@@ -28,7 +31,6 @@ func GetVersion() string {
return version + "+" + metadata
}
-// Get returns build info
func Get() BuildInfo {
v := BuildInfo{
Version: GetVersion(),
diff --git a/mise.toml b/mise.toml
new file mode 100644
index 0000000..489fc70
--- /dev/null
+++ b/mise.toml
@@ -0,0 +1,15 @@
+[tools]
+go = "1.24"
+pre-commit = "4.0.1"
+
+[tasks.setup]
+description = "Setup the project"
+run = ["pre-commit install", "go mod download"]
+
+[tasks.lint]
+description = "Run linter"
+run = "pre-commit run --all-files"
+
+[tasks.golint]
+description = "Run golangci-lint"
+run = "go tool golangci-lint run --out-format=colored-line-number"
diff --git a/models/cacheInfo.go b/models/cacheInfo.go
deleted file mode 100644
index 4dc96ad..0000000
--- a/models/cacheInfo.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package models
-
-import (
- "encoding/json"
- "io/ioutil"
- "os"
- "path/filepath"
- "time"
-
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/msg"
-)
-
-type RepoInfo struct {
- Key string `json:"key"`
- LastUpdate time.Time `json:"last_update"`
- Versions []string `json:"versions"`
-}
-
-func SaveRepoData(key string, versions []string) {
- location := env.GetCacheDir()
- data := &RepoInfo{}
- data.Key = key
- data.LastUpdate = time.Now()
- data.Versions = versions
- d, err := json.Marshal(data)
- if err != nil {
- msg.Err(err.Error())
- }
-
- pp := filepath.Join(location, "info")
- err = os.MkdirAll(pp, 0755)
- if err != nil {
- msg.Err(err.Error())
- }
-
- p := filepath.Join(pp, key+".json")
- f, err := os.Create(p)
- if err != nil {
- msg.Err(err.Error())
- return
- }
- defer f.Close()
-
- _, err = f.Write(d)
- if err != nil {
- msg.Err(err.Error())
- }
-}
-
-// RepoData retrieves cached information about a repo.
-func RepoData(key string) (*RepoInfo, error) {
- location := env.GetCacheDir()
- c := &RepoInfo{}
- p := filepath.Join(location, "info", key+".json")
- f, err := ioutil.ReadFile(p)
- if err != nil {
- return &RepoInfo{}, err
- }
- err = json.Unmarshal(f, c)
- if err != nil {
- return &RepoInfo{}, err
- }
- return c, nil
-}
diff --git a/models/package.go b/models/package.go
deleted file mode 100644
index 8bf9e49..0000000
--- a/models/package.go
+++ /dev/null
@@ -1,113 +0,0 @@
-package models
-
-import (
- "encoding/json"
- . "io/ioutil"
- "strings"
-
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/utils/parser"
-)
-
-type Package struct {
- fileName string
- IsNew bool `json:"-"`
- Name string `json:"name"`
- Description string `json:"description"`
- Version string `json:"version"`
- Homepage string `json:"homepage"`
- MainSrc string `json:"mainsrc"`
- BrowsingPath string `json:"browsingpath"`
- Projects []string `json:"projects"`
- Scripts interface{} `json:"scripts,omitempty"`
- Dependencies interface{} `json:"dependencies"`
- Lock PackageLock `json:"-"`
-}
-
-// Save save changes of boss.json file
-func (p *Package) Save() []byte {
- marshal, _ := parser.JSONMarshal(p, true)
- _ = WriteFile(p.fileName, marshal, 0664)
- p.Lock.Save()
- return marshal
-}
-
-func (p *Package) AddDependency(dep string, ver string) {
- if p.Dependencies == nil {
- p.Dependencies = make(map[string]interface{})
- }
- deps := p.Dependencies.(map[string]interface{})
-
- for key := range deps {
- if strings.EqualFold(key, dep) {
- deps[key] = ver
- return
- }
- }
-
- deps[dep] = ver
-}
-
-func (p *Package) AddProject(project string) {
- p.Projects = append(p.Projects, project)
-}
-
-func (p *Package) GetParsedDependencies() []Dependency {
- dependencies := p.Dependencies.(map[string]interface{})
- if len(dependencies) == 0 {
- return []Dependency{}
- }
- return GetDependencies(dependencies)
-}
-
-func (p *Package) UninstallDependency(dep string) {
- if p.Dependencies != nil {
- deps := p.Dependencies.(map[string]interface{})
- for key := range deps {
- if strings.EqualFold(key, dep) {
- delete(deps, key)
- }
- }
- p.Dependencies = deps
- }
-}
-
-func getNew(file string) *Package {
- res := new(Package)
- res.fileName = file
- res.IsNew = true
-
- res.Dependencies = make(map[string]interface{})
- res.Projects = []string{}
- res.Lock = LoadPackageLock(res)
- return res
-}
-
-func LoadPackage(createNew bool) (*Package, error) {
- if fileBytes, e := ReadFile(env.GetBossFile()); e != nil {
- if createNew {
- e = nil
- }
- return getNew(env.GetBossFile()), e
- } else {
- result := getNew(env.GetBossFile())
- if err := json.Unmarshal(fileBytes, result); err != nil {
- return nil, err
- }
- result.Lock = LoadPackageLock(result)
- result.IsNew = false
- return result, nil
- }
-}
-
-func LoadPackageOther(path string) (*Package, error) {
- if fileBytes, e := ReadFile(path); e != nil {
- return getNew(path), e
- } else {
- result := getNew(path)
- if err := json.Unmarshal(fileBytes, result); err != nil {
- return nil, e
- }
- return result, nil
- }
-}
diff --git a/msg/msg.go b/msg/msg.go
deleted file mode 100644
index e28e450..0000000
--- a/msg/msg.go
+++ /dev/null
@@ -1,181 +0,0 @@
-package msg
-
-import (
- "bufio"
- "fmt"
- "io"
- "os"
- "strings"
- "sync"
-)
-
-type Messenger struct {
- sync.Mutex
- Stdout io.Writer
- Stderr io.Writer
- Stdin io.Reader
- PanicOnDie bool
- eCode int
- hasErrored bool
-}
-
-func NewMessenger() *Messenger {
- m := &Messenger{
- Stdout: os.Stdout,
- Stderr: os.Stderr,
- Stdin: os.Stdin,
- PanicOnDie: false,
- eCode: 1,
- }
-
- return m
-}
-
-var DebugEnable bool
-var Default = NewMessenger()
-
-func Die(msg string, args ...interface{}) {
- Default.Die(msg, args...)
-}
-
-func Msg(msg string, args ...interface{}) {
- Default.Msg(msg, args...)
-}
-
-func Puts(msg string, args ...interface{}) {
- Default.Puts(msg, args...)
-}
-
-func Print(msg string) {
- Default.Print(msg)
-}
-
-func PromptUntil(opts []string) (string, error) {
- return Default.PromptUntil(opts)
-}
-
-func PromptUntilYorN() bool {
- return Default.PromptUntilYorN()
-}
-
-func Info(msg string, args ...interface{}) {
- Default.Info(msg, args...)
-}
-
-func Debug(msg string, args ...interface{}) {
- Default.Debug(msg, args...)
-}
-
-func Warn(msg string, args ...interface{}) {
- Default.Warn(msg, args...)
-}
-
-func Err(msg string, args ...interface{}) {
- Default.Err(msg, args...)
-}
-
-func (m *Messenger) Err(msg string, args ...interface{}) {
- m.Msg("[ERROR]\t"+msg, args...)
- m.hasErrored = true
-}
-
-func (m *Messenger) Warn(msg string, args ...interface{}) {
- m.Msg("[WARN ]\t"+msg, args...)
-}
-
-func (m *Messenger) Info(msg string, args ...interface{}) {
- m.Msg("[INFO ]\t"+msg, args...)
-}
-
-func (m *Messenger) Debug(msg string, args ...interface{}) {
- if !DebugEnable {
- return
- }
- m.Msg("[DEBUG]\t"+msg, args...)
-}
-
-func (m *Messenger) Die(msg string, args ...interface{}) {
- m.Err(msg, args...)
- if m.PanicOnDie {
- panic("trapped a Die() call")
- }
- os.Exit(m.eCode)
-}
-
-func (m *Messenger) ExitCode(e int) int {
- m.Lock()
- old := m.eCode
- m.eCode = e
- m.Unlock()
- return old
-}
-
-func ExitCode(e int) int {
- return Default.ExitCode(e)
-}
-
-func (m *Messenger) Msg(msg string, args ...interface{}) {
- m.Lock()
- defer m.Unlock()
- if !strings.HasSuffix(msg, "\n") {
- msg += "\n"
- }
-
- if len(args) == 0 {
- if _, err := fmt.Fprint(m.Stderr, msg); err != nil {
- println("[Fault] %s", err.Error())
- }
- } else {
- if _, err := fmt.Fprintf(m.Stderr, msg, args...); err != nil {
- println("[Fault] %s", err.Error())
- }
- }
-}
-
-func (m *Messenger) Puts(msg string, args ...interface{}) {
- m.Lock()
- defer m.Unlock()
- if _, err := fmt.Fprintf(m.Stderr, msg, args...); err != nil {
- println("[Fault] %s", err.Error())
- }
- if _, err := fmt.Fprintln(m.Stderr); err != nil {
- println("[Fault] %s", err.Error())
- }
-}
-
-func (m *Messenger) Print(msg string) {
- m.Puts(msg)
-}
-
-func (m *Messenger) HasErrored() bool {
- return m.hasErrored
-}
-
-func (m *Messenger) PromptUntil(opts []string) (string, error) {
- reader := bufio.NewReader(os.Stdin)
- for {
- text, err := reader.ReadString('\n')
- if err != nil {
- return "", err
- }
-
- for _, c := range opts {
- if strings.EqualFold(c, strings.TrimSpace(text)) {
- return c, nil
- }
- }
- }
-}
-
-func (m *Messenger) PromptUntilYorN() bool {
- res, err := m.PromptUntil([]string{"y", "yes", "n", "no"})
- if err != nil {
- m.Die("Error processing response: %s", err)
- }
-
- if res == "y" || res == "yes" {
- return true
- }
-
- return false
-}
diff --git a/pkg/compiler/artifacts.go b/pkg/compiler/artifacts.go
new file mode 100644
index 0000000..2755007
--- /dev/null
+++ b/pkg/compiler/artifacts.go
@@ -0,0 +1,61 @@
+package compiler
+
+import (
+ "os"
+ "path/filepath"
+
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/utils"
+)
+
+func moveArtifacts(dep models.Dependency, rootPath string) {
+ var moduleName = dep.Name()
+ movePath(filepath.Join(rootPath, moduleName, consts.BplFolder), filepath.Join(rootPath, consts.BplFolder))
+ movePath(filepath.Join(rootPath, moduleName, consts.DcpFolder), filepath.Join(rootPath, consts.DcpFolder))
+ movePath(filepath.Join(rootPath, moduleName, consts.BinFolder), filepath.Join(rootPath, consts.BinFolder))
+ movePath(filepath.Join(rootPath, moduleName, consts.DcuFolder), filepath.Join(rootPath, consts.DcuFolder))
+}
+
+func movePath(oldPath string, newPath string) {
+ files, err := os.ReadDir(oldPath)
+ var hasError = false
+ if err == nil {
+ for _, file := range files {
+ if !file.IsDir() {
+ err = os.Rename(filepath.Join(oldPath, file.Name()), filepath.Join(newPath, file.Name()))
+ if err != nil {
+ hasError = true
+ }
+ utils.HandleError(err)
+ }
+ }
+ }
+ if !hasError {
+ err = os.RemoveAll(oldPath)
+ if !os.IsNotExist(err) {
+ utils.HandleError(err)
+ }
+ }
+}
+
+func ensureArtifacts(lockedDependency *models.LockedDependency, dep models.Dependency, rootPath string) {
+ var moduleName = dep.Name()
+ lockedDependency.Artifacts.Clean()
+
+ collectArtifacts(lockedDependency.Artifacts.Bpl, filepath.Join(rootPath, moduleName, consts.BplFolder))
+ collectArtifacts(lockedDependency.Artifacts.Dcu, filepath.Join(rootPath, moduleName, consts.DcuFolder))
+ collectArtifacts(lockedDependency.Artifacts.Bin, filepath.Join(rootPath, moduleName, consts.BinFolder))
+ collectArtifacts(lockedDependency.Artifacts.Dcp, filepath.Join(rootPath, moduleName, consts.DcpFolder))
+}
+
+func collectArtifacts(artifactList []string, path string) {
+ files, err := os.ReadDir(path)
+ if err == nil {
+ for _, file := range files {
+ if !file.IsDir() {
+ artifactList = append(artifactList, file.Name())
+ }
+ }
+ }
+}
diff --git a/core/compiler/compiler.go b/pkg/compiler/compiler.go
similarity index 80%
rename from core/compiler/compiler.go
rename to pkg/compiler/compiler.go
index 843a4c8..18fa049 100644
--- a/core/compiler/compiler.go
+++ b/pkg/compiler/compiler.go
@@ -1,16 +1,15 @@
package compiler
import (
- "io/ioutil"
"os"
"path/filepath"
"strings"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/core/compiler/graphs"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/compiler/graphs"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
"github.com/hashload/boss/utils"
)
@@ -27,7 +26,7 @@ func saveLoadOrder(queue *graphs.NodeQueue) {
break
}
node := queue.Dequeue()
- dependencyPath := filepath.Join(env.GetModulesDir(), node.Dep.GetName(), consts.FilePackage)
+ dependencyPath := filepath.Join(env.GetModulesDir(), node.Dep.Name(), consts.FilePackage)
if dependencyPackage, err := models.LoadPackageOther(dependencyPath); err == nil {
for _, value := range dependencyPackage.Projects {
projects += strings.TrimSuffix(filepath.Base(value), filepath.Ext(value)) + consts.FileExtensionBpl + "\n"
@@ -36,7 +35,7 @@ func saveLoadOrder(queue *graphs.NodeQueue) {
}
outDir := filepath.Join(env.GetModulesDir(), consts.BplFolder, consts.FileBplOrder)
- utils.HandleError(ioutil.WriteFile(outDir, []byte(projects), os.ModePerm))
+ utils.HandleError(os.WriteFile(outDir, []byte(projects), 0600))
}
func buildOrderedPackages(pkg *models.Package) {
@@ -47,17 +46,17 @@ func buildOrderedPackages(pkg *models.Package) {
break
}
node := queue.Dequeue()
- dependencyPath := filepath.Join(env.GetModulesDir(), node.Dep.GetName())
+ dependencyPath := filepath.Join(env.GetModulesDir(), node.Dep.Name())
dependency := pkg.Lock.GetInstalled(node.Dep)
- msg.Info("Building %s", node.Dep.GetName())
+ msg.Info("Building %s", node.Dep.Name())
dependency.Changed = false
if dependencyPackage, err := models.LoadPackageOther(filepath.Join(dependencyPath, consts.FilePackage)); err == nil {
dprojs := dependencyPackage.Projects
if len(dprojs) > 0 {
for _, dproj := range dprojs {
- dprojPath, _ := filepath.Abs(filepath.Join(env.GetModulesDir(), node.Dep.GetName(), dproj))
+ dprojPath, _ := filepath.Abs(filepath.Join(env.GetModulesDir(), node.Dep.Name(), dproj))
if !compile(dprojPath, &node.Dep, pkg.Lock) {
dependency.Failed = true
}
@@ -67,6 +66,5 @@ func buildOrderedPackages(pkg *models.Package) {
}
}
pkg.Lock.SetInstalled(node.Dep, dependency)
-
}
}
diff --git a/core/compiler/dependencies.go b/pkg/compiler/dependencies.go
similarity index 77%
rename from core/compiler/dependencies.go
rename to pkg/compiler/dependencies.go
index ad3e268..7157146 100644
--- a/core/compiler/dependencies.go
+++ b/pkg/compiler/dependencies.go
@@ -3,10 +3,10 @@ package compiler
import (
"path/filepath"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/core/compiler/graphs"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
+ "github.com/hashload/boss/pkg/compiler/graphs"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/models"
)
func loadOrderGraph(pkg *models.Package) *graphs.NodeQueue {
@@ -34,7 +34,7 @@ func loadGraph(graph *graphs.GraphItem, dep *models.Dependency, deps []models.De
}
for _, dep := range deps {
- pkgModule, err := models.LoadPackageOther(filepath.Join(env.GetModulesDir(), dep.GetName(), consts.FilePackage))
+ pkgModule, err := models.LoadPackageOther(filepath.Join(env.GetModulesDir(), dep.Name(), consts.FilePackage))
if err != nil {
node := graphs.NewNode(&dep)
graph.AddNode(node)
@@ -42,8 +42,7 @@ func loadGraph(graph *graphs.GraphItem, dep *models.Dependency, deps []models.De
graph.AddEdge(localFather, node)
}
} else {
- deps := pkgModule.GetParsedDependencies()
- loadGraph(graph, &dep, deps, localFather)
+ loadGraph(graph, &dep, pkgModule.GetParsedDependencies(), localFather)
}
}
}
diff --git a/core/compiler/executor.go b/pkg/compiler/executor.go
similarity index 66%
rename from core/compiler/executor.go
rename to pkg/compiler/executor.go
index 89959e9..99f94a5 100644
--- a/core/compiler/executor.go
+++ b/pkg/compiler/executor.go
@@ -1,32 +1,30 @@
package compiler
import (
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
"github.com/hashload/boss/utils"
"github.com/hashload/boss/utils/dcp"
)
func getCompilerParameters(rootPath string, dep *models.Dependency, platform string) string {
- var binPath string
var moduleName = ""
if dep != nil {
- moduleName = dep.GetName()
+ moduleName = dep.Name()
}
- if !env.Global {
+ binPath := env.GetGlobalBinPath()
+
+ if !env.GetGlobal() {
binPath = filepath.Join(rootPath, moduleName, consts.BinFolder)
- } else {
- binPath = env.GetGlobalBinPath()
}
return " /p:DCC_BplOutput=\"" + filepath.Join(rootPath, moduleName, consts.BplFolder) + "\" " +
@@ -43,11 +41,12 @@ func buildSearchPath(dep *models.Dependency) string {
var searchPath = ""
if dep != nil {
- searchPath = filepath.Join(env.GetModulesDir(), dep.GetName())
+ searchPath = filepath.Join(env.GetModulesDir(), dep.Name())
- if pac, e := models.LoadPackageOther(filepath.Join(env.GetModulesDir(), dep.GetName(), consts.FilePackage)); e == nil {
- searchPath += ";" + filepath.Join(env.GetModulesDir(), dep.GetName(), pac.MainSrc)
- for _, lib := range pac.GetParsedDependencies() {
+ packageData, err := models.LoadPackageOther(filepath.Join(env.GetModulesDir(), dep.Name(), consts.FilePackage))
+ if err == nil {
+ searchPath += ";" + filepath.Join(env.GetModulesDir(), dep.Name(), packageData.MainSrc)
+ for _, lib := range packageData.GetParsedDependencies() {
searchPath += ";" + buildSearchPath(&lib)
}
}
@@ -58,7 +57,7 @@ func buildSearchPath(dep *models.Dependency) string {
func compile(dprojPath string, dep *models.Dependency, rootLock models.PackageLock) bool {
msg.Info(" Building " + filepath.Base(dprojPath))
- bossPackagePath := filepath.Join(env.GetModulesDir(), dep.GetName(), consts.FilePackage)
+ bossPackagePath := filepath.Join(env.GetModulesDir(), dep.Name(), consts.FilePackage)
if dependencyPackage, err := models.LoadPackageOther(bossPackagePath); err == nil {
dcp.InjectDpcsFile(dprojPath, dependencyPackage, rootLock)
@@ -70,25 +69,29 @@ func compile(dprojPath string, dep *models.Dependency, rootLock models.PackageLo
abs, _ := filepath.Abs(filepath.Dir(dprojPath))
buildLog := filepath.Join(abs, fileRes+".log")
buildBat := filepath.Join(abs, fileRes+".bat")
- readFile, err := ioutil.ReadFile(rsvars)
+ readFile, err := os.ReadFile(rsvars)
if err != nil {
msg.Err(" error on read rsvars.bat")
}
readFileStr := string(readFile)
project, _ := filepath.Abs(dprojPath)
- readFileStr += "\n@SET DCC_UnitSearchPath=%DCC_UnitSearchPath%;" + filepath.Join(env.GetModulesDir(), consts.DcuFolder) +
+ readFileStr += "\n@SET DCC_UnitSearchPath=%DCC_UnitSearchPath%;" +
+ filepath.Join(env.GetModulesDir(), consts.DcuFolder) +
";" + filepath.Join(env.GetModulesDir(), consts.DcpFolder) //+ ";" + getNewPathsDep(dep, abs) + " "
readFileStr += ";" + buildSearchPath(dep)
readFileStr += "\n@SET PATH=%PATH%;" + filepath.Join(env.GetModulesDir(), consts.BplFolder) + ";"
for _, value := range []string{"Win32"} {
- readFileStr += " \n msbuild \"" + project + "\" /p:Configuration=Debug " + getCompilerParameters(env.GetModulesDir(), dep, value)
+ readFileStr += " \n msbuild \"" +
+ project +
+ "\" /p:Configuration=Debug " +
+ getCompilerParameters(env.GetModulesDir(), dep, value)
}
readFileStr += " > \"" + buildLog + "\""
- err = ioutil.WriteFile(buildBat, []byte(readFileStr), os.ModePerm)
+ err = os.WriteFile(buildBat, []byte(readFileStr), 0600)
if err != nil {
msg.Warn(" - error on create build file")
return false
@@ -96,16 +99,15 @@ func compile(dprojPath string, dep *models.Dependency, rootLock models.PackageLo
command := exec.Command(buildBat)
command.Dir = abs
- if _, err := command.Output(); err != nil {
+ if _, err = command.Output(); err != nil {
msg.Err(" - Failed to compile, see " + buildLog + " for more information")
return false
- } else {
- msg.Info(" - Success!")
- err := os.Remove(buildLog)
- utils.HandleError(err)
- err = os.Remove(buildBat)
- utils.HandleError(err)
-
- return true
}
+ msg.Info(" - Success!")
+ err = os.Remove(buildLog)
+ utils.HandleError(err)
+ err = os.Remove(buildBat)
+ utils.HandleError(err)
+
+ return true
}
diff --git a/core/compiler/graphs/graph.go b/pkg/compiler/graphs/graph.go
similarity index 89%
rename from core/compiler/graphs/graph.go
rename to pkg/compiler/graphs/graph.go
index 31fdd35..6e95722 100644
--- a/core/compiler/graphs/graph.go
+++ b/pkg/compiler/graphs/graph.go
@@ -4,8 +4,10 @@ import (
"strings"
"sync"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
+ "slices"
+
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
)
type Node struct {
@@ -14,11 +16,11 @@ type Node struct {
}
func NewNode(dependency *models.Dependency) *Node {
- return &Node{Dep: *dependency, Value: strings.ToLower(dependency.GetName())}
+ return &Node{Dep: *dependency, Value: strings.ToLower(dependency.Name())}
}
func (n *Node) String() string {
- return n.Dep.GetName()
+ return n.Dep.Name()
}
type GraphItem struct {
@@ -94,7 +96,7 @@ func (g *GraphItem) AddEdge(nLeft, nRight *Node) {
func (g *GraphItem) String() {
g.lock()
- for index := 0; index < len(g.nodes); index++ {
+ for index := range g.nodes {
var node = g.nodes[index]
var response = ""
response += g.nodes[index].String() + " -> \n\t\tDepends: "
@@ -116,9 +118,8 @@ func (g *GraphItem) String() {
func removeNode(nodes []*Node, key int) []*Node {
if key == len(nodes) {
return nodes[:key]
- } else {
- return append(nodes[:key], nodes[key+1:]...)
}
+ return slices.Delete(nodes, key, key+1)
}
func (g *GraphItem) Queue(pkg *models.Package, allDeps bool) *NodeQueue {
@@ -133,6 +134,31 @@ func (g *GraphItem) Queue(pkg *models.Package, allDeps bool) *NodeQueue {
}
}
+ nodes = g.expandGraphNodes(nodes, pkg)
+
+ g.processNodes(nodes, &queue)
+ g.unlock()
+ return &queue
+}
+
+func (g *GraphItem) processNodes(nodes []*Node, queue *NodeQueue) {
+ for {
+ if len(nodes) == 0 {
+ break
+ }
+
+ for key := 0; key < len(nodes); key++ {
+ node := nodes[key]
+ if !containsOne(g.depends[node.Value], nodes) {
+ queue.Enqueue(*node)
+ nodes = removeNode(nodes, key)
+ key--
+ }
+ }
+ }
+}
+
+func (g *GraphItem) expandGraphNodes(nodes []*Node, pkg *models.Package) []*Node {
var redo = true
for {
if !redo {
@@ -154,23 +180,7 @@ func (g *GraphItem) Queue(pkg *models.Package, allDeps bool) *NodeQueue {
}
}
}
-
- for {
- if len(nodes) == 0 {
- break
- }
-
- for key := 0; key < len(nodes); key++ {
- node := nodes[key]
- if !containsOne(g.depends[node.Value], nodes) {
- queue.Enqueue(*node)
- nodes = removeNode(nodes, key)
- key--
- }
- }
- }
- g.unlock()
- return &queue
+ return nodes
}
type NodeQueue struct {
diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go
new file mode 100644
index 0000000..135c98a
--- /dev/null
+++ b/pkg/consts/consts.go
@@ -0,0 +1,62 @@
+package consts
+
+import "path/filepath"
+
+const (
+ FilePackage = "boss.json"
+ FilePackageLock = "boss-lock.json"
+ FileBplOrder = "bpl_order.txt"
+ FileExtensionBpl = ".bpl"
+ FileExtensionDcp = ".dcp"
+ FileExtensionDpk = ".dpk"
+
+ FilePackageLockOld = "boss.lock"
+ FolderDependencies = "modules"
+
+ FolderEnv = "env"
+
+ FolderEnvBpl = FolderEnv + string(filepath.Separator) + "bpl"
+ FolderEnvDcp = FolderEnv + string(filepath.Separator) + "dcp"
+ FolderEnvDcu = FolderEnv + string(filepath.Separator) + "dcu"
+
+ FolderBossHome = ".boss"
+
+ BinFolder string = ".bin"
+ BplFolder string = ".bpl"
+ DcpFolder string = ".dcp"
+ DcuFolder string = ".dcu"
+
+ BossConfigFile = "boss.cfg.json"
+
+ MinimalDependencyVersion string = ">0.0.0"
+
+ EnvBossBin = "." + string(filepath.Separator) + FolderDependencies + string(filepath.Separator) + BinFolder
+
+ XMLTagNameProperty string = "PropertyGroup"
+ XMLValueAttribute = "value"
+ XMLTagNamePropertyAttribute string = "Condition"
+ XMLTagNamePropertyAttributeValue string = "'$(Base)'!=''"
+
+ XMLTagNameLibraryPath string = "DCC_UnitSearchPath"
+
+ XMLTagNameCompilerOptions string = "CompilerOptions"
+ XMLTagNameSearchPaths string = "SearchPaths"
+ XMLTagNameOtherUnitFiles string = "OtherUnitFiles"
+ XMLTagNameProjectOptions string = "ProjectOptions"
+ XMLTagNameBuildModes string = "BuildModes"
+ XMLTagNameItem string = "Item"
+ XMLNameAttribute = "Name"
+
+ BossInternalDir = "internal."
+ BossInternalDirOld = "{internal}"
+
+ BplIdentifierName = "BplIdentifier.exe"
+
+ RegexArtifacts = "(.*.inc$|.*.pas$|.*.dfm$|.*.fmx$|.*.dcu$|.*.bpl$|.*.dcp$|.*.res$)"
+
+ RegistryBasePath = `Software\Embarcadero\BDS\`
+)
+
+func DefaultPaths() []string {
+ return []string{BplFolder, DcuFolder, DcpFolder, BinFolder}
+}
diff --git a/env/configuration.go b/pkg/env/configuration.go
similarity index 73%
rename from env/configuration.go
rename to pkg/env/configuration.go
index 9a8afab..7376cbf 100644
--- a/env/configuration.go
+++ b/pkg/env/configuration.go
@@ -2,7 +2,6 @@ package env
import (
"encoding/json"
- "io/ioutil"
"os"
"path/filepath"
"time"
@@ -10,16 +9,14 @@ import (
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/http"
sshGit "github.com/go-git/go-git/v5/plumbing/transport/ssh"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/msg"
"github.com/hashload/boss/utils/crypto"
"golang.org/x/crypto/ssh"
)
-var machineID = []byte(crypto.GetMachineID()[:16])
-
type Configuration struct {
- path string
+ path string `json:"-"`
Key string `json:"id"`
Auth map[string]*Auth `json:"auth"`
PurgeTime int `json:"purge_after"`
@@ -29,53 +26,58 @@ type Configuration struct {
DelphiPath string `json:"delphi_path,omitempty"`
ConfigVersion int64 `json:"config_version"`
GitEmbedded bool `json:"git_embedded"`
+
+ Advices struct {
+ SetupPath bool `json:"setup_path,omitempty"`
+ } `json:"advices"`
}
type Auth struct {
- UseSsh bool `json:"use,omitempty"`
+ UseSSH bool `json:"use,omitempty"`
Path string `json:"path,omitempty"`
- User string `json:"x,omitempty"`
- Pass string `json:"y,omitempty"`
- PassPhrase string `json:"z,omitempty"`
+ User string `json:"user,omitempty"`
+ Pass string `json:"pass,omitempty"`
+ PassPhrase string `json:"keypass,omitempty"`
}
func (a *Auth) GetUser() string {
- if ret, err := crypto.Decrypt(machineID, a.User); err != nil {
+ ret, err := crypto.Decrypt(crypto.MachineKey(), a.User)
+ if err != nil {
msg.Err("Fail to decrypt user.")
return ""
- } else {
- return ret
}
+ return ret
}
func (a *Auth) GetPassword() string {
- if ret, err := crypto.Decrypt(machineID, a.Pass); err != nil {
+ ret, err := crypto.Decrypt(crypto.MachineKey(), a.Pass)
+ if err != nil {
msg.Err("Fail to decrypt pass.", err)
return ""
- } else {
- return ret
}
+
+ return ret
}
func (a *Auth) GetPassPhrase() string {
- if ret, err := crypto.Decrypt(machineID, a.PassPhrase); err != nil {
+ ret, err := crypto.Decrypt(crypto.MachineKey(), a.PassPhrase)
+ if err != nil {
msg.Err("Fail to decrypt PassPhrase.", err)
return ""
- } else {
- return ret
}
+ return ret
}
func (a *Auth) SetUser(user string) {
- if cUSer, err := crypto.Encrypt(machineID, user); err != nil {
+ if encryptedUser, err := crypto.Encrypt(crypto.MachineKey(), user); err != nil {
msg.Err("Fail to crypt user.", err)
} else {
- a.User = cUSer
+ a.User = encryptedUser
}
}
func (a *Auth) SetPass(pass string) {
- if cPass, err := crypto.Encrypt(machineID, pass); err != nil {
+ if cPass, err := crypto.Encrypt(crypto.MachineKey(), pass); err != nil {
msg.Err("Fail to crypt pass.")
} else {
a.Pass = cPass
@@ -83,7 +85,7 @@ func (a *Auth) SetPass(pass string) {
}
func (a *Auth) SetPassPhrase(passphrase string) {
- if cPassPhrase, err := crypto.Encrypt(machineID, passphrase); err != nil {
+ if cPassPhrase, err := crypto.Encrypt(crypto.MachineKey(), passphrase); err != nil {
msg.Err("Fail to crypt PassPhrase.")
} else {
a.PassPhrase = cPassPhrase
@@ -96,21 +98,21 @@ func (c *Configuration) GetAuth(repo string) transport.AuthMethod {
switch {
case auth == nil:
return nil
- case auth.UseSsh:
- pem, e := ioutil.ReadFile(auth.Path)
- if e != nil {
- msg.Die("Fail to open ssh key %s", e)
+ case auth.UseSSH:
+ pem, err := os.ReadFile(auth.Path)
+ if err != nil {
+ msg.Die("Fail to open ssh key %s", err)
}
var signer ssh.Signer
if auth.GetPassPhrase() != "" {
- signer, e = ssh.ParsePrivateKeyWithPassphrase(pem, []byte(auth.GetPassPhrase()))
+ signer, err = ssh.ParsePrivateKeyWithPassphrase(pem, []byte(auth.GetPassPhrase()))
} else {
- signer, e = ssh.ParsePrivateKey(pem)
+ signer, err = ssh.ParsePrivateKey(pem)
}
- if e != nil {
- panic(e)
+ if err != nil {
+ panic(err)
}
return &sshGit.PublicKeys{User: "git", Signer: signer}
@@ -163,7 +165,7 @@ func LoadConfiguration(cachePath string) (*Configuration, error) {
}
configFileName := filepath.Join(cachePath, consts.BossConfigFile)
- buffer, err := ioutil.ReadFile(configFileName)
+ buffer, err := os.ReadFile(configFileName)
if err != nil {
return makeDefault(cachePath), err
}
diff --git a/env/env.go b/pkg/env/env.go
similarity index 60%
rename from env/env.go
rename to pkg/env/env.go
index ea0cb39..6ece25e 100644
--- a/env/env.go
+++ b/pkg/env/env.go
@@ -1,51 +1,77 @@
package env
import (
+ //nolint:gosec // We are not using this for security purposes
"crypto/md5"
"encoding/hex"
"os"
"path/filepath"
"strings"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/msg"
"github.com/hashload/boss/utils/dcc32"
"github.com/mitchellh/go-homedir"
)
-var Global bool
-var Internal = false
-var GlobalConfiguration, _ = LoadConfiguration(GetBossHome())
+//nolint:gochecknoglobals //TODO: Refactor this
+var (
+ global bool
+ internal = false
+ globalConfiguration, _ = LoadConfiguration(GetBossHome())
+)
+
+func SetGlobal(b bool) {
+ global = b
+}
+
+func SetInternal(b bool) {
+ internal = b
+}
+
+func GetInternal() bool {
+ return internal
+}
+
+func GetGlobal() bool {
+ return global
+}
+
+func GlobalConfiguration() *Configuration {
+ return globalConfiguration
+}
func HashDelphiPath() string {
+ //nolint:gosec // We are not using this for security purposes
hasher := md5.New()
- hasher.Write([]byte(strings.ToLower(GlobalConfiguration.DelphiPath)))
+ hasher.Write([]byte(strings.ToLower(GlobalConfiguration().DelphiPath)))
hashString := hex.EncodeToString(hasher.Sum(nil))
- if Internal {
+ if internal {
hashString = consts.BossInternalDir + hashString
}
return hashString
}
func GetInternalGlobalDir() string {
- internalOld := Internal
- Internal = true
+ internalOld := internal
+ internal = true
result := filepath.Join(GetBossHome(), consts.FolderDependencies, HashDelphiPath())
- Internal = internalOld
+ internal = internalOld
return result
}
func getwd() string {
- if Global {
+ if global {
return filepath.Join(GetBossHome(), consts.FolderDependencies, HashDelphiPath())
- } else {
- if dir, err := os.Getwd(); err != nil {
- msg.Err("Error to get paths", err)
- return ""
- } else {
- return dir
- }
}
+
+ dir, err := os.Getwd()
+ if err != nil {
+ msg.Err("Error to get paths", err)
+ return ""
+ }
+
+ return dir
}
func GetCacheDir() string {
@@ -53,14 +79,13 @@ func GetCacheDir() string {
}
func GetBossHome() string {
-
homeDir := os.Getenv("BOSS_HOME")
if homeDir == "" {
- systemHome, e := homedir.Dir()
+ systemHome, err := homedir.Dir()
homeDir = systemHome
- if e != nil {
- msg.Err("Error to get cache paths", e)
+ if err != nil {
+ msg.Err("Error to get cache paths", err)
}
homeDir = filepath.FromSlash(homeDir)
@@ -95,8 +120,8 @@ func GetGlobalBinPath() string {
}
func GetDcc32Dir() string {
- if GlobalConfiguration.DelphiPath != "" {
- return GlobalConfiguration.DelphiPath
+ if GlobalConfiguration().DelphiPath != "" {
+ return GlobalConfiguration().DelphiPath
}
byCmd := dcc32.GetDcc32DirByCmd()
diff --git a/pkg/gc/garbage_collector.go b/pkg/gc/garbage_collector.go
new file mode 100644
index 0000000..f85097c
--- /dev/null
+++ b/pkg/gc/garbage_collector.go
@@ -0,0 +1,50 @@
+package gc
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
+)
+
+func RunGC(ignoreLastUpdate bool) error {
+ defer func() {
+ env.GlobalConfiguration().LastPurge = time.Now()
+ env.GlobalConfiguration().SaveConfiguration()
+ }()
+
+ path := filepath.Join(env.GetCacheDir(), "info")
+ return filepath.Walk(path, removeCache(ignoreLastUpdate))
+}
+
+func removeCache(ignoreLastUpdate bool) filepath.WalkFunc {
+ return func(_ string, info os.FileInfo, _ error) error {
+ if info == nil || info.IsDir() {
+ return nil
+ }
+
+ var extension = filepath.Ext(info.Name())
+ base := filepath.Base(info.Name())
+ var name = strings.TrimRight(base, extension)
+ repoInfo, err := models.RepoData(name)
+ if err != nil {
+ msg.Warn("Fail to parse repo info in GC: ", err)
+ return nil
+ }
+
+ lastUpdate := repoInfo.LastUpdate.AddDate(0, 0, env.GlobalConfiguration().PurgeTime)
+
+ if lastUpdate.Before(time.Now()) || ignoreLastUpdate {
+ _ = os.RemoveAll(filepath.Join(env.GetCacheDir(), repoInfo.Key))
+ _ = os.RemoveAll(filepath.Join(env.GetCacheDir(), fmt.Sprintf("%s_wt", repoInfo.Key)))
+ _ = os.RemoveAll(filepath.Join(env.GetCacheDir(), "info", info.Name()))
+ }
+
+ return nil
+ }
+}
diff --git a/pkg/git/git.go b/pkg/git/git.go
new file mode 100644
index 0000000..cffcfd2
--- /dev/null
+++ b/pkg/git/git.go
@@ -0,0 +1,138 @@
+package git
+
+import (
+ "path/filepath"
+
+ "github.com/go-git/go-billy/v5/osfs"
+ goGit "github.com/go-git/go-git/v5"
+ "github.com/go-git/go-git/v5/config"
+ "github.com/go-git/go-git/v5/plumbing"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
+)
+
+func CloneCache(dep models.Dependency) *goGit.Repository {
+ if env.GlobalConfiguration().GitEmbedded {
+ return CloneCacheEmbedded(dep)
+ }
+
+ return CloneCacheNative(dep)
+}
+
+func UpdateCache(dep models.Dependency) *goGit.Repository {
+ if env.GlobalConfiguration().GitEmbedded {
+ return UpdateCacheEmbedded(dep)
+ }
+
+ return UpdateCacheNative(dep)
+}
+
+func initSubmodules(dep models.Dependency, repository *goGit.Repository) {
+ worktree, err := repository.Worktree()
+ if err != nil {
+ msg.Err("... %s", err)
+ }
+ submodules, err := worktree.Submodules()
+ if err != nil {
+ msg.Err("On get submodules... %s", err)
+ }
+
+ err = submodules.Update(&goGit.SubmoduleUpdateOptions{
+ Init: true,
+ RecurseSubmodules: goGit.DefaultSubmoduleRecursionDepth,
+ Auth: env.GlobalConfiguration().GetAuth(dep.GetURLPrefix()),
+ })
+ if err != nil {
+ msg.Err("Failed on update submodules from dependency %s: %s", dep.Repository, err.Error())
+ }
+}
+
+func GetMain(repository *goGit.Repository) (*config.Branch, error) {
+ branch, err := repository.Branch("main")
+ if err != nil {
+ branch, err = repository.Branch("master")
+ }
+ return branch, err
+}
+
+func GetVersions(repository *goGit.Repository, dep models.Dependency) []*plumbing.Reference {
+ var result = make([]*plumbing.Reference, 0)
+
+ err := repository.Fetch(&goGit.FetchOptions{
+ Force: true,
+ Prune: true,
+ Auth: env.GlobalConfiguration().GetAuth(dep.GetURLPrefix()),
+ RefSpecs: []config.RefSpec{
+ "refs/*:refs/*",
+ "HEAD:refs/heads/HEAD",
+ },
+ })
+
+ if err != nil {
+ msg.Warn("Fail to fetch repository %s: %s", dep.Repository, err)
+ }
+
+ tags, err := repository.Tags()
+ if err != nil {
+ msg.Err("Fail to retrieve versions: %v", err)
+ } else {
+ err = tags.ForEach(func(reference *plumbing.Reference) error {
+ result = append(result, reference)
+ return nil
+ })
+ if err != nil {
+ msg.Err("Fail to retrieve versions: %v", err)
+ }
+ }
+
+ branches, err := repository.Branches()
+ if err != nil {
+ msg.Err("Fail to retrieve branches: %v", err)
+ } else {
+ err = branches.ForEach(func(reference *plumbing.Reference) error {
+ result = append(result, reference)
+ return nil
+ })
+ if err != nil {
+ msg.Err("Fail to retrieve branches: %v", err)
+ }
+ }
+
+ return result
+}
+
+func GetTagsShortName(repository *goGit.Repository) []string {
+ tags, _ := repository.Tags()
+ var result = []string{}
+ _ = tags.ForEach(func(reference *plumbing.Reference) error {
+ result = append(result, reference.Name().Short())
+ return nil
+ })
+ return result
+}
+
+func GetByTag(repository *goGit.Repository, shortName string) *plumbing.Reference {
+ tags, _ := repository.Tags()
+
+ for {
+ if reference, err := tags.Next(); err == nil {
+ if reference.Name().Short() == shortName {
+ return reference
+ }
+ } else {
+ return nil
+ }
+ }
+}
+
+func GetRepository(dep models.Dependency) *goGit.Repository {
+ cache := makeStorageCache(dep)
+ dir := osfs.New(filepath.Join(env.GetModulesDir(), dep.Name()))
+ repository, err := goGit.Open(cache, dir)
+ if err != nil {
+ msg.Err("Error on open repository %s: %s", dep.Repository, err)
+ }
+
+ return repository
+}
diff --git a/core/gitWrapper/git_embedded.go b/pkg/git/git_embedded.go
similarity index 64%
rename from core/gitWrapper/git_embedded.go
rename to pkg/git/git_embedded.go
index 4b1b650..31fc996 100644
--- a/core/gitWrapper/git_embedded.go
+++ b/pkg/git/git_embedded.go
@@ -1,37 +1,37 @@
-package gitWrapper
+package git
import (
- "fmt"
"os"
"path/filepath"
"github.com/go-git/go-billy/v5"
+ "github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-billy/v5/osfs"
"github.com/go-git/go-git/v5"
cache2 "github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/storage"
"github.com/go-git/go-git/v5/storage/filesystem"
- "github.com/hashload/boss/core/paths"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
+ "github.com/hashload/boss/pkg/paths"
)
func CloneCacheEmbedded(dep models.Dependency) *git.Repository {
msg.Info("Downloading dependency %s", dep.Repository)
storageCache := makeStorageCache(dep)
- wtFs := makeWtFileSystem(dep)
+ worktreeFileSystem := createWorktreeFs(dep)
url := dep.GetURL()
- auth := env.GlobalConfiguration.GetAuth(dep.GetURLPrefix())
+ auth := env.GlobalConfiguration().GetAuth(dep.GetURLPrefix())
- repository, e := git.Clone(storageCache, wtFs, &git.CloneOptions{
+ repository, err := git.Clone(storageCache, worktreeFileSystem, &git.CloneOptions{
URL: url,
Tags: git.AllTags,
Auth: auth,
})
- if e != nil {
- _ = os.RemoveAll(filepath.Join(env.GetCacheDir(), dep.GetHashName()))
- msg.Die("Error to get repository of %s: %s", dep.Repository, e)
+ if err != nil {
+ _ = os.RemoveAll(filepath.Join(env.GetCacheDir(), dep.HashName()))
+ msg.Die("Error to get repository of %s: %s", dep.Repository, err)
}
initSubmodules(dep, repository)
return repository
@@ -39,7 +39,7 @@ func CloneCacheEmbedded(dep models.Dependency) *git.Repository {
func UpdateCacheEmbedded(dep models.Dependency) *git.Repository {
storageCache := makeStorageCache(dep)
- wtFs := makeWtFileSystem(dep)
+ wtFs := createWorktreeFs(dep)
repository, err := git.Open(storageCache, wtFs)
if err != nil {
@@ -54,7 +54,7 @@ func UpdateCacheEmbedded(dep models.Dependency) *git.Repository {
err = repository.Fetch(&git.FetchOptions{
Force: true,
- Auth: env.GlobalConfiguration.GetAuth(dep.GetURLPrefix())})
+ Auth: env.GlobalConfiguration().GetAuth(dep.GetURLPrefix())})
if err != nil && err.Error() != "already up-to-date" {
msg.Debug("Error to fetch repository of %s: %s", dep.Repository, err)
}
@@ -63,29 +63,29 @@ func UpdateCacheEmbedded(dep models.Dependency) *git.Repository {
}
func refreshCopy(dep models.Dependency) *git.Repository {
- dir := filepath.Join(env.GetCacheDir(), dep.GetHashName())
- e := os.RemoveAll(dir)
- if e == nil {
+ dir := filepath.Join(env.GetCacheDir(), dep.HashName())
+ err := os.RemoveAll(dir)
+ if err == nil {
return CloneCacheEmbedded(dep)
- } else {
- msg.Err("Error on retry get refresh copy: %s", e)
}
+
+ msg.Err("Error on retry get refresh copy: %s", err)
+
return nil
}
func makeStorageCache(dep models.Dependency) storage.Storer {
paths.EnsureCacheDir(dep)
- dir := filepath.Join(env.GetCacheDir(), dep.GetHashName())
+ dir := filepath.Join(env.GetCacheDir(), dep.HashName())
fs := osfs.New(dir)
newStorage := filesystem.NewStorage(fs, cache2.NewObjectLRUDefault())
return newStorage
}
-func makeWtFileSystem(dep models.Dependency) billy.Filesystem {
+func createWorktreeFs(dep models.Dependency) billy.Filesystem {
paths.EnsureCacheDir(dep)
- dir := filepath.Join(env.GetCacheDir(), fmt.Sprintf("%s_wt", dep.GetHashName()))
- fs := osfs.New(dir)
+ fs := memfs.New()
return fs
}
diff --git a/core/gitWrapper/git_native.go b/pkg/git/git_native.go
similarity index 76%
rename from core/gitWrapper/git_native.go
rename to pkg/git/git_native.go
index a35f438..e28a851 100644
--- a/core/gitWrapper/git_native.go
+++ b/pkg/git/git_native.go
@@ -1,18 +1,17 @@
-package gitWrapper
+package git
import (
"fmt"
"io"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
git2 "github.com/go-git/go-git/v5"
- "github.com/hashload/boss/core/paths"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
+ "github.com/hashload/boss/pkg/paths"
"github.com/hashload/boss/utils"
)
@@ -26,7 +25,7 @@ func checkHasGitClient() {
func CloneCacheNative(dep models.Dependency) *git2.Repository {
msg.Info("Downloading dependency %s", dep.Repository)
- getWrapperClone(dep)
+ doClone(dep)
return GetRepository(dep)
}
@@ -35,13 +34,13 @@ func UpdateCacheNative(dep models.Dependency) *git2.Repository {
return GetRepository(dep)
}
-func getWrapperClone(dep models.Dependency) {
+func doClone(dep models.Dependency) {
checkHasGitClient()
paths.EnsureCacheDir(dep)
- dirModule := filepath.Join(env.GetModulesDir(), dep.GetName())
- dir := "--separate-git-dir=" + filepath.Join(env.GetCacheDir(), dep.GetHashName())
+ dirModule := filepath.Join(env.GetModulesDir(), dep.Name())
+ dir := "--separate-git-dir=" + filepath.Join(env.GetCacheDir(), dep.HashName())
err := os.RemoveAll(dirModule)
if !os.IsNotExist(err) {
@@ -54,28 +53,27 @@ func getWrapperClone(dep models.Dependency) {
cmd := exec.Command("git", "clone", dir, dep.GetURL(), dirModule)
- if err := runCommand(cmd); err != nil {
+ if err = runCommand(cmd); err != nil {
msg.Die(err.Error())
}
initSubmodulesNative(dep)
_ = os.Remove(filepath.Join(dirModule, ".git"))
-
}
func writeDotGitFile(dep models.Dependency) {
- mask := fmt.Sprintf("gitdir: %s\n", filepath.Join(env.GetCacheDir(), dep.GetHashName()))
- path := filepath.Join(env.GetModulesDir(), dep.GetName(), ".git")
- _ = ioutil.WriteFile(path, []byte(mask), os.ModePerm)
+ mask := fmt.Sprintf("gitdir: %s\n", filepath.Join(env.GetCacheDir(), dep.HashName()))
+ path := filepath.Join(env.GetModulesDir(), dep.Name(), ".git")
+ _ = os.WriteFile(path, []byte(mask), 0600)
}
func getWrapperFetch(dep models.Dependency) {
checkHasGitClient()
- dirModule := filepath.Join(env.GetModulesDir(), dep.GetName())
+ dirModule := filepath.Join(env.GetModulesDir(), dep.Name())
if _, err := os.Stat(dirModule); os.IsNotExist(err) {
- err := os.MkdirAll(dirModule, os.ModePerm)
+ err = os.MkdirAll(dirModule, 0600)
utils.HandleError(err)
}
@@ -99,7 +97,7 @@ func getWrapperFetch(dep models.Dependency) {
}
func initSubmodulesNative(dep models.Dependency) {
- dirModule := filepath.Join(env.GetModulesDir(), dep.GetName())
+ dirModule := filepath.Join(env.GetModulesDir(), dep.Name())
cmd := exec.Command("git", "submodule", "update", "--init", "--recursive")
cmd.Dir = dirModule
@@ -130,7 +128,7 @@ func newWriter(errorWritter bool) *writer {
return &writer{errorWritter: errorWritter}
}
-func (writer *writer) Write(p []byte) (n int, err error) {
+func (writer *writer) Write(p []byte) (int, error) {
var str = " " + string(p)
if writer.errorWritter {
msg.Err(str)
diff --git a/pkg/installer/core.go b/pkg/installer/core.go
new file mode 100644
index 0000000..c285b28
--- /dev/null
+++ b/pkg/installer/core.go
@@ -0,0 +1,288 @@
+package installer
+
+import (
+ "errors"
+ "os"
+ "path/filepath"
+ "strings"
+
+ goGit "github.com/go-git/go-git/v5"
+ "github.com/go-git/go-git/v5/plumbing"
+ "github.com/hashload/boss/pkg/compiler"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/git"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
+ "github.com/hashload/boss/pkg/paths"
+ "github.com/hashload/boss/utils"
+ "github.com/hashload/boss/utils/librarypath"
+ "github.com/masterminds/semver"
+)
+
+type installContext struct {
+ rootLocked *models.PackageLock
+ root *models.Package
+ processed []string
+ useLockedVersion bool
+}
+
+func newInstallContext(pkg *models.Package, useLockedVersion bool) *installContext {
+ return &installContext{
+ rootLocked: &pkg.Lock,
+ root: pkg,
+ useLockedVersion: useLockedVersion,
+ processed: consts.DefaultPaths(),
+ }
+}
+
+func DoInstall(pkg *models.Package, lockedVersion bool) {
+ msg.Info("Installing modules in project path")
+
+ installContext := newInstallContext(pkg, lockedVersion)
+
+ dependencies := installContext.ensureDependencies(pkg)
+
+ paths.EnsureCleanModulesDir(dependencies, pkg.Lock)
+
+ pkg.Lock.CleanRemoved(dependencies)
+ pkg.Save()
+
+ librarypath.UpdateLibraryPath(pkg)
+ msg.Info("Compiling units")
+ compiler.Build(pkg)
+ pkg.Save()
+ msg.Info("Success!")
+}
+
+func (ic *installContext) ensureDependencies(pkg *models.Package) []models.Dependency {
+ if pkg.Dependencies == nil {
+ return []models.Dependency{}
+ }
+ deps := pkg.GetParsedDependencies()
+
+ ic.ensureModules(pkg, deps)
+
+ deps = append(deps, ic.processOthers()...)
+
+ return deps
+}
+
+func (ic *installContext) processOthers() []models.Dependency {
+ infos, err := os.ReadDir(env.GetModulesDir())
+ var lenProcessedInitial = len(ic.processed)
+ var result []models.Dependency
+ if err != nil {
+ msg.Err("Error on try load dir of modules: %s", err)
+ }
+
+ for _, info := range infos {
+ if !info.IsDir() {
+ continue
+ }
+
+ if utils.Contains(ic.processed, info.Name()) {
+ continue
+ }
+
+ ic.processed = append(ic.processed, info.Name())
+
+ msg.Info("Processing module %s", info.Name())
+
+ fileName := filepath.Join(env.GetModulesDir(), info.Name(), consts.FilePackage)
+
+ _, err := os.Stat(fileName)
+ if os.IsNotExist(err) {
+ msg.Warn(" boss.json not exists in %s", info.Name())
+ }
+
+ if packageOther, err := models.LoadPackageOther(fileName); err != nil {
+ if os.IsNotExist(err) {
+ continue
+ }
+ msg.Err(" Error on try load package %s: %s", fileName, err)
+ } else {
+ result = append(result, ic.ensureDependencies(packageOther)...)
+ }
+ }
+ if lenProcessedInitial > len(ic.processed) {
+ result = append(result, ic.processOthers()...)
+ }
+
+ return result
+}
+
+func (ic *installContext) ensureModules(pkg *models.Package, deps []models.Dependency) {
+ for _, dep := range deps {
+ msg.Info("Processing dependency %s", dep.Name())
+ msg.Info("Processing dependency %s", dep.Name())
+
+ if ic.shouldSkipDependency(dep) {
+ msg.Info("Dependency %s already installed", dep.Name())
+ msg.Info("Dependency %s already installed", dep.Name())
+ continue
+ }
+
+ GetDependency(dep)
+ repository := git.GetRepository(dep)
+ referenceName := ic.getReferenceName(pkg, dep, repository)
+
+ wt, err := repository.Worktree()
+ if err != nil {
+ msg.Die(" Error on get worktree from repository %s\n%s", dep.Repository, err)
+ }
+
+ status, err := wt.Status()
+ if err != nil {
+ msg.Die(" Error on get status from worktree %s\n%s", dep.Repository, err)
+ }
+
+ head, er := repository.Head()
+ if er != nil {
+ msg.Die(" Error on get head from repository %s\n%s", dep.Repository, er)
+ }
+
+ currentRef := head.Name()
+ if !ic.rootLocked.NeedUpdate(dep, referenceName.Short()) && status.IsClean() && referenceName == currentRef {
+ msg.Info(" %s already updated", dep.Name())
+ continue
+ }
+
+ ic.checkoutAndUpdate(dep, repository, referenceName)
+ }
+}
+
+func (ic *installContext) shouldSkipDependency(dep models.Dependency) bool {
+ if !ic.useLockedVersion {
+ return false
+ }
+
+ installed, exists := ic.rootLocked.Installed[strings.ToLower(dep.GetURL())]
+ if !exists {
+ return false
+ }
+
+ depv := strings.NewReplacer("^", "", "~", "").Replace(dep.GetVersion())
+ requiredVersion, err := semver.NewVersion(depv)
+ if err != nil {
+ msg.Warn(" Error '%s' on get required version. Updating...", err)
+ return false
+ }
+
+ installedVersion, err := semver.NewVersion(installed.Version)
+ if err != nil {
+ msg.Warn(" Error '%s' on get installed version. Updating...", err)
+ return false
+ }
+
+ return !installedVersion.LessThan(requiredVersion)
+}
+
+func (ic *installContext) getReferenceName(
+ pkg *models.Package,
+ dep models.Dependency,
+ repository *goGit.Repository) plumbing.ReferenceName {
+ bestMatch := ic.getVersion(dep, repository)
+ var referenceName plumbing.ReferenceName
+
+ if bestMatch == nil {
+ if mainBranchReference, err := git.GetMain(repository); err == nil {
+ return plumbing.NewBranchReferenceName(mainBranchReference.Name)
+ }
+ }
+
+ referenceName = bestMatch.Name()
+ if dep.GetVersion() == consts.MinimalDependencyVersion {
+ pkg.Dependencies[dep.Repository] = "^" + referenceName.Short()
+ }
+
+ return referenceName
+}
+
+func (ic *installContext) checkoutAndUpdate(
+ dep models.Dependency,
+ repository *goGit.Repository,
+ referenceName plumbing.ReferenceName) {
+ worktree, err := repository.Worktree()
+ if err != nil {
+ msg.Die(" Error on get worktree from repository %s\n%s", dep.Repository, err)
+ }
+
+ err = worktree.Checkout(&goGit.CheckoutOptions{
+ Force: true,
+ Branch: referenceName,
+ })
+
+ ic.rootLocked.Add(dep, referenceName.Short())
+ ic.rootLocked.Add(dep, referenceName.Short())
+
+ if err != nil {
+ msg.Die(" Error on switch to needed version from dependency %s\n%s", dep.Repository, err)
+ }
+
+ err = worktree.Pull(&goGit.PullOptions{
+ Force: true,
+ Auth: env.GlobalConfiguration().GetAuth(dep.GetURLPrefix()),
+ })
+
+ if err != nil && !errors.Is(err, goGit.NoErrAlreadyUpToDate) {
+ msg.Warn(" Error on pull from dependency %s\n%s", dep.Repository, err)
+ }
+}
+
+func (ic *installContext) getVersion(
+ dep models.Dependency,
+ repository *goGit.Repository,
+) *plumbing.Reference {
+ if ic.useLockedVersion {
+ lockedDependency := ic.rootLocked.GetInstalled(dep)
+
+ if tag := git.GetByTag(repository, lockedDependency.Version); tag != nil &&
+ lockedDependency.Version != dep.GetVersion() {
+ return tag
+ }
+ }
+
+ versions := git.GetVersions(repository, dep)
+ constraints, err := semver.NewConstraint(dep.GetVersion())
+ if err != nil {
+ for _, version := range versions {
+ if version.Name().Short() == dep.GetVersion() {
+ return version
+ }
+ }
+
+ return nil
+ }
+
+ return ic.getVersionSemantic(
+ versions,
+ constraints)
+}
+
+func (ic *installContext) getVersionSemantic(
+ versions []*plumbing.Reference,
+ contraint *semver.Constraints) *plumbing.Reference {
+ var bestVersion *semver.Version
+ var bestReference *plumbing.Reference
+
+ for _, version := range versions {
+ short := version.Name().Short()
+ newVersion, err := semver.NewVersion(short)
+ if err != nil {
+ continue
+ }
+ if contraint.Check(newVersion) {
+ if bestVersion != nil && newVersion.GreaterThan(bestVersion) {
+ bestVersion = newVersion
+ bestReference = version
+ }
+
+ if bestVersion == nil {
+ bestVersion = newVersion
+ bestReference = version
+ }
+ }
+ }
+ return bestReference
+}
diff --git a/core/installer/global_unix.go b/pkg/installer/global_unix.go
similarity index 63%
rename from core/installer/global_unix.go
rename to pkg/installer/global_unix.go
index 1e83282..5d5ad92 100644
--- a/core/installer/global_unix.go
+++ b/pkg/installer/global_unix.go
@@ -3,12 +3,12 @@
package installer
import (
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
)
-func GlobalInstall(args []string, pkg *models.Package, lockedVersion bool, noSave bool) {
- EnsureDependencyOfArgs(pkg, args)
+func GlobalInstall(args []string, pkg *models.Package, lockedVersion bool, _ /* nosave */ bool) {
+ EnsureDependency(pkg, args)
DoInstall(pkg, lockedVersion)
msg.Err("Cannot install global packages on this platform, only build and install local")
}
diff --git a/core/installer/global_win.go b/pkg/installer/global_win.go
similarity index 84%
rename from core/installer/global_win.go
rename to pkg/installer/global_win.go
index 402f338..33ad1d4 100644
--- a/core/installer/global_win.go
+++ b/pkg/installer/global_win.go
@@ -6,33 +6,25 @@ import (
"io/fs"
"os/exec"
"path/filepath"
+ "slices"
"strings"
- "github.com/hashload/boss/consts"
- bossRegistry "github.com/hashload/boss/core/registry"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
+ bossRegistry "github.com/hashload/boss/pkg/registry"
"github.com/hashload/boss/utils"
"golang.org/x/sys/windows/registry"
)
func GlobalInstall(args []string, pkg *models.Package, lockedVersion bool, noSave bool) {
// TODO noSave
- EnsureDependencyOfArgs(pkg, args)
+ EnsureDependency(pkg, args)
DoInstall(pkg, lockedVersion)
doInstallPackages()
}
-func find(array []string, value string) int {
- for key, item := range array {
- if item == value {
- return key
- }
- }
- return -1
-}
-
func addPathBpl(ideVersion string) {
idePath, err := registry.OpenKey(registry.CURRENT_USER, consts.RegistryBasePath+ideVersion+`\Environment Variables`,
registry.ALL_ACCESS)
@@ -90,7 +82,7 @@ func doInstallPackages() {
return nil
}
- if find(keys, path) == -1 {
+ if !slices.Contains(keys, path) {
utils.HandleError(knowPackages.SetStringValue(path, path))
}
existingBpls = append(existingBpls, path)
@@ -99,7 +91,7 @@ func doInstallPackages() {
})
for _, key := range keys {
- if find(existingBpls, key) != -1 {
+ if slices.Contains(existingBpls, key) {
continue
}
diff --git a/pkg/installer/installer.go b/pkg/installer/installer.go
new file mode 100644
index 0000000..bfb18cf
--- /dev/null
+++ b/pkg/installer/installer.go
@@ -0,0 +1,47 @@
+package installer
+
+import (
+ "os"
+
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
+)
+
+func InstallModules(args []string, lockedVersion bool, noSave bool) {
+ pkg, err := models.LoadPackage(env.GetGlobal())
+ if err != nil {
+ if os.IsNotExist(err) {
+ msg.Die("boss.json not exists in " + env.GetCurrentDir())
+ } else {
+ msg.Die("Fail on open dependencies file: %s", err)
+ }
+ }
+
+ if env.GetGlobal() {
+ GlobalInstall(args, pkg, lockedVersion, noSave)
+ } else {
+ LocalInstall(args, pkg, lockedVersion, noSave)
+ }
+}
+
+func UninstallModules(args []string, noSave bool) {
+ pkg, err := models.LoadPackage(false)
+ if err != nil && !os.IsNotExist(err) {
+ msg.Die("Fail on open dependencies file: %s", err)
+ }
+
+ if pkg == nil {
+ return
+ }
+
+ for _, arg := range args {
+ dependencyRepository := ParseDependency(arg)
+ pkg.UninstallDependency(dependencyRepository)
+ }
+
+ pkg.Save()
+
+ // TODO implement remove without reinstall process
+ InstallModules([]string{}, false, noSave)
+}
diff --git a/core/installer/local.go b/pkg/installer/local.go
similarity index 67%
rename from core/installer/local.go
rename to pkg/installer/local.go
index 3ec0cc7..9f8020b 100644
--- a/core/installer/local.go
+++ b/pkg/installer/local.go
@@ -1,13 +1,13 @@
package installer
import (
- "github.com/hashload/boss/models"
+ "github.com/hashload/boss/pkg/models"
"github.com/hashload/boss/utils/dcp"
)
-func LocalInstall(args []string, pkg *models.Package, lockedVersion bool, noSave bool) {
+func LocalInstall(args []string, pkg *models.Package, lockedVersion bool, _ /* noSave */ bool) {
// TODO noSave
- EnsureDependencyOfArgs(pkg, args)
+ EnsureDependency(pkg, args)
DoInstall(pkg, lockedVersion)
dcp.InjectDpcs(pkg, pkg.Lock)
}
diff --git a/core/installer/utils.go b/pkg/installer/utils.go
similarity index 57%
rename from core/installer/utils.go
rename to pkg/installer/utils.go
index d6e93fc..2e54d43 100644
--- a/core/installer/utils.go
+++ b/pkg/installer/utils.go
@@ -4,15 +4,18 @@ import (
"regexp"
"strings"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/models"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/models"
)
-func EnsureDependencyOfArgs(pkg *models.Package, args []string) {
- for e := range args {
- dependency := ParseDependency(args[e])
+//nolint:lll // This regex is too long and it's better to keep it like this
+const urlVersionMatcher = `(?m)^(?:http[s]?:\/\/|git@)?(?P[\w\.\-\/:]+?)(?:[@:](?P[\^~]?(?:\d+\.)?(?:\d+\.)?(?:\*|\d+|[\w\-]+)))?$`
- re := regexp.MustCompile(`(?U)(?m)^(?:http[s]{0,1}://)?(?P.*)(?::(?P[\^~]?(?:\d+\.)?(?:\d+\.)?(?:\*|\d+)))?$`)
+func EnsureDependency(pkg *models.Package, args []string) {
+ for _, dependency := range args {
+ dependency = ParseDependency(dependency)
+
+ re := regexp.MustCompile(urlVersionMatcher)
match := make(map[string]string)
split := re.FindStringSubmatch(dependency)
@@ -23,7 +26,7 @@ func EnsureDependencyOfArgs(pkg *models.Package, args []string) {
}
var ver string
var dep string
- dep = match["host"]
+ dep = match["url"]
if len(match["version"]) == 0 {
ver = consts.MinimalDependencyVersion
} else {
@@ -40,11 +43,11 @@ func EnsureDependencyOfArgs(pkg *models.Package, args []string) {
func ParseDependency(dependencyName string) string {
re := regexp.MustCompile(`(?m)(([?^/]).*)`)
- if !re.Match([]byte(dependencyName)) {
+ if !re.MatchString(dependencyName) {
return "github.com/hashload/" + dependencyName
}
re = regexp.MustCompile(`(?m)([?^/].*)(([?^/]).*)`)
- if !re.Match([]byte(dependencyName)) {
+ if !re.MatchString(dependencyName) {
return "github.com/" + dependencyName
}
return dependencyName
diff --git a/pkg/installer/vsc.go b/pkg/installer/vsc.go
new file mode 100644
index 0000000..4a20148
--- /dev/null
+++ b/pkg/installer/vsc.go
@@ -0,0 +1,52 @@
+package installer
+
+import (
+ "os"
+ "path/filepath"
+
+ goGit "github.com/go-git/go-git/v5"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/git"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
+ "github.com/hashload/boss/utils"
+)
+
+//nolint:gochecknoglobals //TODO: Refactor this
+var updatedDependencies []string
+
+func GetDependency(dep models.Dependency) {
+ if utils.Contains(updatedDependencies, dep.HashName()) {
+ msg.Debug("Using cached of %s", dep.Name())
+ return
+ }
+ msg.Info("Updating cache of dependency %s", dep.Name())
+
+ updatedDependencies = append(updatedDependencies, dep.HashName())
+ var repository *goGit.Repository
+ if hasCache(dep) {
+ repository = git.UpdateCache(dep)
+ } else {
+ _ = os.RemoveAll(filepath.Join(env.GetCacheDir(), dep.HashName()))
+ repository = git.CloneCache(dep)
+ }
+ tagsShortNames := git.GetTagsShortName(repository)
+ models.CacheRepositoryDetails(dep, tagsShortNames)
+}
+
+func hasCache(dep models.Dependency) bool {
+ dir := filepath.Join(env.GetCacheDir(), dep.HashName())
+ info, err := os.Stat(dir)
+ if err == nil {
+ return true
+ }
+ if os.IsNotExist(err) {
+ return false
+ }
+ if !info.IsDir() {
+ _ = os.RemoveAll(dir)
+ return false
+ }
+ _, err = os.Stat(dir)
+ return !os.IsNotExist(err)
+}
diff --git a/pkg/models/cacheInfo.go b/pkg/models/cacheInfo.go
new file mode 100644
index 0000000..2a64193
--- /dev/null
+++ b/pkg/models/cacheInfo.go
@@ -0,0 +1,67 @@
+package models
+
+import (
+ "encoding/json"
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/msg"
+)
+
+type RepoInfo struct {
+ Key string `json:"key"`
+ Name string `json:"name"`
+ LastUpdate time.Time `json:"last_update"`
+ Versions []string `json:"versions"`
+}
+
+func CacheRepositoryDetails(dep Dependency, versions []string) {
+ location := env.GetCacheDir()
+ data := &RepoInfo{
+ Key: dep.HashName(),
+ Name: dep.Name(),
+ Versions: versions,
+ LastUpdate: time.Now(),
+ }
+
+ buff, err := json.Marshal(data)
+ if err != nil {
+ msg.Err(err.Error())
+ }
+
+ infoPath := filepath.Join(location, "info")
+ err = os.MkdirAll(infoPath, 0755)
+ if err != nil {
+ msg.Err(err.Error())
+ }
+
+ jsonFilePath := filepath.Join(infoPath, data.Key+".json")
+ jsonFile, err := os.Create(jsonFilePath)
+ if err != nil {
+ msg.Err(err.Error())
+ return
+ }
+ defer jsonFile.Close()
+
+ _, err = jsonFile.Write(buff)
+ if err != nil {
+ msg.Err(err.Error())
+ }
+}
+
+func RepoData(key string) (*RepoInfo, error) {
+ location := env.GetCacheDir()
+ cacheRepository := &RepoInfo{}
+ cacheInfoPath := filepath.Join(location, "info", key+".json")
+ cacheInfoData, err := os.ReadFile(cacheInfoPath)
+ if err != nil {
+ return &RepoInfo{}, err
+ }
+ err = json.Unmarshal(cacheInfoData, cacheRepository)
+ if err != nil {
+ return &RepoInfo{}, err
+ }
+ return cacheRepository, nil
+}
diff --git a/models/dep.go b/pkg/models/dependency.go
similarity index 73%
rename from models/dep.go
rename to pkg/models/dependency.go
index 9ecdb9e..27cc228 100644
--- a/models/dep.go
+++ b/pkg/models/dependency.go
@@ -1,15 +1,16 @@
package models
import (
+ //nolint:gosec // We are not using this for security purposes
"crypto/md5"
"encoding/hex"
"io"
"regexp"
"strings"
- "github.com/hashload/boss/env"
+ "github.com/hashload/boss/pkg/env"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/msg"
)
type Dependency struct {
@@ -18,7 +19,8 @@ type Dependency struct {
UseSSH bool
}
-func (p *Dependency) GetHashName() string {
+func (p *Dependency) HashName() string {
+ //nolint:gosec // We are not using this for security purposes
hash := md5.New()
if _, err := io.WriteString(hash, p.Repository); err != nil {
msg.Warn("Failed on write dependency hash")
@@ -30,7 +32,7 @@ func (p *Dependency) GetVersion() string {
return p.version
}
-func (p *Dependency) makeSshUrl() string {
+func (p *Dependency) sshURL() string {
if strings.Contains(p.Repository, "@") {
return p.Repository
}
@@ -42,24 +44,24 @@ func (p *Dependency) makeSshUrl() string {
}
func (p *Dependency) GetURLPrefix() string {
- var re = regexp.MustCompile(`^[^/^:]+`)
- return re.FindString(p.Repository)
+ urlPrefixPattern := regexp.MustCompile(`^[^/^:]+`)
+ return urlPrefixPattern.FindString(p.Repository)
}
func (p *Dependency) GetURL() string {
prefix := p.GetURLPrefix()
- auth := env.GlobalConfiguration.Auth[prefix]
+ auth := env.GlobalConfiguration().Auth[prefix]
if auth != nil {
- if auth.UseSsh {
- return p.makeSshUrl()
+ if auth.UseSSH {
+ return p.sshURL()
}
}
- var hasHttp = regexp.MustCompile(`(?m)^https?:\/\/`)
- if hasHttp.MatchString(p.Repository) {
+ var hasHTTPS = regexp.MustCompile(`(?m)^https?:\/\/`)
+ if hasHTTPS.MatchString(p.Repository) {
return p.Repository
- } else {
- return "https://" + p.Repository
}
+
+ return "https://" + p.Repository
}
var re = regexp.MustCompile(`(?m)^(.|)(\d+)\.(\d+)$`)
@@ -86,10 +88,10 @@ func ParseDependency(repo string, info string) Dependency {
return dependency
}
-func GetDependencies(deps map[string]interface{}) []Dependency {
+func GetDependencies(deps map[string]string) []Dependency {
dependencies := make([]Dependency, 0)
for repo, info := range deps {
- dependencies = append(dependencies, ParseDependency(repo, info.(string)))
+ dependencies = append(dependencies, ParseDependency(repo, info))
}
return dependencies
}
@@ -97,12 +99,12 @@ func GetDependencies(deps map[string]interface{}) []Dependency {
func GetDependenciesNames(deps []Dependency) []string {
var dependencies []string
for _, info := range deps {
- dependencies = append(dependencies, info.GetName())
+ dependencies = append(dependencies, info.Name())
}
return dependencies
}
-func (p *Dependency) GetName() string {
+func (p *Dependency) Name() string {
var re = regexp.MustCompile(`[^/]+(:?/$|$)`)
return re.FindString(p.Repository)
}
diff --git a/models/lock.go b/pkg/models/lock.go
similarity index 68%
rename from models/lock.go
rename to pkg/models/lock.go
index 68d6966..2e73f25 100644
--- a/models/lock.go
+++ b/pkg/models/lock.go
@@ -1,20 +1,20 @@
package models
import (
+
+ //nolint:gosec // We are not using this for security purposes
"crypto/md5"
"encoding/hex"
"encoding/json"
"io"
- "io/ioutil"
- "log"
"os"
"path/filepath"
"strings"
"time"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/msg"
"github.com/hashload/boss/utils"
"github.com/masterminds/semver"
)
@@ -31,8 +31,8 @@ type LockedDependency struct {
Version string `json:"version"`
Hash string `json:"hash"`
Artifacts DependencyArtifacts `json:"artifacts"`
- Failed bool `json:"failed"`
- Changed bool `json:"changed"`
+ Failed bool `json:"-"`
+ Changed bool `json:"-"`
}
type PackageLock struct {
@@ -46,7 +46,7 @@ func removeOld(parentPackage *Package) {
var oldFileName = filepath.Join(filepath.Dir(parentPackage.fileName), consts.FilePackageLockOld)
var newFileName = filepath.Join(filepath.Dir(parentPackage.fileName), consts.FilePackageLock)
if _, err := os.Stat(oldFileName); err == nil {
- err := os.Rename(oldFileName, newFileName)
+ err = os.Rename(oldFileName, newFileName)
utils.HandleError(err)
}
}
@@ -54,7 +54,9 @@ func removeOld(parentPackage *Package) {
func LoadPackageLock(parentPackage *Package) PackageLock {
removeOld(parentPackage)
packageLockPath := filepath.Join(filepath.Dir(parentPackage.fileName), consts.FilePackageLock)
- if fileBytes, err := ioutil.ReadFile(packageLockPath); err != nil {
+ fileBytes, err := os.ReadFile(packageLockPath)
+ if err != nil {
+ //nolint:gosec // We are not using this for security purposes
hash := md5.New()
if _, err := io.WriteString(hash, parentPackage.Name); err != nil {
msg.Warn("Failed on write machine id to hash")
@@ -67,38 +69,37 @@ func LoadPackageLock(parentPackage *Package) PackageLock {
Installed: map[string]LockedDependency{},
}
- } else {
- lockfile := PackageLock{
- fileName: packageLockPath,
- Updated: time.Now(),
- Installed: map[string]LockedDependency{},
- }
+ }
- if err := json.Unmarshal(fileBytes, &lockfile); err != nil {
- utils.HandleError(err)
- }
- return lockfile
+ lockfile := PackageLock{
+ fileName: packageLockPath,
+ Updated: time.Now(),
+ Installed: map[string]LockedDependency{},
+ }
+
+ if err := json.Unmarshal(fileBytes, &lockfile); err != nil {
+ utils.HandleError(err)
}
+ return lockfile
}
-func (p PackageLock) Save() {
+func (p *PackageLock) Save() {
marshal, err := json.MarshalIndent(&p, "", "\t")
if err != nil {
- log.Fatalf("error %v", err)
+ msg.Die("error %v", err)
}
- _ = ioutil.WriteFile(p.fileName, marshal, 0664)
+ _ = os.WriteFile(p.fileName, marshal, 0600)
}
-func (p PackageLock) AddInstalled(dep Dependency, version string) {
-
- dependencyDir := filepath.Join(env.GetCurrentDir(), consts.FolderDependencies, dep.GetName())
+func (p *PackageLock) Add(dep Dependency, version string) {
+ dependencyDir := filepath.Join(env.GetCurrentDir(), consts.FolderDependencies, dep.Name())
hash := utils.HashDir(dependencyDir)
if locked, ok := p.Installed[strings.ToLower(dep.Repository)]; !ok {
p.Installed[strings.ToLower(dep.Repository)] = LockedDependency{
- Name: dep.GetName(),
+ Name: dep.Name(),
Version: version,
Changed: true,
Hash: hash,
@@ -116,12 +117,12 @@ func (p PackageLock) AddInstalled(dep Dependency, version string) {
}
}
-func (p Dependency) internalNeedUpdate(lockedDependency LockedDependency, version string) bool {
+func (p *Dependency) internalNeedUpdate(lockedDependency LockedDependency, version string) bool {
if lockedDependency.Failed {
return true
}
- dependencyDir := filepath.Join(env.GetCurrentDir(), consts.FolderDependencies, p.GetName())
+ dependencyDir := filepath.Join(env.GetCurrentDir(), consts.FolderDependencies, p.Name())
if _, err := os.Stat(dependencyDir); os.IsNotExist(err) {
return true
@@ -142,7 +143,6 @@ func (p Dependency) internalNeedUpdate(lockedDependency LockedDependency, versio
return version != lockedDependency.Version
}
return parsedNewVersion.GreaterThan(parsedVersion)
-
}
func (p *DependencyArtifacts) Clean() {
@@ -151,7 +151,7 @@ func (p *DependencyArtifacts) Clean() {
p.Dcp = []string{}
p.Dcu = []string{}
}
-func (p LockedDependency) checkArtifactsType(directory string, artifacts []string) bool {
+func (p *LockedDependency) checkArtifactsType(directory string, artifacts []string) bool {
for _, value := range artifacts {
bpl := filepath.Join(directory, value)
_, err := os.Stat(bpl)
@@ -162,7 +162,7 @@ func (p LockedDependency) checkArtifactsType(directory string, artifacts []strin
return true
}
-func (p LockedDependency) checkArtifacts(lock PackageLock) bool {
+func (p *LockedDependency) checkArtifacts(lock *PackageLock) bool {
baseModulesDir := filepath.Join(filepath.Dir(lock.fileName), consts.FolderDependencies)
if !p.checkArtifactsType(filepath.Join(baseModulesDir, consts.BplFolder), p.Artifacts.Bpl) {
@@ -184,38 +184,36 @@ func (p LockedDependency) checkArtifacts(lock PackageLock) bool {
return true
}
-func (p PackageLock) NeedUpdate(dep Dependency, version string) bool {
- if lockedDependency, ok := p.Installed[strings.ToLower(dep.Repository)]; !ok {
+func (p *PackageLock) NeedUpdate(dep Dependency, version string) bool {
+ lockedDependency, ok := p.Installed[strings.ToLower(dep.Repository)]
+ if !ok {
return true
- } else {
- needUpdate := dep.internalNeedUpdate(lockedDependency, version) || !lockedDependency.checkArtifacts(p)
- lockedDependency.Changed = needUpdate || lockedDependency.Changed
-
- if lockedDependency.Changed {
- lockedDependency.Failed = false
- lockedDependency.Artifacts.Bin = []string{}
- lockedDependency.Artifacts.Bpl = []string{}
- lockedDependency.Artifacts.Dcp = []string{}
- lockedDependency.Artifacts.Dcu = []string{}
- }
- p.Installed[strings.ToLower(dep.Repository)] = lockedDependency
- return needUpdate
}
+
+ needUpdate := dep.internalNeedUpdate(lockedDependency, version) || !lockedDependency.checkArtifacts(p)
+ lockedDependency.Changed = needUpdate || lockedDependency.Changed
+
+ if lockedDependency.Changed {
+ lockedDependency.Failed = false
+ }
+ p.Installed[strings.ToLower(dep.Repository)] = lockedDependency
+
+ return needUpdate
}
-func (p PackageLock) GetInstalled(dep Dependency) LockedDependency {
+func (p *PackageLock) GetInstalled(dep Dependency) LockedDependency {
return p.Installed[strings.ToLower(dep.Repository)]
}
-func (p PackageLock) SetInstalled(dep Dependency, locked LockedDependency) {
- dependencyDir := filepath.Join(env.GetCurrentDir(), consts.FolderDependencies, dep.GetName())
+func (p *PackageLock) SetInstalled(dep Dependency, locked LockedDependency) {
+ dependencyDir := filepath.Join(env.GetCurrentDir(), consts.FolderDependencies, dep.Name())
hash := utils.HashDir(dependencyDir)
locked.Hash = hash
p.Installed[strings.ToLower(dep.Repository)] = locked
}
-func (p PackageLock) CleanRemoved(deps []Dependency) {
+func (p *PackageLock) CleanRemoved(deps []Dependency) {
var repositories []string
for _, dep := range deps {
repositories = append(repositories, strings.ToLower(dep.Repository))
@@ -228,7 +226,7 @@ func (p PackageLock) CleanRemoved(deps []Dependency) {
}
}
-func (p PackageLock) GetArtifactList() []string {
+func (p *PackageLock) GetArtifactList() []string {
var result []string
for _, installed := range p.Installed {
@@ -237,7 +235,7 @@ func (p PackageLock) GetArtifactList() []string {
return result
}
-func (p LockedDependency) GetArtifacts() []string {
+func (p *LockedDependency) GetArtifacts() []string {
var result []string
result = append(result, p.Artifacts.Dcp...)
result = append(result, p.Artifacts.Dcu...)
diff --git a/pkg/models/package.go b/pkg/models/package.go
new file mode 100644
index 0000000..96244cd
--- /dev/null
+++ b/pkg/models/package.go
@@ -0,0 +1,112 @@
+package models
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/utils/parser"
+)
+
+type Package struct {
+ fileName string
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Version string `json:"version"`
+ Homepage string `json:"homepage"`
+ MainSrc string `json:"mainsrc"`
+ BrowsingPath string `json:"browsingpath"`
+ Projects []string `json:"projects"`
+ Scripts map[string]string `json:"scripts,omitempty"`
+ Dependencies map[string]string `json:"dependencies"`
+ Lock PackageLock `json:"-"`
+}
+
+func (p *Package) Save() []byte {
+ marshal, _ := parser.JSONMarshal(p, true)
+ _ = os.WriteFile(p.fileName, marshal, 0600)
+ p.Lock.Save()
+ return marshal
+}
+
+func (p *Package) AddDependency(dep string, ver string) {
+ for key := range p.Dependencies {
+ if strings.EqualFold(key, dep) {
+ p.Dependencies[key] = ver
+ return
+ }
+ }
+
+ p.Dependencies[dep] = ver
+}
+
+func (p *Package) AddProject(project string) {
+ p.Projects = append(p.Projects, project)
+}
+
+func (p *Package) GetParsedDependencies() []Dependency {
+ if p == nil || len(p.Dependencies) == 0 {
+ return []Dependency{}
+ }
+ return GetDependencies(p.Dependencies)
+}
+
+func (p *Package) UninstallDependency(dep string) {
+ if p.Dependencies != nil {
+ for key := range p.Dependencies {
+ if strings.EqualFold(key, dep) {
+ delete(p.Dependencies, key)
+ return
+ }
+ }
+ }
+}
+
+func getNew(file string) *Package {
+ res := new(Package)
+ res.fileName = file
+
+ res.Dependencies = make(map[string]string)
+ res.Projects = []string{}
+ res.Lock = LoadPackageLock(res)
+ return res
+}
+
+func LoadPackage(createNew bool) (*Package, error) {
+ fileBytes, err := os.ReadFile(env.GetBossFile())
+ if err != nil {
+ if createNew {
+ err = nil
+ }
+ return getNew(env.GetBossFile()), err
+ }
+ result := getNew(env.GetBossFile())
+
+ if err := json.Unmarshal(fileBytes, result); err != nil {
+ if os.IsNotExist(err) {
+ return nil, err
+ }
+
+ return nil, fmt.Errorf("error on unmarshal file %s: %w", env.GetBossFile(), err)
+ }
+ result.Lock = LoadPackageLock(result)
+ return result, nil
+}
+
+func LoadPackageOther(path string) (*Package, error) {
+ fileBytes, err := os.ReadFile(path)
+ if err != nil {
+ return getNew(path), err
+ }
+
+ result := getNew(path)
+
+ err = json.Unmarshal(fileBytes, result)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
diff --git a/pkg/msg/msg.go b/pkg/msg/msg.go
new file mode 100644
index 0000000..f26442f
--- /dev/null
+++ b/pkg/msg/msg.go
@@ -0,0 +1,135 @@
+package msg
+
+import (
+ "io"
+ "os"
+ "strings"
+ "sync"
+
+ "github.com/pterm/pterm"
+)
+
+type logLevel int
+
+const (
+ _ logLevel = iota
+ WARN
+ ERROR
+ INFO
+ DEBUG
+)
+
+type Messenger struct {
+ sync.Mutex
+ Stdout io.Writer
+ Stderr io.Writer
+ Stdin io.Reader
+ exitStatus int
+ hasError bool
+
+ logLevel logLevel
+}
+
+func NewMessenger() *Messenger {
+ m := &Messenger{
+ Stdout: os.Stdout,
+ Stderr: os.Stderr,
+ Stdin: os.Stdin,
+ exitStatus: 1,
+ logLevel: INFO,
+ }
+
+ return m
+}
+
+//nolint:gochecknoglobals // This is a global variable
+var defaultMsg = NewMessenger()
+
+func Die(msg string, args ...any) {
+ defaultMsg.Die(msg, args...)
+}
+
+func Info(msg string, args ...any) {
+ defaultMsg.Info(msg, args...)
+}
+
+func Debug(msg string, args ...any) {
+ defaultMsg.Debug(msg, args...)
+}
+
+func Warn(msg string, args ...any) {
+ defaultMsg.Warn(msg, args...)
+}
+
+func Err(msg string, args ...any) {
+ defaultMsg.Err(msg, args...)
+}
+
+func LogLevel(level logLevel) {
+ defaultMsg.LogLevel(level)
+}
+
+func (m *Messenger) LogLevel(level logLevel) {
+ m.Lock()
+ m.logLevel = level
+ m.Unlock()
+}
+
+func (m *Messenger) Err(msg string, args ...any) {
+ if m.logLevel < ERROR {
+ return
+ }
+ m.print(pterm.Error, msg, args...)
+ m.hasError = true
+}
+
+func (m *Messenger) Warn(msg string, args ...any) {
+ if m.logLevel < WARN {
+ return
+ }
+ m.print(pterm.Warning, msg, args...)
+}
+
+func (m *Messenger) Info(msg string, args ...any) {
+ if m.logLevel < INFO {
+ return
+ }
+ m.print(pterm.Info, msg, args...)
+}
+
+func (m *Messenger) Debug(msg string, args ...any) {
+ if m.logLevel < DEBUG {
+ return
+ }
+
+ m.print(pterm.Debug, msg, args...)
+}
+
+func (m *Messenger) Die(msg string, args ...any) {
+ m.Err(msg, args...)
+ os.Exit(m.exitStatus)
+}
+
+func (m *Messenger) ExitCode(exitStatus int) {
+ m.Lock()
+ m.exitStatus = exitStatus
+ m.Unlock()
+}
+
+func ExitCode(exitStatus int) {
+ defaultMsg.ExitCode(exitStatus)
+}
+
+func (m *Messenger) print(printer pterm.PrefixPrinter, msg string, args ...any) {
+ m.Lock()
+ defer m.Unlock()
+ if !strings.HasSuffix(msg, "\n") {
+ msg += "\n"
+ }
+
+ printer.Printf(msg, args...)
+}
+
+func (m *Messenger) HasErrored() bool {
+ return m.hasError
+}
diff --git a/pkg/paths/paths.go b/pkg/paths/paths.go
new file mode 100644
index 0000000..7841021
--- /dev/null
+++ b/pkg/paths/paths.go
@@ -0,0 +1,93 @@
+package paths
+
+import (
+ "os"
+ "path/filepath"
+
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
+ "github.com/hashload/boss/utils"
+)
+
+func EnsureCleanModulesDir(dependencies []models.Dependency, lock models.PackageLock) {
+ cacheDir := env.GetModulesDir()
+ cacheDirInfo, err := os.Stat(cacheDir)
+ if os.IsNotExist(err) {
+ err = os.MkdirAll(cacheDir, os.ModeDir|0755)
+ utils.HandleError(err)
+ }
+
+ if cacheDirInfo != nil && !cacheDirInfo.IsDir() {
+ msg.Die("modules is not a directory")
+ }
+
+ fileInfos, err := os.ReadDir(cacheDir)
+ utils.HandleError(err)
+ dependenciesNames := models.GetDependenciesNames(dependencies)
+ for _, info := range fileInfos {
+ if !info.IsDir() {
+ err = os.Remove(info.Name())
+ utils.HandleError(err)
+ }
+ if utils.Contains(consts.DefaultPaths(), info.Name()) {
+ cleanArtifacts(filepath.Join(cacheDir, info.Name()), lock)
+ continue
+ }
+
+ if !utils.Contains(dependenciesNames, info.Name()) {
+ remove:
+ if err = os.RemoveAll(filepath.Join(cacheDir, info.Name())); err != nil {
+ msg.Warn("Failed to remove old cache: %s", err.Error())
+ goto remove
+ }
+ }
+ }
+
+ for _, path := range consts.DefaultPaths() {
+ createPath(filepath.Join(cacheDir, path))
+ }
+}
+
+func EnsureCacheDir(dep models.Dependency) {
+ if !env.GlobalConfiguration().GitEmbedded {
+ return
+ }
+ cacheDir := filepath.Join(env.GetCacheDir(), dep.HashName())
+
+ fi, err := os.Stat(cacheDir)
+ if err != nil {
+ msg.Debug("Creating %s", cacheDir)
+ err = os.MkdirAll(cacheDir, os.ModeDir|0755)
+ if err != nil {
+ msg.Die("Could not create %s: %s", cacheDir, err)
+ }
+ } else if !fi.IsDir() {
+ msg.Die("cache is not a directory")
+ }
+}
+
+func createPath(path string) {
+ utils.HandleError(os.MkdirAll(path, os.ModeDir|0755))
+}
+
+func cleanArtifacts(dir string, lock models.PackageLock) {
+ fileInfos, err := os.ReadDir(dir)
+ utils.HandleError(err)
+ artifactList := lock.GetArtifactList()
+ for _, infoArtifact := range fileInfos {
+ if infoArtifact.IsDir() {
+ continue
+ }
+ if !utils.Contains(artifactList, infoArtifact.Name()) {
+ for {
+ err = os.Remove(filepath.Join(dir, infoArtifact.Name()))
+ utils.HandleError(err)
+ if err == nil {
+ break
+ }
+ }
+ }
+ }
+}
diff --git a/core/registry/registry.go b/pkg/registry/registry.go
similarity index 85%
rename from core/registry/registry.go
rename to pkg/registry/registry.go
index db31f92..b79bd65 100644
--- a/core/registry/registry.go
+++ b/pkg/registry/registry.go
@@ -4,7 +4,7 @@ import (
"path/filepath"
"strings"
- "github.com/hashload/boss/env"
+ "github.com/hashload/boss/pkg/env"
)
func GetDelphiPaths() []string {
@@ -17,7 +17,7 @@ func GetDelphiPaths() []string {
func GetCurrentDelphiVersion() string {
for version, path := range getDelphiVersionFromRegistry() {
- if strings.HasPrefix(strings.ToLower(path), strings.ToLower(env.GlobalConfiguration.DelphiPath)) {
+ if strings.HasPrefix(strings.ToLower(path), strings.ToLower(env.GlobalConfiguration().DelphiPath)) {
return version
}
}
diff --git a/core/registry/registry_unix.go b/pkg/registry/registry_unix.go
similarity index 84%
rename from core/registry/registry_unix.go
rename to pkg/registry/registry_unix.go
index 2f3e3fd..06ab220 100644
--- a/core/registry/registry_unix.go
+++ b/pkg/registry/registry_unix.go
@@ -3,11 +3,10 @@
package registry
-import "github.com/hashload/boss/msg"
+import "github.com/hashload/boss/pkg/msg"
func getDelphiVersionFromRegistry() map[string]string {
msg.Warn("getDelphiVersionFromRegistry not implemented on this platform")
return map[string]string{}
-
}
diff --git a/core/registry/registry_win.go b/pkg/registry/registry_win.go
similarity index 95%
rename from core/registry/registry_win.go
rename to pkg/registry/registry_win.go
index 1c9ead4..a0060ce 100644
--- a/core/registry/registry_win.go
+++ b/pkg/registry/registry_win.go
@@ -6,7 +6,7 @@ package registry
import (
"os"
- "github.com/hashload/boss/consts"
+ "github.com/hashload/boss/pkg/consts"
"github.com/hashload/boss/utils"
"golang.org/x/sys/windows/registry"
)
diff --git a/core/scripts/runner.go b/pkg/scripts/runner.go
similarity index 58%
rename from core/scripts/runner.go
rename to pkg/scripts/runner.go
index cddf118..b038a89 100644
--- a/core/scripts/runner.go
+++ b/pkg/scripts/runner.go
@@ -3,19 +3,15 @@ package scripts
import (
"bufio"
"errors"
- "fmt"
"io"
"os/exec"
- "strings"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
)
-func RunCmd(cmdName string) {
- fields := strings.Fields(cmdName)
-
- cmd := exec.Command(fields[0], fields[1:]...)
+func RunCmd(name string, args ...string) {
+ cmd := exec.Command(name, args...)
cmdReader, err := cmd.StdoutPipe()
cmdErr, _ := cmd.StderrPipe()
if err != nil {
@@ -27,9 +23,8 @@ func RunCmd(cmdName string) {
go func() {
for scanner.Scan() {
text := scanner.Text()
- fmt.Printf("%s\n", text)
+ msg.Info("%s\n", text)
}
-
}()
err = cmd.Start()
@@ -46,19 +41,17 @@ func RunCmd(cmdName string) {
}
func Run(args []string) {
- if pkgJson, e := models.LoadPackage(true); e != nil {
- msg.Err(e.Error())
+ if packageData, err := models.LoadPackage(true); err != nil {
+ msg.Err(err.Error())
} else {
- if pkgJson.Scripts == nil {
+ if packageData.Scripts == nil {
msg.Die(errors.New("script not exists").Error())
}
- scripts := pkgJson.Scripts.(map[string]interface{})
- if command, ok := scripts[args[0]]; !ok {
+ if command, ok := packageData.Scripts[args[0]]; !ok {
msg.Err(errors.New("script not exists").Error())
} else {
- RunCmd(command.(string) + " " + strings.Join(args[1:], " "))
+ RunCmd(command, args[1:]...)
}
}
-
}
diff --git a/setup/migrations.go b/setup/migrations.go
index 24cc2e1..e7e6a6d 100644
--- a/setup/migrations.go
+++ b/setup/migrations.go
@@ -1,78 +1,143 @@
package setup
import (
+ "crypto/aes"
+ "crypto/cipher"
+ "encoding/base64"
+ "encoding/json"
+ "errors"
+ "fmt"
"os"
"path/filepath"
"time"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/core/installer"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
+ "github.com/denisbrodbeck/machineid"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/installer"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
"github.com/hashload/boss/utils"
)
-func updateVersion(newVersion int64) {
- env.GlobalConfiguration.ConfigVersion = newVersion
- env.GlobalConfiguration.SaveConfiguration()
+func one() {
+ env.GlobalConfiguration().InternalRefreshRate = 5
}
-func needUpdate(toVersion int64) bool {
- return env.GlobalConfiguration.ConfigVersion < toVersion
+func two() {
+ oldPath := filepath.Join(env.GetBossHome(), consts.FolderDependencies, consts.BossInternalDirOld+env.HashDelphiPath())
+ newPath := filepath.Join(env.GetBossHome(), consts.FolderDependencies, consts.BossInternalDir+env.HashDelphiPath())
+ err := os.Rename(oldPath, newPath)
+ if !os.IsNotExist(err) {
+ utils.HandleError(err)
+ }
}
-func executeUpdate(version int64, update func()) {
- if needUpdate(version) {
- msg.Debug("\t\tRunning update to version %d", version)
- update()
- updateVersion(version)
- } else {
- msg.Debug("\t\tUpdate to version %d already performed", version)
- }
+func three() {
+ env.GlobalConfiguration().GitEmbedded = true
+ env.GlobalConfiguration().SaveConfiguration()
}
-func migration() {
+func six() {
+ err := os.RemoveAll(env.GetInternalGlobalDir())
+ utils.HandleError(err)
+}
- executeUpdate(1,
- func() {
- env.GlobalConfiguration.InternalRefreshRate = 5
- })
+func seven() {
+ bossCfg := filepath.Join(env.GetBossHome(), consts.BossConfigFile)
+ if _, err := os.Stat(bossCfg); os.IsNotExist(err) {
+ return
+ }
+ file, err := os.Open(bossCfg)
+ utils.HandleError(err)
+
+ data := map[string]any{}
+
+ err = json.NewDecoder(file).Decode(&data)
+ utils.HandleError(err)
+
+ auth, found := data["auth"].(map[string]any)
+ if !found {
+ return
+ }
- executeUpdate(2, func() {
- OldPath := filepath.Join(env.GetBossHome(), consts.FolderDependencies, consts.BossInternalDirOld+env.HashDelphiPath())
- newPath := filepath.Join(env.GetBossHome(), consts.FolderDependencies, consts.BossInternalDir+env.HashDelphiPath())
- err := os.Rename(OldPath, newPath)
- if !os.IsNotExist(err) {
- utils.HandleError(err)
+ for key, value := range auth {
+ authMap, ok := value.(map[string]interface{})
+ if !ok {
+ continue
}
- })
-
- executeUpdate(3, func() {
- env.GlobalConfiguration.GitEmbedded = true
- })
-
- executeUpdate(5, func() {
- env.Internal = false
- env.GlobalConfiguration.LastInternalUpdate = time.Now().AddDate(-1000, 0, 0)
- modulesDir := filepath.Join(env.GetBossHome(), consts.FolderDependencies, env.HashDelphiPath())
- if _, err := os.Stat(modulesDir); os.IsNotExist(err) {
- return
+
+ if user, found := authMap["x"]; found {
+ us, err := oldDecrypt(user)
+ utils.HandleErrorFatal(err)
+ env.GlobalConfiguration().Auth[key].SetUser(us)
}
- err := os.Remove(filepath.Join(modulesDir, consts.FilePackageLock))
- utils.HandleError(err)
- modules, err := models.LoadPackage(false)
- if err != nil {
- return
+ if pass, found := authMap["y"]; found {
+ ps, err := oldDecrypt(pass)
+ utils.HandleErrorFatal(err)
+ env.GlobalConfiguration().Auth[key].SetPass(ps)
+ }
+
+ if passPhrase, found := authMap["z"]; found {
+ pp, err := oldDecrypt(passPhrase)
+ utils.HandleErrorFatal(err)
+ env.GlobalConfiguration().Auth[key].SetPassPhrase(pp)
}
+ }
+}
- installer.GlobalInstall([]string{}, modules, false, false)
- env.Internal = true
- })
+func cleanup() {
+ env.SetInternal(false)
+ env.GlobalConfiguration().LastInternalUpdate = time.Now().AddDate(-1000, 0, 0)
+ modulesDir := filepath.Join(env.GetBossHome(), consts.FolderDependencies, env.HashDelphiPath())
+ if _, err := os.Stat(modulesDir); os.IsNotExist(err) {
+ return
+ }
- executeUpdate(6, func() {
- err := os.RemoveAll(env.GetInternalGlobalDir())
- utils.HandleError(err)
- })
+ err := os.Remove(filepath.Join(modulesDir, consts.FilePackageLock))
+ utils.HandleError(err)
+ modules, err := models.LoadPackage(false)
+ if err != nil {
+ return
+ }
+
+ installer.GlobalInstall([]string{}, modules, false, false)
+ env.SetInternal(true)
+}
+
+func oldDecrypt(securemess any) (string, error) {
+ data, ok := securemess.(string)
+ if !ok {
+ return "", errors.New("error on convert data to string")
+ }
+
+ cipherText, err := base64.URLEncoding.DecodeString(data)
+ if err != nil {
+ return "", fmt.Errorf("error on decode base64: %w", err)
+ }
+
+ id, err := machineid.ID()
+ if err != nil {
+ msg.Err("Error on get machine ID")
+ id = "AAAA"
+ }
+
+ block, err := aes.NewCipher([]byte(id[:16]))
+ if err != nil {
+ return "", fmt.Errorf("error on create cipher: %w", err)
+ }
+
+ if len(cipherText) < aes.BlockSize {
+ return "", errors.New("error on check block size: cipher text block size is too short")
+ }
+
+ iv := cipherText[:aes.BlockSize]
+ cipherText = cipherText[aes.BlockSize:]
+
+ //nolint:staticcheck // Just use the old decrypt method to migrate the data
+ stream := cipher.NewCFBDecrypter(block, iv)
+ stream.XORKeyStream(cipherText, cipherText)
+
+ return string(cipherText), nil
}
diff --git a/setup/migrator.go b/setup/migrator.go
new file mode 100644
index 0000000..2cea387
--- /dev/null
+++ b/setup/migrator.go
@@ -0,0 +1,37 @@
+package setup
+
+import (
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/msg"
+)
+
+func updateVersion(newVersion int64) {
+ env.GlobalConfiguration().ConfigVersion = newVersion
+ env.GlobalConfiguration().SaveConfiguration()
+}
+
+func needUpdate(toVersion int64) bool {
+ return env.GlobalConfiguration().ConfigVersion < toVersion
+}
+
+func executeUpdate(version int64, update ...func()) {
+ if needUpdate(version) {
+ msg.Debug("\t\tRunning update to version %d", version)
+ for _, fn := range update {
+ fn()
+ }
+ updateVersion(version)
+ } else {
+ msg.Debug("\t\tUpdate to version %d already performed", version)
+ }
+}
+
+func migration() {
+ executeUpdate(1, one)
+ executeUpdate(2, two)
+ executeUpdate(3, three)
+ executeUpdate(4, cleanup)
+ executeUpdate(5, cleanup)
+ executeUpdate(6, six)
+ executeUpdate(7, seven, cleanup)
+}
diff --git a/setup/paths.go b/setup/paths.go
new file mode 100644
index 0000000..6dbd910
--- /dev/null
+++ b/setup/paths.go
@@ -0,0 +1,104 @@
+package setup
+
+import (
+ "os"
+ "runtime"
+ "strings"
+ "time"
+
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/msg"
+ "github.com/hashload/boss/utils"
+ "github.com/mattn/go-isatty"
+ "github.com/pterm/pterm"
+)
+
+func buildMessage(path []string) string {
+ if runtime.GOOS == "windows" {
+ advice := "\nTo add the path permanently, run the following command in the terminal:\n\n" +
+ "Press Win + R, type 'sysdm.cpl' and press Enter\n" +
+ "Click on the 'Advanced' tab and then on 'Environment Variables'\n" +
+ "In the 'System Variables' section, click on 'Path' and then on 'Edit'\n" +
+ "Click on 'New' and add the following path:\n" +
+ "\n"
+
+ for _, p := range path {
+ advice += p + "\n"
+ }
+ }
+
+ shellFile := ".bashrc"
+
+ shell := os.Getenv("SHELL")
+
+ if strings.HasSuffix(shell, "fish") {
+ shellFile = ".config/fish/config.fish"
+ }
+
+ if strings.HasSuffix(shell, "zsh") {
+ shellFile = ".zshrc"
+ }
+
+ pathStr := strings.Join(path, ":")
+
+ return "\nTo add the path permanently, run the following command in the terminal:\n\n" +
+ "echo 'export PATH=$PATH:" + pathStr + "' >> ~/" + shellFile + "\n" +
+ "source ~/" + shellFile + "\n"
+}
+
+func InitializePath() {
+ if env.GlobalConfiguration().Advices.SetupPath {
+ return
+ }
+
+ paths := []string{
+ consts.EnvBossBin,
+ env.GetGlobalBinPath(),
+ env.GetGlobalEnvBpl(),
+ env.GetGlobalEnvDcu(),
+ env.GetGlobalEnvDcp(),
+ }
+
+ var needAdd = false
+ currentPath, err := os.Getwd()
+ if err != nil {
+ msg.Die("Failed to load current working directory \n %s", err.Error())
+ return
+ }
+
+ splitPath := strings.Split(currentPath, ";")
+
+ for _, path := range paths {
+ if !utils.Contains(splitPath, path) {
+ splitPath = append(splitPath, path)
+ needAdd = true
+ msg.Info("Adding path %s", path)
+ }
+ }
+
+ if needAdd {
+ newPath := strings.Join(splitPath, ";")
+ currentPathEnv := os.Getenv(PATH)
+ err := os.Setenv(PATH, currentPathEnv+";"+newPath)
+ if err != nil {
+ msg.Die("Failed to update PATH \n %s", err.Error())
+ return
+ }
+
+ msg.Warn("Please restart your console after complete.")
+
+ if isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd()) {
+ msg.Info(buildMessage(paths))
+
+ spinner, _ := pterm.DefaultSpinner.Start("Sleeping for 5 seconds")
+ if spinner != nil {
+ time.Sleep(5 * time.Second)
+ _ = spinner.Stop()
+ }
+
+ env.GlobalConfiguration().Advices.SetupPath = true
+ env.GlobalConfiguration().SaveConfiguration()
+ }
+ }
+}
diff --git a/setup/setup.go b/setup/setup.go
index eb33dd9..a3e8509 100644
--- a/setup/setup.go
+++ b/setup/setup.go
@@ -6,155 +6,111 @@ import (
"strings"
"time"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/core/installer"
- "github.com/hashload/boss/core/registry"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
- "github.com/hashload/boss/utils"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/installer"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
+ "github.com/hashload/boss/pkg/registry"
"github.com/hashload/boss/utils/dcc32"
)
const PATH string = "PATH"
-var (
- defaultModules = []string{
+func defaultModules() []string {
+ return []string{
"bpl-identifier",
}
-)
+}
func Initialize() {
- var OldGlobal = env.Global
- env.Internal = true
- env.Global = true
+ var oldGlobal = env.GetGlobal()
+ env.SetInternal(true)
+ env.SetGlobal(true)
msg.Debug("DEBUG MODE")
msg.Debug("\tInitializing delphi version")
initializeDelphiVersion()
- paths := []string{
- consts.EnvBossBin,
- env.GetGlobalBinPath(),
- env.GetGlobalEnvBpl(),
- env.GetGlobalEnvDcu(),
- env.GetGlobalEnvDcp(),
- }
-
msg.Debug("\tExecuting migrations")
migration()
- msg.Debug("\tAdjusting paths")
- addPaths(paths)
msg.Debug("\tInstalling internal modules")
- installModules(defaultModules)
+ installModules(defaultModules())
msg.Debug("\tCreating paths")
createPaths()
- env.Global = OldGlobal
- env.Internal = false
- msg.Debug("finish boss system initialization")
+ InitializePath()
+ env.SetGlobal(oldGlobal)
+ env.SetInternal(false)
+ msg.Debug("finish boss system initialization")
}
func createPaths() {
_, err := os.Stat(env.GetGlobalEnvBpl())
if os.IsNotExist(err) {
- _ = os.MkdirAll(env.GetGlobalEnvBpl(), os.ModePerm)
+ _ = os.MkdirAll(env.GetGlobalEnvBpl(), 0600)
}
}
-func addPaths(paths []string) {
- var needAdd = false
- currentPath, e := os.Getwd()
- if e != nil {
- msg.Die("Failed to load current working directory \n %s", e.Error())
- return
- }
-
- splitPath := strings.Split(currentPath, ";")
-
- for _, path := range paths {
- if !utils.Contains(splitPath, path) {
- splitPath = append(splitPath, path)
- needAdd = true
- }
- }
-
- if needAdd {
- newPath := strings.Join(splitPath, ";")
- currentPathEnv := os.Getenv(PATH)
- err := os.Setenv(PATH, currentPathEnv+";"+newPath)
- if err != nil {
- msg.Die("Failed to update PATH \n %s", err.Error())
- return
-
- }
-
- msg.Warn("Please restart your console after complete.")
- }
-
-}
-
func installModules(modules []string) {
pkg, _ := models.LoadPackage(true)
- dependencies := pkg.Dependencies.(map[string]interface{})
encountered := 0
for _, newPackage := range modules {
- for installed := range dependencies {
+ for installed := range pkg.Dependencies {
if strings.Contains(installed, newPackage) {
encountered++
}
}
}
- nextUpdate := env.GlobalConfiguration.LastInternalUpdate.
- AddDate(0, 0, env.GlobalConfiguration.PurgeTime)
+ nextUpdate := env.GlobalConfiguration().LastInternalUpdate.
+ AddDate(0, 0, env.GlobalConfiguration().PurgeTime)
if encountered == len(modules) && time.Now().Before(nextUpdate) {
return
}
- env.GlobalConfiguration.LastInternalUpdate = time.Now()
- env.GlobalConfiguration.SaveConfiguration()
+ env.GlobalConfiguration().LastInternalUpdate = time.Now()
+ env.GlobalConfiguration().SaveConfiguration()
installer.GlobalInstall(modules, pkg, false, false)
moveBptIdentifier()
}
func moveBptIdentifier() {
- var OutExeCompilation = filepath.Join(env.GetGlobalBinPath(), consts.BplIdentifierName)
- if _, err := os.Stat(OutExeCompilation); os.IsNotExist(err) {
+ var outExeCompilation = filepath.Join(env.GetGlobalBinPath(), consts.BplIdentifierName)
+ if _, err := os.Stat(outExeCompilation); os.IsNotExist(err) {
return
}
var exePath = filepath.Join(env.GetModulesDir(), consts.BinFolder, consts.BplIdentifierName)
- err := os.MkdirAll(filepath.Dir(exePath), os.ModePerm)
+ err := os.MkdirAll(filepath.Dir(exePath), 0600)
if err != nil {
msg.Err(err.Error())
}
- err = os.Rename(OutExeCompilation, exePath)
+ err = os.Rename(outExeCompilation, exePath)
if err != nil {
msg.Err(err.Error())
}
}
func initializeDelphiVersion() {
- if len(env.GlobalConfiguration.DelphiPath) != 0 {
+ if len(env.GlobalConfiguration().DelphiPath) != 0 {
return
}
dcc32DirByCmd := dcc32.GetDcc32DirByCmd()
if len(dcc32DirByCmd) != 0 {
- env.GlobalConfiguration.DelphiPath = dcc32DirByCmd[0]
- env.GlobalConfiguration.SaveConfiguration()
+ env.GlobalConfiguration().DelphiPath = dcc32DirByCmd[0]
+ env.GlobalConfiguration().SaveConfiguration()
return
}
byRegistry := registry.GetDelphiPaths()
if len(byRegistry) != 0 {
- env.GlobalConfiguration.DelphiPath = byRegistry[len(byRegistry)-1]
- env.GlobalConfiguration.SaveConfiguration()
+ env.GlobalConfiguration().DelphiPath = byRegistry[len(byRegistry)-1]
+ env.GlobalConfiguration().SaveConfiguration()
return
}
-
}
diff --git a/utils/crypto/main.go b/utils/crypto/crypto.go
similarity index 54%
rename from utils/crypto/main.go
rename to utils/crypto/crypto.go
index 2b82eb0..63a26d2 100644
--- a/utils/crypto/main.go
+++ b/utils/crypto/crypto.go
@@ -3,74 +3,79 @@ package crypto
import (
"crypto/aes"
"crypto/cipher"
+ "errors"
+
+ //nolint:gosec // MD5 is used for hash comparison
"crypto/md5"
"crypto/rand"
"encoding/base64"
"encoding/hex"
- "errors"
+ "fmt"
"io"
"github.com/denisbrodbeck/machineid"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/msg"
)
-func Encrypt(key []byte, message string) (cyphred string, err error) {
+func Encrypt(key []byte, message string) (string, error) {
plainText := []byte(message)
block, err := aes.NewCipher(key)
if err != nil {
- return
+ return "", fmt.Errorf("error on create cipher: %w", err)
}
cipherText := make([]byte, aes.BlockSize+len(plainText))
iv := cipherText[:aes.BlockSize]
if _, err = io.ReadFull(rand.Reader, iv); err != nil {
- return
+ return "", fmt.Errorf("error on read random: %w", err)
}
- stream := cipher.NewCFBEncrypter(block, iv)
+ stream := cipher.NewCTR(block, iv)
stream.XORKeyStream(cipherText[aes.BlockSize:], plainText)
- cyphred = base64.URLEncoding.EncodeToString(cipherText)
- return
+ return base64.URLEncoding.EncodeToString(cipherText), nil
}
-func Decrypt(key []byte, securemess string) (decrypted string, err error) {
+func Decrypt(key []byte, securemess string) (string, error) {
cipherText, err := base64.URLEncoding.DecodeString(securemess)
if err != nil {
- return
+ return "", fmt.Errorf("error on decode base64: %w", err)
}
block, err := aes.NewCipher(key)
if err != nil {
- return
-
+ return "", fmt.Errorf("error on create cipher: %w", err)
}
if len(cipherText) < aes.BlockSize {
- err = errors.New("cipher text block size is too short")
- return
+ return "", errors.New("error on check block size: cipher text block size is too short")
}
iv := cipherText[:aes.BlockSize]
cipherText = cipherText[aes.BlockSize:]
- stream := cipher.NewCFBDecrypter(block, iv)
+ stream := cipher.NewCTR(block, iv)
stream.XORKeyStream(cipherText, cipherText)
- decrypted = string(cipherText)
- return
+ return string(cipherText), nil
}
+
func GetMachineID() string {
- id, e := machineid.ID()
- if e != nil {
+ id, err := machineid.ID()
+ if err != nil {
msg.Err("Error on get machine ID")
- id = "AAAA"
+ id = "12345678901234567890123456789012"
}
return id
}
+func MachineKey() []byte {
+ return []byte(GetMachineID())
+}
+
func Md5MachineID() string {
+ //nolint:gosec // MD5 is used for hash comparison
hash := md5.New()
if _, err := io.WriteString(hash, GetMachineID()); err != nil {
msg.Warn("Failed on write machine id to hash")
diff --git a/utils/crypto/crypto_test.go b/utils/crypto/crypto_test.go
new file mode 100644
index 0000000..caa21a2
--- /dev/null
+++ b/utils/crypto/crypto_test.go
@@ -0,0 +1,51 @@
+package crypto_test
+
+import (
+ "testing"
+
+ "github.com/hashload/boss/utils/crypto"
+)
+
+func TestCryptoa(t *testing.T) {
+ type args struct {
+ key []byte
+ message string
+ }
+ tests := []struct {
+ name string
+ args args
+ }{
+ {
+ name: "Test 1",
+ args: args{
+ key: []byte("1234567890123456"),
+ message: "Hello, World!",
+ }},
+ {
+ name: "Test 2",
+ args: args{
+ key: []byte("1234567890123456"),
+ message: "Hello, World!",
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := crypto.Encrypt(tt.args.key, tt.args.message)
+ if err != nil {
+ t.Errorf("Encrypt() error = %v", err)
+ return
+ }
+
+ dec, err := crypto.Decrypt(tt.args.key, got)
+ if err != nil {
+ t.Errorf("Decrypt() error = %v", err)
+ return
+ }
+
+ if dec != tt.args.message {
+ t.Errorf("Decrypt() = %v, want %v", dec, tt.args.message)
+ }
+ })
+ }
+}
diff --git a/utils/dcp/dcp.go b/utils/dcp/dcp.go
index 3d26441..54e413e 100644
--- a/utils/dcp/dcp.go
+++ b/utils/dcp/dcp.go
@@ -2,23 +2,21 @@ package dcp
import (
"fmt"
- "io/ioutil"
- "log"
+ "io"
"os"
"path/filepath"
"regexp"
"strings"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/models"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
"github.com/hashload/boss/utils"
"github.com/hashload/boss/utils/librarypath"
"golang.org/x/text/encoding/charmap"
"golang.org/x/text/transform"
)
-var encode = charmap.Windows1252
-
func InjectDpcs(pkg *models.Package, lock models.PackageLock) {
dprojNames := librarypath.GetProjectNames(pkg)
@@ -30,25 +28,29 @@ func InjectDpcs(pkg *models.Package, lock models.PackageLock) {
}
func InjectDpcsFile(fileName string, pkg *models.Package, lock models.PackageLock) {
- if fileName, exists := getDprDpkFromDproj(fileName); exists {
- file := readFile(fileName)
- requiresList := getRequiresList(pkg, lock)
- if file, needWrite := processFile(file, requiresList); needWrite {
- writeFile(fileName, file)
- }
+ dprDpkFileName, exists := getDprDpkFromDproj(fileName)
+ if !exists {
+ return
+ }
+
+ file := readFile(dprDpkFileName)
+ requiresList := getRequiresList(pkg, lock)
+
+ if processedFile, needWrite := processFile(file, requiresList); needWrite {
+ writeFile(dprDpkFileName, processedFile)
}
}
func readFile(filename string) string {
f, err := os.Open(filename)
if err != nil {
- log.Fatal(err)
+ msg.Die(err.Error())
}
- r := transform.NewReader(f, encode.NewDecoder())
+ r := transform.NewReader(f, charmap.Windows1252.NewDecoder())
- bytes, err := ioutil.ReadAll(r)
+ bytes, err := io.ReadAll(r)
if err != nil {
- log.Fatal(err)
+ msg.Die(err.Error())
}
return string(bytes)
@@ -57,19 +59,19 @@ func readFile(filename string) string {
func writeFile(filename string, content string) {
f, err := os.Create(filename)
if err != nil {
- log.Fatal(err)
+ msg.Die(err.Error())
}
- w := transform.NewWriter(f, encode.NewEncoder())
+ w := transform.NewWriter(f, charmap.Windows1252.NewEncoder())
_, err = fmt.Fprint(w, content)
if err != nil {
- log.Fatal(err)
+ msg.Die(err.Error())
}
if err = f.Close(); err != nil {
- log.Fatal(err)
+ msg.Die(err.Error())
}
}
-func getDprDpkFromDproj(dprojName string) (filename string, find bool) {
+func getDprDpkFromDproj(dprojName string) (string, bool) {
baseName := strings.TrimSuffix(dprojName, filepath.Ext(dprojName))
dpkName := baseName + consts.FileExtensionDpk
@@ -117,12 +119,12 @@ func injectDcps(filecontent string, dcps []string) (string, bool) {
return result, true
}
-func processFile(content string, dcps []string) (newContent string, hasNew bool) {
+func processFile(content string, dcps []string) (string, bool) {
if len(dcps) == 0 {
return content, false
}
- if content, success := injectDcps(content, dcps); success {
- return content, true
+ if injectedContent, success := injectDcps(content, dcps); success {
+ return injectedContent, true
}
lines := strings.Split(content, "\n")
@@ -140,5 +142,4 @@ func processFile(content string, dcps []string) (newContent string, hasNew bool)
content = strings.Join(lines[:containsindex], "\n\n") +
"requires" + dpcLine + ";\n\n" + strings.Join(lines[containsindex:], "\n")
return content, true
-
}
diff --git a/utils/dcp/requires_mapper.go b/utils/dcp/requires_mapper.go
index 0ca843d..b81c1d4 100644
--- a/utils/dcp/requires_mapper.go
+++ b/utils/dcp/requires_mapper.go
@@ -4,8 +4,8 @@ import (
"path/filepath"
"strings"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/models"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/models"
)
func getRequiresList(pkg *models.Package, rootLock models.PackageLock) []string {
diff --git a/utils/errorHandle.go b/utils/errorHandle.go
index f73226c..9d3be8d 100644
--- a/utils/errorHandle.go
+++ b/utils/errorHandle.go
@@ -1,9 +1,15 @@
package utils
-import "github.com/hashload/boss/msg"
+import "github.com/hashload/boss/pkg/msg"
func HandleError(err error) {
if err != nil {
msg.Err(err.Error())
}
}
+
+func HandleErrorFatal(err error) {
+ if err != nil {
+ msg.Die(err.Error())
+ }
+}
diff --git a/utils/hash.go b/utils/hash.go
index 6e8f6b1..6387e78 100644
--- a/utils/hash.go
+++ b/utils/hash.go
@@ -1,37 +1,45 @@
package utils
import (
+ //nolint:gosec // MD5 is used for hash comparison
"crypto/md5"
"encoding/hex"
- "io/ioutil"
"os"
"path/filepath"
+
+ "github.com/hashload/boss/pkg/msg"
)
func hashByte(contentPtr *[]byte) string {
contents := *contentPtr
+ //nolint:gosec // MD5 is used for hash comparison
hasher := md5.New()
hasher.Write(contents)
return hex.EncodeToString(hasher.Sum(nil))
-
}
func HashDir(dir string) string {
var err error
- var finHash = "b:"
- err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
- if err != nil {
+ var finalHash = "b:"
+ err = filepath.Walk(dir, func(path string, _ os.FileInfo, err error) error {
+ if err != nil && !os.IsNotExist(err) {
+ msg.Warn("Failed to read file %s", path)
+ return nil
+ }
+
+ if os.IsNotExist(err) {
return nil
}
- fileBytes, _ := ioutil.ReadFile(path)
+
+ fileBytes, _ := os.ReadFile(path)
fileHash := hashByte(&fileBytes)
- finHash += fileHash
+ finalHash += fileHash
return nil
})
if err != nil {
os.Exit(1)
}
- c := []byte(finHash)
+ c := []byte(finalHash)
m := hashByte(&c)
return m
}
diff --git a/utils/librarypath/dproj_itil.go b/utils/librarypath/dproj_util.go
similarity index 61%
rename from utils/librarypath/dproj_itil.go
rename to utils/librarypath/dproj_util.go
index 5f4860a..93e3dac 100644
--- a/utils/librarypath/dproj_itil.go
+++ b/utils/librarypath/dproj_util.go
@@ -1,20 +1,17 @@
package librarypath
import (
- "io/ioutil"
"os"
"path"
"path/filepath"
"regexp"
- "strconv"
"strings"
"github.com/beevik/etree"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
- "github.com/hashload/boss/utils"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
)
func updateDprojLibraryPath(pkg *models.Package) {
@@ -36,23 +33,23 @@ func updateOtherUnitFilesProject(lpiName string) {
msg.Err(".lpi not found.")
return
}
- e := doc.ReadFromFile(lpiName)
- if e != nil {
- msg.Err("Error on read lpi: %s", e)
+ err = doc.ReadFromFile(lpiName)
+ if err != nil {
+ msg.Err("Error on read lpi: %s", err)
return
}
root := doc.Root()
- compilerOptions := root.SelectElement(consts.XmlTagNameCompilerOptions)
+ compilerOptions := root.SelectElement(consts.XMLTagNameCompilerOptions)
processCompilerOptions(compilerOptions)
- projectOptions := root.SelectElement(consts.XmlTagNameProjectOptions)
+ projectOptions := root.SelectElement(consts.XMLTagNameProjectOptions)
- buildModes := projectOptions.SelectElement(consts.XmlTagNameBuildModes)
- for _, item := range buildModes.SelectElements(consts.XmlTagNameItem) {
- attribute := item.SelectAttr(consts.XmlNameAttribute)
- compilerOptions := item.SelectElement(consts.XmlTagNameCompilerOptions)
+ buildModes := projectOptions.SelectElement(consts.XMLTagNameBuildModes)
+ for _, item := range buildModes.SelectElements(consts.XMLTagNameItem) {
+ attribute := item.SelectAttr(consts.XMLNameAttribute)
+ compilerOptions = item.SelectElement(consts.XMLTagNameCompilerOptions)
if compilerOptions != nil {
msg.Info(" Updating %s mode", attribute.Value)
processCompilerOptions(compilerOptions)
@@ -62,17 +59,18 @@ func updateOtherUnitFilesProject(lpiName string) {
doc.WriteSettings.CanonicalAttrVal = true
doc.WriteSettings.CanonicalEndTags = false
doc.WriteSettings.CanonicalText = true
- if err := doc.WriteToFile(lpiName); err != nil {
+
+ if err = doc.WriteToFile(lpiName); err != nil {
panic(err)
}
}
func processCompilerOptions(compilerOptions *etree.Element) {
- searchPaths := compilerOptions.SelectElement(consts.XmlTagNameSearchPaths)
+ searchPaths := compilerOptions.SelectElement(consts.XMLTagNameSearchPaths)
if searchPaths == nil {
return
}
- otherUnitFiles := searchPaths.SelectElement(consts.XmlTagNameOtherUnitFiles)
+ otherUnitFiles := searchPaths.SelectElement(consts.XMLTagNameOtherUnitFiles)
if otherUnitFiles == nil {
otherUnitFiles = createTagOtherUnitFiles(searchPaths)
}
@@ -83,7 +81,7 @@ func processCompilerOptions(compilerOptions *etree.Element) {
}
func createTagOtherUnitFiles(node *etree.Element) *etree.Element {
- child := node.CreateElement(consts.XmlTagNameOtherUnitFiles)
+ child := node.CreateElement(consts.XMLTagNameOtherUnitFiles)
child.CreateAttr("Value", "")
return child
}
@@ -96,7 +94,6 @@ func updateGlobalBrowsingPath(pkg *models.Package) {
updateGlobalBrowsingByProject(projectName, i == 0)
}
}
-
}
func updateLibraryPathProject(dprojName string) {
@@ -106,23 +103,23 @@ func updateLibraryPathProject(dprojName string) {
msg.Err(".dproj not found.")
return
}
- e := doc.ReadFromFile(dprojName)
- if e != nil {
- msg.Err("Error on read dproj: %s", e)
+ err = doc.ReadFromFile(dprojName)
+ if err != nil {
+ msg.Err("Error on read dproj: %s", err)
return
}
root := doc.Root()
- childrens := root.FindElements(consts.XmlTagNameProperty)
+ childrens := root.FindElements(consts.XMLTagNameProperty)
for _, children := range childrens {
- attribute := children.SelectAttr(consts.XmlTagNamePropertyAttribute)
- if attribute != nil && attribute.Value == consts.XmlTagNamePropertyAttributeValue {
- child := children.SelectElement(consts.XmlTagNameLibraryPath)
+ attribute := children.SelectAttr(consts.XMLTagNamePropertyAttribute)
+ if attribute != nil && attribute.Value == consts.XMLTagNamePropertyAttributeValue {
+ child := children.SelectElement(consts.XMLTagNameLibraryPath)
if child == nil {
child = createTagLibraryPath(children)
}
rootPath := filepath.Join(env.GetCurrentDir(), path.Dir(dprojName))
- if _, err := os.Stat(rootPath); os.IsNotExist(err) {
+ if _, err = os.Stat(rootPath); os.IsNotExist(err) {
rootPath = env.GetCurrentDir()
}
processCurrentPath(child, rootPath)
@@ -133,13 +130,13 @@ func updateLibraryPathProject(dprojName string) {
doc.WriteSettings.CanonicalEndTags = false
doc.WriteSettings.CanonicalText = true
- if err := doc.WriteToFile(dprojName); err != nil {
+ if err = doc.WriteToFile(dprojName); err != nil {
panic(err)
}
}
func createTagLibraryPath(node *etree.Element) *etree.Element {
- child := node.CreateElement(consts.XmlTagNameLibraryPath)
+ child := node.CreateElement(consts.XMLTagNameLibraryPath)
return child
}
@@ -150,7 +147,7 @@ func GetProjectNames(pkg *models.Package) []string {
if len(pkg.Projects) > 0 {
result = pkg.Projects
} else {
- files, err := ioutil.ReadDir(env.GetCurrentDir())
+ files, err := os.ReadDir(env.GetCurrentDir())
if err != nil {
panic(err)
}
@@ -170,7 +167,7 @@ func GetProjectNames(pkg *models.Package) []string {
}
func isLazarus() bool {
- files, err := ioutil.ReadDir(env.GetCurrentDir())
+ files, err := os.ReadDir(env.GetCurrentDir())
if err != nil {
panic(err)
}
@@ -193,36 +190,3 @@ func processCurrentPath(node *etree.Element, rootPath string) {
node.SetText(strings.Join(currentPaths, ";"))
}
-
-func _(dprojName string) []string {
- doc := etree.NewDocument()
- info, err := os.Stat(dprojName)
- if os.IsNotExist(err) || info.IsDir() {
- msg.Err(".dproj not found.")
- return []string{}
- }
- err = doc.ReadFromFile(dprojName)
- if err != nil {
- msg.Err("Error on read dproj: %s", err)
- return []string{}
- }
- root := doc.Root()
-
- var result []string
-
- path, err := etree.CompilePath("/Project/ProjectExtensions/BorlandProject/Platforms")
- utils.HandleError(err)
- platforms := root.FindElementPath(path)
- for _, platform := range platforms.ChildElements() {
- value := platform.SelectAttr(consts.XmlValueAttribute)
- activePlatform, err := strconv.ParseBool(platform.Text())
- utils.HandleError(err)
-
- if value != nil && activePlatform {
- result = append(result, value.Value)
- }
- }
-
- return result
-
-}
diff --git a/utils/librarypath/global_util_unix.go b/utils/librarypath/global_util_unix.go
index ea5b923..5f98ac9 100644
--- a/utils/librarypath/global_util_unix.go
+++ b/utils/librarypath/global_util_unix.go
@@ -4,13 +4,13 @@
package librarypath
import (
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/msg"
)
func updateGlobalLibraryPath() {
msg.Warn("updateGlobalLibraryPath not implemented on this platform")
}
-func updateGlobalBrowsingByProject(dprojName string, setReadOnly bool) {
+func updateGlobalBrowsingByProject(_ string, _ bool) {
msg.Warn("updateGlobalBrowsingByProject not implemented on this platform")
}
diff --git a/utils/librarypath/global_util_win.go b/utils/librarypath/global_util_win.go
index 93662e2..8077f50 100644
--- a/utils/librarypath/global_util_win.go
+++ b/utils/librarypath/global_util_win.go
@@ -8,13 +8,13 @@ import (
"path/filepath"
"strings"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/msg"
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/msg"
"github.com/hashload/boss/utils"
"golang.org/x/sys/windows/registry"
- bossRegistry "github.com/hashload/boss/core/registry"
+ bossRegistry "github.com/hashload/boss/pkg/registry"
)
const SearchPathRegistry = "Search Path"
@@ -23,7 +23,7 @@ const BrowsingPathRegistry = "Browsing Path"
func updateGlobalLibraryPath() {
ideVersion := bossRegistry.GetCurrentDelphiVersion()
if ideVersion == "" {
- msg.Err("Version not found for path %s", env.GlobalConfiguration.DelphiPath)
+ msg.Err("Version not found for path %s", env.GlobalConfiguration().DelphiPath)
}
library, err := registry.OpenKey(registry.CURRENT_USER, consts.RegistryBasePath+ideVersion+`\Library`, registry.ALL_ACCESS)
@@ -64,7 +64,7 @@ func updateGlobalLibraryPath() {
func updateGlobalBrowsingByProject(dprojName string, setReadOnly bool) {
ideVersion := bossRegistry.GetCurrentDelphiVersion()
if ideVersion == "" {
- msg.Err("Version not found for path %s", env.GlobalConfiguration.DelphiPath)
+ msg.Err("Version not found for path %s", env.GlobalConfiguration().DelphiPath)
}
library, err := registry.OpenKey(registry.CURRENT_USER, consts.RegistryBasePath+ideVersion+`\Library`, registry.ALL_ACCESS)
diff --git a/utils/librarypath/librarypath.go b/utils/librarypath/librarypath.go
index b89bde7..20dc20f 100644
--- a/utils/librarypath/librarypath.go
+++ b/utils/librarypath/librarypath.go
@@ -2,28 +2,28 @@ package librarypath
import (
"fmt"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
- "github.com/hashload/boss/consts"
- "github.com/hashload/boss/env"
- "github.com/hashload/boss/models"
- "github.com/hashload/boss/msg"
+ "slices"
+
+ "github.com/hashload/boss/pkg/consts"
+ "github.com/hashload/boss/pkg/env"
+ "github.com/hashload/boss/pkg/models"
+ "github.com/hashload/boss/pkg/msg"
"github.com/hashload/boss/utils"
)
func UpdateLibraryPath(pkg *models.Package) {
- if env.Global {
+ if env.GetGlobal() {
updateGlobalLibraryPath()
} else {
updateDprojLibraryPath(pkg)
updateGlobalBrowsingPath(pkg)
}
-
}
func cleanPath(paths []string, fullPath bool) []string {
@@ -33,7 +33,7 @@ func cleanPath(paths []string, fullPath bool) []string {
prefix, _ = filepath.Rel(env.GetCurrentDir(), prefix)
}
- for key := 0; key < len(paths); key++ {
+ for key := range paths {
if strings.HasPrefix(paths[key], prefix) {
continue
}
@@ -48,56 +48,65 @@ func GetNewBrowsingPaths(paths []string, fullPath bool, rootPath string, setRead
paths = cleanPath(paths, fullPath)
var path = env.GetModulesDir()
- matches, _ := ioutil.ReadDir(path)
+ matches, _ := os.ReadDir(path)
for _, value := range matches {
+ paths = processBrowsingPath(value, paths, path, fullPath, rootPath, setReadOnly)
+ }
+ return paths
+}
- var packagePath = filepath.Join(path, value.Name(), consts.FilePackage)
- if _, err := os.Stat(packagePath); !os.IsNotExist(err) {
-
- other, _ := models.LoadPackageOther(packagePath)
- if other.BrowsingPath != "" {
- dir := filepath.Join(path, value.Name(), other.BrowsingPath)
- paths = getNewBrowsingPathsFromDir(dir, paths, fullPath, rootPath)
-
- if setReadOnly {
- readonlybat := filepath.Join(dir, "readonly.bat")
- readFileStr := fmt.Sprintf(`attrib +r "%s" /s /d`, filepath.Join(dir, "*"))
- err = ioutil.WriteFile(readonlybat, []byte(readFileStr), os.ModePerm)
- if err != nil {
- msg.Warn(" - error on create build file")
- }
-
- cmd := exec.Command(readonlybat)
-
- if _, err := cmd.Output(); err != nil {
- msg.Err(" - Failed to set readonly property to folder", dir, " - ", err)
- } else {
- os.Remove(readonlybat)
- }
- }
-
+func processBrowsingPath(
+ value os.DirEntry,
+ paths []string,
+ basePath string,
+ fullPath bool,
+ rootPath string,
+ setReadOnly bool,
+) []string {
+ var packagePath = filepath.Join(basePath, value.Name(), consts.FilePackage)
+ if _, err := os.Stat(packagePath); !os.IsNotExist(err) {
+ other, _ := models.LoadPackageOther(packagePath)
+ if other.BrowsingPath != "" {
+ dir := filepath.Join(basePath, value.Name(), other.BrowsingPath)
+ paths = getNewBrowsingPathsFromDir(dir, paths, fullPath, rootPath)
+ if setReadOnly {
+ setReadOnlyProperty(dir)
}
-
}
}
return paths
}
+func setReadOnlyProperty(dir string) {
+ readonlybat := filepath.Join(dir, "readonly.bat")
+ readFileStr := fmt.Sprintf(`attrib +r "%s" /s /d`, filepath.Join(dir, "*"))
+ err := os.WriteFile(readonlybat, []byte(readFileStr), 0600)
+ if err != nil {
+ msg.Warn(" - error on create build file")
+ }
+
+ cmd := exec.Command(readonlybat)
+
+ _, err = cmd.Output()
+ if err != nil {
+ msg.Err(" - Failed to set readonly property to folder", dir, " - ", err)
+ } else {
+ os.Remove(readonlybat)
+ }
+}
+
func GetNewPaths(paths []string, fullPath bool, rootPath string) []string {
paths = cleanPath(paths, fullPath)
var path = env.GetModulesDir()
- matches, _ := ioutil.ReadDir(path)
+ matches, _ := os.ReadDir(path)
for _, value := range matches {
-
var packagePath = filepath.Join(path, value.Name(), consts.FilePackage)
if _, err := os.Stat(packagePath); !os.IsNotExist(err) {
-
other, _ := models.LoadPackageOther(packagePath)
paths = getNewPathsFromDir(filepath.Join(path, value.Name(), other.MainSrc), paths, fullPath, rootPath)
-
} else {
paths = getNewPathsFromDir(filepath.Join(path, value.Name()), paths, fullPath, rootPath)
}
@@ -135,21 +144,20 @@ func getDefaultPath(fullPath bool, rootPath string) []string {
func cleanEmpty(paths []string) []string {
for index, value := range paths {
-
if value == "" {
- paths = append(paths[:index], paths[index+1:]...)
+ paths = slices.Delete(paths, index, index+1)
}
}
return paths
}
func getNewBrowsingPathsFromDir(path string, paths []string, fullPath bool, rootPath string) []string {
- _, e := os.Stat(path)
- if os.IsNotExist(e) {
+ _, err := os.Stat(path)
+ if os.IsNotExist(err) {
return paths
}
- _ = filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
+ _ = filepath.Walk(path, func(path string, info os.FileInfo, _ error) error {
matched, _ := regexp.MatchString(consts.RegexArtifacts, info.Name())
if matched {
dir, _ := filepath.Split(path)
@@ -160,11 +168,6 @@ func getNewBrowsingPathsFromDir(path string, paths []string, fullPath bool, root
if !utils.Contains(paths, dir) {
paths = append(paths, dir)
}
- // add ..\ prefixed path -> @MeroFuruya fix #146
- //prefixedPath := "..\\" + dir
- //if !utils.Contains(paths, prefixedPath) {
- // paths = append(paths, prefixedPath)
- //}
}
return nil
})
@@ -172,12 +175,12 @@ func getNewBrowsingPathsFromDir(path string, paths []string, fullPath bool, root
}
func getNewPathsFromDir(path string, paths []string, fullPath bool, rootPath string) []string {
- _, e := os.Stat(path)
- if os.IsNotExist(e) {
+ _, err := os.Stat(path)
+ if os.IsNotExist(err) {
return paths
}
- _ = filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
+ _ = filepath.Walk(path, func(path string, info os.FileInfo, _ error) error {
matched, _ := regexp.MatchString(consts.RegexArtifacts, info.Name())
if matched {
dir, _ := filepath.Split(path)
diff --git a/utils/parser/parser.go b/utils/parser/parser.go
index 61530b0..b019167 100644
--- a/utils/parser/parser.go
+++ b/utils/parser/parser.go
@@ -5,7 +5,7 @@ import (
"encoding/json"
)
-func JSONMarshal(v interface{}, safeEncoding bool) ([]byte, error) {
+func JSONMarshal(v any, safeEncoding bool) ([]byte, error) {
b, err := json.MarshalIndent(v, "", "\t")
if safeEncoding {