mirror of
https://github.com/rclone/rclone.git
synced 2024-11-07 09:04:52 +01:00
build: refactor version info and icon resource handling on windows
This makes it easier to add resources with any build method, and also when building librclone.dll. Goversioninfo is now used as a library, instead of running it as a tool.
This commit is contained in:
parent
4ab57eb90b
commit
4506f35f2e
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@ -216,7 +216,6 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ "${{ matrix.os }}" == "ubuntu-latest" ]]; then make release_dep_linux ; fi
|
||||
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then make release_dep_windows ; fi
|
||||
make ci_beta
|
||||
env:
|
||||
RCLONE_CONFIG_PASS: ${{ secrets.RCLONE_CONFIG_PASS }}
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -16,3 +16,4 @@ Thumbs.db
|
||||
__pycache__
|
||||
.DS_Store
|
||||
/docs/static/img/logos/
|
||||
resource_windows_*.syso
|
||||
|
11
Makefile
11
Makefile
@ -30,6 +30,7 @@ ifdef RELEASE_TAG
|
||||
TAG := $(RELEASE_TAG)
|
||||
endif
|
||||
GO_VERSION := $(shell go version)
|
||||
GO_OS := $(shell go env GOOS)
|
||||
ifdef BETA_SUBDIR
|
||||
BETA_SUBDIR := /$(BETA_SUBDIR)
|
||||
endif
|
||||
@ -46,7 +47,13 @@ endif
|
||||
.PHONY: rclone test_all vars version
|
||||
|
||||
rclone:
|
||||
ifeq ($(GO_OS),windows)
|
||||
go run bin/resource_windows.go -version $(TAG) -syso resource_windows_`go env GOARCH`.syso
|
||||
endif
|
||||
go build -v --ldflags "-s -X github.com/rclone/rclone/fs.Version=$(TAG)" $(BUILDTAGS) $(BUILD_ARGS)
|
||||
ifeq ($(GO_OS),windows)
|
||||
rm resource_windows_`go env GOARCH`.syso
|
||||
endif
|
||||
mkdir -p `go env GOPATH`/bin/
|
||||
cp -av rclone`go env GOEXE` `go env GOPATH`/bin/rclone`go env GOEXE`.new
|
||||
mv -v `go env GOPATH`/bin/rclone`go env GOEXE`.new `go env GOPATH`/bin/rclone`go env GOEXE`
|
||||
@ -102,10 +109,6 @@ build_dep:
|
||||
release_dep_linux:
|
||||
go install github.com/goreleaser/nfpm/v2/cmd/nfpm@latest
|
||||
|
||||
# Get the release dependencies we only install on Windows
|
||||
release_dep_windows:
|
||||
GOOS="" GOARCH="" go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@latest
|
||||
|
||||
# Update dependencies
|
||||
showupdates:
|
||||
@echo "*** Direct dependencies that could be updated ***"
|
||||
|
@ -6,7 +6,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
@ -21,23 +20,21 @@ import (
|
||||
"sync"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-semver/semver"
|
||||
)
|
||||
|
||||
var (
|
||||
// Flags
|
||||
debug = flag.Bool("d", false, "Print commands instead of running them.")
|
||||
parallel = flag.Int("parallel", runtime.NumCPU(), "Number of commands to run in parallel.")
|
||||
debug = flag.Bool("d", false, "Print commands instead of running them")
|
||||
parallel = flag.Int("parallel", runtime.NumCPU(), "Number of commands to run in parallel")
|
||||
copyAs = flag.String("release", "", "Make copies of the releases with this name")
|
||||
gitLog = flag.String("git-log", "", "git log to include as well")
|
||||
include = flag.String("include", "^.*$", "os/arch regexp to include")
|
||||
exclude = flag.String("exclude", "^$", "os/arch regexp to exclude")
|
||||
cgo = flag.Bool("cgo", false, "Use cgo for the build")
|
||||
noClean = flag.Bool("no-clean", false, "Don't clean the build directory before running.")
|
||||
noClean = flag.Bool("no-clean", false, "Don't clean the build directory before running")
|
||||
tags = flag.String("tags", "", "Space separated list of build tags")
|
||||
buildmode = flag.String("buildmode", "", "Passed to go build -buildmode flag")
|
||||
compileOnly = flag.Bool("compile-only", false, "Just build the binary, not the zip.")
|
||||
compileOnly = flag.Bool("compile-only", false, "Just build the binary, not the zip")
|
||||
extraEnv = flag.String("env", "", "comma separated list of VAR=VALUE env vars to set")
|
||||
macOSSDK = flag.String("macos-sdk", "", "macOS SDK to use")
|
||||
macOSArch = flag.String("macos-arch", "", "macOS arch to use")
|
||||
@ -140,21 +137,21 @@ func chdir(dir string) {
|
||||
func substitute(inFile, outFile string, data interface{}) {
|
||||
t, err := template.ParseFiles(inFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to read template file %q: %v %v", inFile, err)
|
||||
log.Fatalf("Failed to read template file %q: %v", inFile, err)
|
||||
}
|
||||
out, err := os.Create(outFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create output file %q: %v %v", outFile, err)
|
||||
log.Fatalf("Failed to create output file %q: %v", outFile, err)
|
||||
}
|
||||
defer func() {
|
||||
err := out.Close()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to close output file %q: %v %v", outFile, err)
|
||||
log.Fatalf("Failed to close output file %q: %v", outFile, err)
|
||||
}
|
||||
}()
|
||||
err = t.Execute(out, data)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to substitute template file %q: %v %v", inFile, err)
|
||||
log.Fatalf("Failed to substitute template file %q: %v", inFile, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,101 +199,6 @@ func buildDebAndRpm(dir, version, goarch string) []string {
|
||||
return artifacts
|
||||
}
|
||||
|
||||
// generate system object (syso) file to be picked up by a following go build for embedding icon and version info resources into windows executable
|
||||
func buildWindowsResourceSyso(goarch string, versionTag string) string {
|
||||
type M map[string]interface{}
|
||||
version := strings.TrimPrefix(versionTag, "v")
|
||||
semanticVersion := semver.New(version)
|
||||
|
||||
// Build json input to goversioninfo utility
|
||||
bs, err := json.Marshal(M{
|
||||
"FixedFileInfo": M{
|
||||
"FileVersion": M{
|
||||
"Major": semanticVersion.Major,
|
||||
"Minor": semanticVersion.Minor,
|
||||
"Patch": semanticVersion.Patch,
|
||||
},
|
||||
"ProductVersion": M{
|
||||
"Major": semanticVersion.Major,
|
||||
"Minor": semanticVersion.Minor,
|
||||
"Patch": semanticVersion.Patch,
|
||||
},
|
||||
},
|
||||
"StringFileInfo": M{
|
||||
"CompanyName": "https://rclone.org",
|
||||
"ProductName": "Rclone",
|
||||
"FileDescription": "Rclone",
|
||||
"InternalName": "rclone",
|
||||
"OriginalFilename": "rclone.exe",
|
||||
"LegalCopyright": "The Rclone Authors",
|
||||
"FileVersion": version,
|
||||
"ProductVersion": version,
|
||||
},
|
||||
"IconPath": "../graphics/logo/ico/logo_symbol_color.ico",
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to build version info json: %v", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
// Write json to temporary file that will only be used by the goversioninfo command executed below.
|
||||
jsonPath, err := filepath.Abs("versioninfo_windows_" + goarch + ".json") // Appending goos and goarch as suffix to avoid any race conditions
|
||||
if err != nil {
|
||||
log.Printf("Failed to resolve path: %v", err)
|
||||
return ""
|
||||
}
|
||||
err = os.WriteFile(jsonPath, bs, 0644)
|
||||
if err != nil {
|
||||
log.Printf("Failed to write %s: %v", jsonPath, err)
|
||||
return ""
|
||||
}
|
||||
defer func() {
|
||||
if err := os.Remove(jsonPath); err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
log.Printf("Warning: Couldn't remove generated %s: %v. Please remove it manually.", jsonPath, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Execute goversioninfo utility using the json file as input.
|
||||
// It will produce a system object (syso) file that a following go build should pick up.
|
||||
sysoPath, err := filepath.Abs("../resource_windows_" + goarch + ".syso") // Appending goos and goarch as suffix to avoid any race conditions, and also it is recognized by go build and avoids any builds for other systems considering it
|
||||
if err != nil {
|
||||
log.Printf("Failed to resolve path: %v", err)
|
||||
return ""
|
||||
}
|
||||
args := []string{
|
||||
"goversioninfo",
|
||||
"-o",
|
||||
sysoPath,
|
||||
}
|
||||
if strings.Contains(goarch, "64") {
|
||||
args = append(args, "-64") // Make the syso a 64-bit coff file
|
||||
}
|
||||
if strings.Contains(goarch, "arm") {
|
||||
args = append(args, "-arm") // Make the syso an arm binary
|
||||
}
|
||||
args = append(args, jsonPath)
|
||||
err = runEnv(args, nil)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return sysoPath
|
||||
}
|
||||
|
||||
// delete generated system object (syso) resource file
|
||||
func cleanupResourceSyso(sysoFilePath string) {
|
||||
if sysoFilePath == "" {
|
||||
return
|
||||
}
|
||||
if err := os.Remove(sysoFilePath); err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
log.Printf("Warning: Couldn't remove generated %s: %v. Please remove it manually.", sysoFilePath, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trip a version suffix off the arch if present
|
||||
func stripVersion(goarch string) string {
|
||||
i := strings.Index(goarch, "-")
|
||||
@ -315,17 +217,41 @@ func runOut(command ...string) string {
|
||||
return strings.TrimSpace(string(out))
|
||||
}
|
||||
|
||||
// Generate Windows resource system object file (.syso), which can be picked
|
||||
// up by the following go build for embedding version information and icon
|
||||
// resources into the executable.
|
||||
func generateResourceWindows(version, arch string) func() {
|
||||
sysoPath := fmt.Sprintf("../resource_windows_%s.syso", arch) // Use explicit destination filename, even though it should be same as default, so that we are sure we have the correct reference to it
|
||||
if err := os.Remove(sysoPath); !os.IsNotExist(err) {
|
||||
// Note: This one we choose to treat as fatal, to avoid any risk of picking up an old .syso file without noticing.
|
||||
log.Fatalf("Failed to remove existing Windows %s resource system object file %s: %v", arch, sysoPath, err)
|
||||
}
|
||||
args := []string{"go", "run", "../bin/resource_windows.go", "-arch", arch, "-version", version, "-syso", sysoPath}
|
||||
if err := runEnv(args, nil); err != nil {
|
||||
log.Printf("Warning: Couldn't generate Windows %s resource system object file, binaries will not have version information or icon embedded", arch)
|
||||
return nil
|
||||
}
|
||||
if _, err := os.Stat(sysoPath); err != nil {
|
||||
log.Printf("Warning: Couldn't find generated Windows %s resource system object file, binaries will not have version information or icon embedded", arch)
|
||||
return nil
|
||||
}
|
||||
return func() {
|
||||
if err := os.Remove(sysoPath); err != nil && !os.IsNotExist(err) {
|
||||
log.Printf("Warning: Couldn't remove generated Windows %s resource system object file %s: %v. Please remove it manually.", arch, sysoPath, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// build the binary in dir returning success or failure
|
||||
func compileArch(version, goos, goarch, dir string) bool {
|
||||
log.Printf("Compiling %s/%s into %s", goos, goarch, dir)
|
||||
goarchBase := stripVersion(goarch)
|
||||
output := filepath.Join(dir, "rclone")
|
||||
if goos == "windows" {
|
||||
output += ".exe"
|
||||
sysoPath := buildWindowsResourceSyso(goarch, version)
|
||||
if sysoPath == "" {
|
||||
log.Printf("Warning: Windows binaries will not have file information embedded")
|
||||
if cleanupFn := generateResourceWindows(version, goarchBase); cleanupFn != nil {
|
||||
defer cleanupFn()
|
||||
}
|
||||
defer cleanupResourceSyso(sysoPath)
|
||||
}
|
||||
err := os.MkdirAll(dir, 0777)
|
||||
if err != nil {
|
||||
@ -348,7 +274,7 @@ func compileArch(version, goos, goarch, dir string) bool {
|
||||
)
|
||||
env := []string{
|
||||
"GOOS=" + goos,
|
||||
"GOARCH=" + stripVersion(goarch),
|
||||
"GOARCH=" + goarchBase,
|
||||
}
|
||||
if *extraEnv != "" {
|
||||
env = append(env, strings.Split(*extraEnv, ",")...)
|
||||
|
122
bin/resource_windows.go
Normal file
122
bin/resource_windows.go
Normal file
@ -0,0 +1,122 @@
|
||||
// Utility program to generate Rclone-specific Windows resource system object
|
||||
// file (.syso), that can be picked up by a following go build for embedding
|
||||
// version information and icon resources into a rclone binary.
|
||||
//
|
||||
// Run it with "go generate", or "go run" to be able to customize with
|
||||
// command-line flags. Note that this program is intended to be run directly
|
||||
// from its original location in the source tree: Default paths are absolute
|
||||
// within the current source tree, which is convenient because it makes it
|
||||
// oblivious to the working directory, and it gives identical result whether
|
||||
// run by "go generate" or "go run", but it will not make sense if this
|
||||
// program's source is moved out from the source tree.
|
||||
//
|
||||
// Can be used for rclone.exe (default), and other binaries such as
|
||||
// librclone.dll (must be specified with flag -binary).
|
||||
//
|
||||
|
||||
//go:generate go run resource_windows.go
|
||||
//go:build tools
|
||||
// +build tools
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/coreos/go-semver/semver"
|
||||
"github.com/josephspurrier/goversioninfo"
|
||||
"github.com/rclone/rclone/fs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Get path of directory containing the current source file to use for absolute path references within the code tree (as described above)
|
||||
projectDir := ""
|
||||
_, sourceFile, _, ok := runtime.Caller(0)
|
||||
if ok {
|
||||
projectDir = path.Dir(path.Dir(sourceFile)) // Root of the current project working directory
|
||||
}
|
||||
|
||||
// Define flags
|
||||
binary := flag.String("binary", "rclone.exe", `The name of the binary to generate resource for, e.g. "rclone.exe" or "librclone.dll"`)
|
||||
arch := flag.String("arch", runtime.GOARCH, `Architecture of resource file, or the target GOARCH, "386", "amd64", "arm", or "arm64"`)
|
||||
version := flag.String("version", fs.Version, "Version number or tag name")
|
||||
icon := flag.String("icon", path.Join(projectDir, "graphics/logo/ico/logo_symbol_color.ico"), "Path to icon file to embed in an .exe binary")
|
||||
dir := flag.String("dir", projectDir, "Path to output directory where to write the resulting system object file (.syso), with a default name according to -arch (resource_windows_<arch>.syso), only considered if not -syso is specified")
|
||||
syso := flag.String("syso", "", "Path to output resource system object file (.syso) to be created/overwritten, ignores -dir")
|
||||
|
||||
// Parse command-line flags
|
||||
flag.Parse()
|
||||
|
||||
// Handle default value for -file which depends on optional -dir and -arch
|
||||
if *syso == "" {
|
||||
// Use default filename, which includes target GOOS (hardcoded "windows")
|
||||
// and GOARCH (from argument -arch) as suffix, to avoid any race conditions,
|
||||
// and also this will be recognized by go build when it is consuming the
|
||||
// .syso file and will only be used for builds with matching os/arch.
|
||||
*syso = path.Join(*dir, fmt.Sprintf("resource_windows_%s.syso", *arch))
|
||||
}
|
||||
|
||||
// Parse version/tag string argument as a SemVer
|
||||
stringVersion := strings.TrimPrefix(*version, "v")
|
||||
semanticVersion, err := semver.NewVersion(stringVersion)
|
||||
if err != nil {
|
||||
log.Fatalf("Invalid version number: %v", err)
|
||||
}
|
||||
|
||||
// Extract binary extension
|
||||
binaryExt := path.Ext(*binary)
|
||||
|
||||
// Create the version info configuration container
|
||||
vi := &goversioninfo.VersionInfo{}
|
||||
|
||||
// FixedFileInfo
|
||||
vi.FixedFileInfo.FileOS = "040004" // VOS_NT_WINDOWS32
|
||||
if strings.EqualFold(binaryExt, ".exe") {
|
||||
vi.FixedFileInfo.FileType = "01" // VFT_APP
|
||||
} else if strings.EqualFold(binaryExt, ".dll") {
|
||||
vi.FixedFileInfo.FileType = "02" // VFT_DLL
|
||||
} else {
|
||||
log.Fatalf("Specified binary must have extension .exe or .dll")
|
||||
}
|
||||
// FixedFileInfo.FileVersion
|
||||
vi.FixedFileInfo.FileVersion.Major = int(semanticVersion.Major)
|
||||
vi.FixedFileInfo.FileVersion.Minor = int(semanticVersion.Minor)
|
||||
vi.FixedFileInfo.FileVersion.Patch = int(semanticVersion.Patch)
|
||||
vi.FixedFileInfo.FileVersion.Build = 0
|
||||
// FixedFileInfo.ProductVersion
|
||||
vi.FixedFileInfo.ProductVersion.Major = int(semanticVersion.Major)
|
||||
vi.FixedFileInfo.ProductVersion.Minor = int(semanticVersion.Minor)
|
||||
vi.FixedFileInfo.ProductVersion.Patch = int(semanticVersion.Patch)
|
||||
vi.FixedFileInfo.ProductVersion.Build = 0
|
||||
|
||||
// StringFileInfo
|
||||
vi.StringFileInfo.CompanyName = "https://rclone.org"
|
||||
vi.StringFileInfo.ProductName = "Rclone"
|
||||
vi.StringFileInfo.FileDescription = "Rclone"
|
||||
vi.StringFileInfo.InternalName = (*binary)[:len(*binary)-len(binaryExt)]
|
||||
vi.StringFileInfo.OriginalFilename = *binary
|
||||
vi.StringFileInfo.LegalCopyright = "The Rclone Authors"
|
||||
vi.StringFileInfo.FileVersion = stringVersion
|
||||
vi.StringFileInfo.ProductVersion = stringVersion
|
||||
|
||||
// Icon (only relevant for .exe, not .dll)
|
||||
if *icon != "" && strings.EqualFold(binaryExt, ".exe") {
|
||||
vi.IconPath = *icon
|
||||
}
|
||||
|
||||
// Build native structures from the configuration data
|
||||
vi.Build()
|
||||
|
||||
// Write the native structures as binary data to a buffer
|
||||
vi.Walk()
|
||||
|
||||
// Write the binary data buffer to file
|
||||
if err := vi.WriteSyso(*syso, *arch); err != nil {
|
||||
log.Fatalf(`Failed to generate Windows %s resource system object file for %v with path "%v": %v`, *arch, *binary, *syso, err)
|
||||
}
|
||||
}
|
2
go.mod
2
go.mod
@ -35,6 +35,7 @@ require (
|
||||
github.com/iguanesolutions/go-systemd/v5 v5.1.1
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4
|
||||
github.com/jlaffaye/ftp v0.2.0
|
||||
github.com/josephspurrier/goversioninfo v1.4.0
|
||||
github.com/jzelinskie/whirlpool v0.0.0-20201016144138-0675e54bb004
|
||||
github.com/klauspost/compress v1.17.2
|
||||
github.com/koofr/go-httpclient v0.0.0-20230225102643-5d51a2e9dea6
|
||||
@ -90,6 +91,7 @@ require (
|
||||
github.com/ProtonMail/go-srp v0.0.7 // indirect
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.7.4 // indirect
|
||||
github.com/PuerkitoBio/goquery v1.8.1 // indirect
|
||||
github.com/akavel/rsrc v0.10.2 // indirect
|
||||
github.com/anacrolix/generics v0.0.0-20230911070922-5dd7545c6b13 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
|
5
go.sum
5
go.sum
@ -84,6 +84,8 @@ github.com/aalpar/deheap v0.0.0-20210914013432-0cc84d79dec3 h1:hhdWprfSpFbN7lz3W
|
||||
github.com/aalpar/deheap v0.0.0-20210914013432-0cc84d79dec3/go.mod h1:XaUnRxSCYgL3kkgX0QHIV0D+znljPIDImxlv2kbGv0Y=
|
||||
github.com/abbot/go-http-auth v0.4.0 h1:QjmvZ5gSC7jm3Zg54DqWE/T5m1t2AfDu6QlXJT0EVT0=
|
||||
github.com/abbot/go-http-auth v0.4.0/go.mod h1:Cz6ARTIzApMJDzh5bRMSUou6UMSp0IEXg9km/ci7TJM=
|
||||
github.com/akavel/rsrc v0.10.2 h1:Zxm8V5eI1hW4gGaYsJQUhxpjkENuG91ki8B4zCrvEsw=
|
||||
github.com/akavel/rsrc v0.10.2/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
||||
github.com/anacrolix/dms v1.6.0 h1:v2g1Y+Fc/ICSEc+7M6B92oFcfcqa5LXYPhE4Hcm5tVA=
|
||||
github.com/anacrolix/dms v1.6.0/go.mod h1:5fAMpBcPFG4WQFh91zhf2E7/KYZ3/WmmRAf/WMoL0Q0=
|
||||
github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c=
|
||||
@ -329,6 +331,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/josephspurrier/goversioninfo v1.4.0 h1:Puhl12NSHUSALHSuzYwPYQkqa2E1+7SrtAPJorKK0C8=
|
||||
github.com/josephspurrier/goversioninfo v1.4.0/go.mod h1:JWzv5rKQr+MmW+LvM412ToT/IkYDZjaclF2pKDss8IY=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
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=
|
||||
@ -488,6 +492,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
|
Loading…
Reference in New Issue
Block a user