From 84b4b38585897a91400f2eb355dafc364fe789bc Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Fri, 21 Jun 2024 15:01:56 +0200 Subject: [PATCH] Restore compatibility with Go 1.18 Also test compatibility of fetch_repo and gazelle. --- BUILD.bazel | 8 +++- MODULE.bazel | 4 ++ cmd/fetch_repo/BUILD.bazel | 10 ++++- cmd/fetch_repo/errorscompat.go | 61 +++++++++++++++++++++++++++ cmd/fetch_repo/go_mod_download.go | 2 +- internal/go_repository_tools_srcs.bzl | 1 + 6 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 cmd/fetch_repo/errorscompat.go diff --git a/BUILD.bazel b/BUILD.bazel index e281ea890..44ccd5685 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -1,6 +1,6 @@ load("@bazel_gazelle_is_bazel_module//:defs.bzl", "GAZELLE_IS_BAZEL_MODULE") load("@bazel_skylib//:bzl_library.bzl", "bzl_library") -load("@io_bazel_rules_go//go:def.bzl", "nogo") +load("@io_bazel_rules_go//go:def.bzl", "go_cross_binary", "nogo") load("//:def.bzl", "gazelle", "gazelle_binary") # gazelle:prefix github.com/bazelbuild/bazel-gazelle @@ -38,6 +38,12 @@ gazelle_binary( ], ) +go_cross_binary( + name = "gazelle_local_go1.18", + sdk_version = "1.18", + target = ":gazelle_local", +) + nogo( name = "nogo", vet = True, diff --git a/MODULE.bazel b/MODULE.bazel index 69bff2a7d..d821962eb 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -58,6 +58,10 @@ bazel_dep(name = "bazel_skylib_gazelle_plugin", version = "1.4.1", dev_dependenc bazel_dep(name = "stardoc", version = "0.6.2", dev_dependency = True, repo_name = "io_bazel_stardoc") go_sdk_dev = use_extension("@io_bazel_rules_go//go:extensions.bzl", "go_sdk", dev_dependency = True) +go_sdk_dev.download(version = "1.22.4") + +# Used by compatibility tests, keep as low as possible. +go_sdk_dev.download(version = "1.18.10") # Known to exist since it is instantiated by rules_go itself. use_repo( diff --git a/cmd/fetch_repo/BUILD.bazel b/cmd/fetch_repo/BUILD.bazel index 382a9616b..37e081873 100644 --- a/cmd/fetch_repo/BUILD.bazel +++ b/cmd/fetch_repo/BUILD.bazel @@ -1,10 +1,11 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test") +load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_cross_binary", "go_library", "go_test") go_library( name = "fetch_repo_lib", srcs = [ "clean.go", "copy_tree.go", + "errorscompat.go", "fetch_repo.go", "go_mod_download.go", "module.go", @@ -25,6 +26,13 @@ go_binary( visibility = ["//visibility:public"], ) +# Verify that fetch_repo builds with Go 1.18. +go_cross_binary( + name = "fetch_repo_go1.18", + sdk_version = "1.18", + target = ":fetch_repo", +) + go_test( name = "fetch_repo_test", srcs = ["fetch_repo_test.go"], diff --git a/cmd/fetch_repo/errorscompat.go b/cmd/fetch_repo/errorscompat.go new file mode 100644 index 000000000..694520009 --- /dev/null +++ b/cmd/fetch_repo/errorscompat.go @@ -0,0 +1,61 @@ +// Taken from +// https://github.com/golang/go/blob/20b79fd5775c39061d949569743912ad5e58b0e7/src/errors/join.go +// TODO: Remove when Go 1.20 is the minimum supported version. + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +// Join returns an error that wraps the given errors. +// Any nil error values are discarded. +// Join returns nil if every value in errs is nil. +// The error formats as the concatenation of the strings obtained +// by calling the Error method of each element of errs, with a newline +// between each string. +// +// A non-nil error returned by Join implements the Unwrap() []error method. +func Join(errs ...error) error { + n := 0 + for _, err := range errs { + if err != nil { + n++ + } + } + if n == 0 { + return nil + } + e := &joinError{ + errs: make([]error, 0, n), + } + for _, err := range errs { + if err != nil { + e.errs = append(e.errs, err) + } + } + return e +} + +type joinError struct { + errs []error +} + +func (e *joinError) Error() string { + // Since Join returns nil if every value in errs is nil, + // e.errs cannot be empty. + if len(e.errs) == 1 { + return e.errs[0].Error() + } + + b := []byte(e.errs[0].Error()) + for _, err := range e.errs[1:] { + b = append(b, '\n') + b = append(b, err.Error()...) + } + return string(b) +} + +func (e *joinError) Unwrap() []error { + return e.errs +} diff --git a/cmd/fetch_repo/go_mod_download.go b/cmd/fetch_repo/go_mod_download.go index 35d08f337..4e71fad6f 100644 --- a/cmd/fetch_repo/go_mod_download.go +++ b/cmd/fetch_repo/go_mod_download.go @@ -61,7 +61,7 @@ func runGoModDownload(dl *GoModDownloadResult, dest string, importpath string, v return fmt.Errorf("go mod download output format: `%s %s`: parsing JSON: %q error: %w", cmd.Path, strings.Join(cmd.Args, " "), buf.String(), err) } if dl.Error != "" { - return errors.Join(errors.New(dl.Error), dlErr) + return Join(errors.New(dl.Error), dlErr) } if dlErr != nil { return dlErr diff --git a/internal/go_repository_tools_srcs.bzl b/internal/go_repository_tools_srcs.bzl index 65dda9440..db115f11c 100644 --- a/internal/go_repository_tools_srcs.bzl +++ b/internal/go_repository_tools_srcs.bzl @@ -10,6 +10,7 @@ GO_REPOSITORY_TOOLS_SRCS = [ Label("//cmd/fetch_repo:BUILD.bazel"), Label("//cmd/fetch_repo:clean.go"), Label("//cmd/fetch_repo:copy_tree.go"), + Label("//cmd/fetch_repo:errorscompat.go"), Label("//cmd/fetch_repo:fetch_repo.go"), Label("//cmd/fetch_repo:go_mod_download.go"), Label("//cmd/fetch_repo:module.go"),