diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index 97f66c112..dfaedb31d 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -41,6 +41,7 @@ tasks:
# Regenerate the BUILD files for the test module using Gazelle.
# Also verify -repo_config are generated correctly in gazelle.bash
- rm pkg/BUILD.bazel proto/BUILD.bazel
+ - touch pkg/BUILD.bazel proto/BUILD.bazel # ensure empty pkg/BUILD.bazel exists
- bazel run //:gazelle -- update pkg proto
- bazel run //:gazelle -- pkg proto
build_targets:
diff --git a/.bazelversion b/.bazelversion
new file mode 100644
index 000000000..19b860c18
--- /dev/null
+++ b/.bazelversion
@@ -0,0 +1 @@
+6.4.0
diff --git a/MODULE.bazel b/MODULE.bazel
index 6207d1ccc..4ed18fe1f 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -56,7 +56,6 @@ use_repo(
bazel_dep(name = "bazel_skylib_gazelle_plugin", version = "1.4.1", dev_dependency = True)
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)
# Known to exist since it is instantiated by rules_go itself.
diff --git a/internal/bzlmod/go_deps.bzl b/internal/bzlmod/go_deps.bzl
index f741291d1..24d5ddc2f 100644
--- a/internal/bzlmod/go_deps.bzl
+++ b/internal/bzlmod/go_deps.bzl
@@ -13,14 +13,14 @@
# limitations under the License.
load("//internal:go_repository.bzl", "go_repository")
-load(":go_mod.bzl", "deps_from_go_mod", "sums_from_go_mod")
+load(":go_mod.bzl", "deps_from_go_mod", "parse_go_work", "sums_from_go_mod", "sums_from_go_work")
load(
":default_gazelle_overrides.bzl",
"DEFAULT_BUILD_EXTRA_ARGS_BY_PATH",
"DEFAULT_BUILD_FILE_GENERATION_BY_PATH",
"DEFAULT_DIRECTIVES_BY_PATH",
)
-load(":semver.bzl", "semver")
+load(":semver.bzl", "humanize_comparable_version", "semver")
load(
":utils.bzl",
"drop_nones",
@@ -82,6 +82,12 @@ _GAZELLE_ATTRS = {
),
}
+def go_work_from_label(module_ctx, go_work_label):
+ """Loads deps from a go.work file"""
+ go_work_path = module_ctx.path(go_work_label)
+ go_work_content = module_ctx.read(go_work_path)
+ return parse_go_work(go_work_content, go_work_label)
+
def _fail_on_non_root_overrides(module_ctx, module, tag_class):
if module.is_root:
return
@@ -271,6 +277,78 @@ _go_repository_config = repository_rule(
},
)
+def fail_on_version_conflict(version, previous, module_tag, module_name_to_go_dot_mod_label, go_works, fail_or_warn):
+ """
+ Check if duplicate modules have different versions, and fail with a useful error message if they do.
+
+ Args:
+ version: The version of the module.
+ previous: The previous module object.
+ module_tag: The module tag.
+ module_name_to_go_dot_mod_label: A dictionary mapping module paths to go.mod labels.
+ go_works: A list of go_work objects representing use statements in the go.work file.
+ previous: The previous module object.
+ """
+
+ if not previous:
+ # no previous module, so no possible error
+ return
+
+ if not previous or version == previous.version:
+ # version is the same, skip because we won't error
+ return
+
+ # When using go.work, duplicate dependency versions are possible.
+ # This can cause issues, so we fail with a hopefully actionable error.
+ current_label = module_tag.parent_label
+
+ previous_label = previous.module_tag.parent_label
+
+ corrective_measure = None
+ default_corrective_mesasure = "To correct this:\n 1. manually update: all go.mod files to ensure the versions of '{}' are the same.\n 2. in the folder where you made changes to run: go mod tidy\n 3. run: go work sync.".format(module_tag.path)
+
+ if previous.version[0] == version[0] or str(current_label).endswith("go.work") or str(previous_label).endswith("go.work"):
+ corrective_measure = default_corrective_mesasure
+ else:
+ label = module_name_to_go_dot_mod_label.get(module_tag.path)
+
+ print(dir(previous.module_tag))
+ if label:
+ # if the label is present that means the module_tag is of a go.mod file, which means the correct action may be different.
+
+ # if the duplicate module in question is provided by go.work use statement then only manual intervention can fix it
+ # from_file_tags on go_work represents use statements in the go.work file
+ for from_file_tags in [go_work.from_file_tags for go_work in go_works]:
+ for from_file_tag in from_file_tags:
+ if from_file_tag.go_mod == label:
+ corrective_measure = default_corrective_mesasure
+ break
+ elif previous.module_tag.indirect or module_tag.indirect:
+ # if the dependency indirect, the user will need to manually update go.mod, run go mod tidy in that directory and then run go work sync
+ corrective_measure = default_corrective_mesasure
+ else:
+ # TODO: if the version are v0.8.0 and v0.17.0 go work sync wont work
+ # ensure the corrective measure describes this. Maybe this is limited to indirect dependencies
+ corrective_measure = "To correct this, run:\n 1. go work sync."
+
+ message = "Multiple versions of {} found:\n - {} contains: {}\n - {} contains {}.\n{}".format(module_tag.path, current_label, humanize_comparable_version(version), previous_label, humanize_comparable_version(previous.version), corrective_measure)
+
+ if fail_or_warn:
+ fail(message)
+ else:
+ print(message)
+
+def _fail_if_not_root(module, from_file_tag):
+ if module.is_root != True:
+ fail("go_deps.from_file(go_work = '{}') tag can only be used from a root module but: '{}' is not a root module.".format(from_file_tag.go_work, module.name))
+
+def _fail_if_invalid_from_file_usage(from_file_tag):
+ if (
+ (from_file_tag.go_work == None and from_file_tag.go_mod == None) and
+ (from_file_tag.go_work != None and from_file_tag.go_mod != None)
+ ):
+ fail("go_deps.from_file tag must have either go_work or go_mod attribute, but not both.")
+
def _noop(_):
pass
@@ -329,9 +407,40 @@ def _go_deps_impl(module_ctx):
", ".join([str(tag.go_mod) for tag in module.tags.from_file]),
),
)
+
additional_module_tags = []
+ from_file_tags = []
+ go_works = []
+ module_name_to_go_dot_mod_label = {}
+
for from_file_tag in module.tags.from_file:
- module_path, module_tags_from_go_mod, go_mod_replace_map = deps_from_go_mod(module_ctx, from_file_tag.go_mod)
+ _fail_if_invalid_from_file_usage(from_file_tag)
+
+ if from_file_tag.go_mod:
+ from_file_tags.append(from_file_tag)
+ elif from_file_tag.go_work:
+ _fail_if_not_root(module, from_file_tag)
+
+ go_work = go_work_from_label(module_ctx, from_file_tag.go_work)
+ go_works.append(go_work)
+
+ # this ensures go.work replacements as considered
+ additional_module_tags += [
+ with_replaced_or_new_fields(tag, _is_dev_dependency = False)
+ for tag in go_work.module_tags
+ ]
+
+ for entry, new_sum in sums_from_go_work(module_ctx, from_file_tag.go_work).items():
+ _safe_insert_sum(sums, entry, new_sum)
+
+ replace_map.update(go_work.replace_map)
+ from_file_tags = from_file_tags + go_work.from_file_tags
+ else:
+ fail("Either \"go_mod\" or \"go_work\" must be specified in \"go_deps.from_file\" tags.")
+
+ for from_file_tag in from_file_tags:
+ module_path, module_tags_from_go_mod, go_mod_replace_map, module_name = deps_from_go_mod(module_ctx, from_file_tag.go_mod)
+ module_name_to_go_dot_mod_label[module_name] = from_file_tag.go_mod
is_dev_dependency = _is_dev_dependency(module_ctx, from_file_tag)
additional_module_tags += [
with_replaced_or_new_fields(tag, _is_dev_dependency = is_dev_dependency)
@@ -382,12 +491,12 @@ def _go_deps_impl(module_ctx):
# transitive dependencies have also been declared - we may end up
# resolving them to higher versions, but only compatible ones.
paths = {}
+
for module_tag in module.tags.module + additional_module_tags:
- if module_tag.path in paths:
- fail("Duplicate Go module path \"{}\" in module \"{}\".".format(module_tag.path, module.name))
+ if not module_tag.path in paths:
+ paths[module_tag.path] = None
if module_tag.path in bazel_deps:
continue
- paths[module_tag.path] = None
raw_version = _canonicalize_raw_version(module_tag.version)
# For modules imported from a go.sum, we know which ones are direct
@@ -403,6 +512,14 @@ def _go_deps_impl(module_ctx):
root_module_direct_deps[_repo_name(module_tag.path)] = None
version = semver.to_comparable(raw_version)
+ previous = paths.get(module_tag.path)
+
+ fail_or_warn = len([x for x in module.tags.from_file if x.fail_on_version_conflict == True]) > 0
+
+ # rather then failing, we could do MVS here, or some other heuristic
+ fail_on_version_conflict(version, previous, module_tag, module_name_to_go_dot_mod_label, go_works, fail_or_warn)
+ paths[module_tag.path] = struct(version = version, module_tag = module_tag)
+
if module_tag.path not in module_resolutions or version > module_resolutions[module_tag.path].version:
module_resolutions[module_tag.path] = struct(
repo_name = _repo_name(module_tag.path),
@@ -553,13 +670,14 @@ def _get_sum_from_module(path, module, sums):
entry = (module.replace, module.raw_version)
if entry not in sums:
+ # TODO: if no sum exist, this is probably because a go mod tidy was missed
fail("No sum for {}@{} found".format(path, module.raw_version))
return sums[entry]
def _safe_insert_sum(sums, entry, new_sum):
if entry in sums and new_sum != sums[entry]:
- fail("Multiple mismatching sums for {}@{} found.".format(entry[0], entry[1]))
+ fail("Multiple mismatching sums for {}@{} found. {} vs {}".format(entry[0], entry[1], new_sum, sums[entry]))
sums[entry] = new_sum
def _canonicalize_raw_version(raw_version):
@@ -577,7 +695,9 @@ _config_tag = tag_class(
_from_file_tag = tag_class(
attrs = {
- "go_mod": attr.label(mandatory = True),
+ "go_mod": attr.label(mandatory = False),
+ "go_work": attr.label(mandatory = False),
+ "fail_on_version_conflict": attr.bool(default = True),
},
)
@@ -592,6 +712,10 @@ _module_tag = tag_class(
),
"build_naming_convention": attr.string(doc = """Removed, do not use""", default = ""),
"build_file_proto_mode": attr.string(doc = """Removed, do not use""", default = ""),
+ "parent_label": attr.label(
+ doc = """The label of the go.mod or go.work file that this module was imported from.""",
+ default = Label("//:MODULE.bazel"),
+ ),
},
)
diff --git a/internal/bzlmod/go_mod.bzl b/internal/bzlmod/go_mod.bzl
index 59e134670..024bf170b 100644
--- a/internal/bzlmod/go_mod.bzl
+++ b/internal/bzlmod/go_mod.bzl
@@ -16,6 +16,94 @@ visibility([
"//tests/bzlmod/...",
])
+def _validate_go_version(path, state, tokens, line_no):
+ if len(tokens) == 1:
+ fail("{}:{}: expected another token after 'go'".format(path, line_no))
+ if state["go"] != None:
+ fail("{}:{}: unexpected second 'go' directive".format(path, line_no))
+ if len(tokens) > 2:
+ fail("{}:{}: unexpected token '{}' after '{}'".format(path, line_no, tokens[2], tokens[1]))
+
+def use_spec_to_label(workspace_name, use_directive):
+ if use_directive.find("..") >= 0:
+ fail("go.work use directive: '{}' contains '..' which is not currently supported.".format(use_directive))
+
+ if use_directive.startswith("./"):
+ use_directive = use_directive[2:]
+
+ if use_directive.startswith("."):
+ use_directive = use_directive[1:]
+
+ if use_directive.endswith("/"):
+ use_directive = use_directive[:-1]
+
+ return Label("@@{}//{}:go.mod".format(workspace_name, use_directive))
+
+def parse_go_work(content, go_work_label):
+ # see: https://go.dev/ref/mod#go-work-file
+
+ # Valid directive values understood by this parser never contain tabs or
+ # carriage returns, so we can simplify the parsing below by canonicalizing
+ # whitespace upfront.
+ content = content.replace("\t", " ").replace("\r", " ")
+
+ state = {
+ "go": None,
+ "use": [],
+ "replace": {},
+ }
+
+ current_directive = None
+ for line_no, line in enumerate(content.splitlines(), 1):
+ tokens, _ = _tokenize_line(line, go_work_label.name, line_no)
+
+ if not tokens:
+ continue
+
+ if current_directive:
+ if tokens[0] == ")":
+ current_directive = None
+ elif current_directive == "use":
+ state["use"].append(tokens[0])
+ elif current_directive == "replace":
+ _parse_replace_directive(state, tokens, go_work_label.name, line_no)
+ else:
+ fail("{}:{}: unexpected directive '{}'".format(go_work_label.name, line_no, current_directive))
+ elif tokens[0] == "go":
+ _validate_go_version(go_work_label.name, state, tokens, line_no)
+ go = tokens[1]
+ elif tokens[0] == "replace":
+ if tokens[1] == "(":
+ current_directive = tokens[0]
+ continue
+ else:
+ _parse_replace_directive(state, tokens[1:], go_work_label.name, line_no)
+ elif tokens[0] == "use":
+ if len(tokens) != 2:
+ fail("{}:{}: expected path or block in 'use' directive".format(go_work_label.name, line_no))
+ elif tokens[1] == "(":
+ current_directive = tokens[0]
+ continue
+ else:
+ state["use"].append(tokens[1])
+ else:
+ fail("{}:{}: unexpected directive '{}'".format(go_work_label.name, line_no, tokens[0]))
+
+ major, minor = go.split(".")[:2]
+
+ go_mods = [use_spec_to_label(go_work_label.workspace_name, use) for use in state["use"]]
+ from_file_tags = [struct(go_mod = go_mod, _is_dev_dependency = False) for go_mod in go_mods]
+
+ module_tags = [struct(version = mod.version, path = mod.to_path, parent_label = go_work_label, indirect = False) for mod in state["replace"].values()]
+
+ return struct(
+ go = (int(major), int(minor)),
+ from_file_tags = from_file_tags,
+ replace_map = state["replace"],
+ module_tags = module_tags,
+ use = state["use"],
+ )
+
def deps_from_go_mod(module_ctx, go_mod_label):
"""Loads the entries from a go.mod file.
@@ -45,9 +133,10 @@ def deps_from_go_mod(module_ctx, go_mod_label):
path = require.path,
version = require.version,
indirect = require.indirect,
+ parent_label = go_mod_label,
))
- return go_mod.module, deps, go_mod.replace_map
+ return go_mod.module, deps, go_mod.replace_map, go_mod.module
def parse_go_mod(content, path):
# See https://go.dev/ref/mod#go-mod-file.
@@ -79,13 +168,8 @@ def parse_go_mod(content, path):
# The 'go' directive only has a single-line form and is thus parsed
# here rather than in _parse_directive.
if tokens[0] == "go":
- if len(tokens) == 1:
- fail("{}:{}: expected another token after 'go'".format(path, line_no))
- if state["go"] != None:
- fail("{}:{}: unexpected second 'go' directive".format(path, line_no))
+ _validate_go_version(path, state, tokens, line_no)
state["go"] = tokens[1]
- if len(tokens) > 2:
- fail("{}:{}: unexpected token '{}' after '{}'".format(path, line_no, tokens[2], tokens[1]))
if tokens[1] == "(":
current_directive = tokens[0]
@@ -139,37 +223,41 @@ def _parse_directive(state, directive, tokens, comment, path, line_no):
indirect = comment == "indirect",
))
elif directive == "replace":
- # A replace directive might use a local file path beginning with ./ or ../
- # These are not supported with gazelle~go_deps.
- if (len(tokens) == 3 and tokens[2][0] == ".") or (len(tokens) > 3 and tokens[3][0] == "."):
- fail("{}:{}: local file path not supported in replace directive: '{}'".format(path, line_no, tokens[2]))
-
- # replacements key off of the from_path
- from_path = tokens[0]
-
- # pattern: replace from_path => to_path to_version
- if len(tokens) == 4 and tokens[1] == "=>":
- state["replace"][from_path] = struct(
- from_version = None,
- to_path = tokens[2],
- version = _canonicalize_raw_version(tokens[3]),
- )
- # pattern: replace from_path from_version => to_path to_version
- elif len(tokens) == 5 and tokens[2] == "=>":
- state["replace"][from_path] = struct(
- from_version = _canonicalize_raw_version(tokens[1]),
- to_path = tokens[3],
- version = _canonicalize_raw_version(tokens[4]),
- )
- else:
- fail(
- "{}:{}: replace directive must follow pattern: ".format(path, line_no) +
- "'replace from_path from_version => to_path to_version' or " +
- "'replace from_path => to_path to_version'"
- )
+ _parse_replace_directive(state, tokens, path, line_no)
# TODO: Handle exclude.
+def _parse_replace_directive(state, tokens, path, line_no):
+ # A replace directive might use a local file path beginning with ./ or ../
+ # These are not supported with gazelle~go_deps.
+ if (len(tokens) == 3 and tokens[2][0] == ".") or (len(tokens) > 3 and tokens[3][0] == "."):
+ fail("{}:{}: local file path not supported in replace directive: '{}'".format(path, line_no, tokens[2]))
+
+ # replacements key off of the from_path
+ from_path = tokens[0]
+
+ # pattern: replace from_path => to_path to_version
+ if len(tokens) == 4 and tokens[1] == "=>":
+ state["replace"][from_path] = struct(
+ from_version = None,
+ to_path = tokens[2],
+ version = _canonicalize_raw_version(tokens[3]),
+ )
+ # pattern: replace from_path from_version => to_path to_version
+
+ elif len(tokens) == 5 and tokens[2] == "=>":
+ state["replace"][from_path] = struct(
+ from_version = _canonicalize_raw_version(tokens[1]),
+ to_path = tokens[3],
+ version = _canonicalize_raw_version(tokens[4]),
+ )
+ else:
+ fail(
+ "{}:{}: replace directive must follow pattern: ".format(path, line_no) +
+ "'replace from_path from_version => to_path to_version' or " +
+ "'replace from_path => to_path to_version'",
+ )
+
def _tokenize_line(line, path, line_no):
tokens = []
r = line
@@ -240,16 +328,37 @@ def sums_from_go_mod(module_ctx, go_mod_label):
"""
_check_go_mod_name(go_mod_label.name)
- # We go through a Label so that the module extension is restarted if go.sum
+ return parse_sumfile(module_ctx, go_mod_label, "go.sum")
+
+def sums_from_go_work(module_ctx, go_work_label):
+ """Loads the entries from a go.work.sum file given a go.workLabel.
+
+ Args:
+ module_ctx: a https://bazel.build/rules/lib/module_ctx object
+ passed from the MODULE.bazel call.
+ go_work_label: a Label for a `go.work` file. This label is used
+ to find the associated `go.work.sum` file.
+
+ Returns:
+ A Dict[(string, string) -> (string)] is retruned where each entry
+ is defined by a Go Module's sum:
+ (path, version) -> (sum)
+ """
+ _check_go_work_name(go_work_label.name)
+
+ return parse_sumfile(module_ctx, go_work_label, "go.work.sum")
+
+def parse_sumfile(module_ctx, label, somefile):
+ # We go through a Label so that the module extension is restarted if the sumfile
# changes. We have to use a canonical label as we may not have visibility
- # into the module that provides the go.sum.
- go_sum_label = Label("@@{}//{}:{}".format(
- go_mod_label.workspace_name,
- go_mod_label.package,
- "go.sum",
+ # into the module that provides the sumfile
+ sum_label = Label("@@{}//{}:{}".format(
+ label.workspace_name,
+ label.package,
+ somefile,
))
- go_sum_content = module_ctx.read(go_sum_label)
- return parse_go_sum(go_sum_content)
+ sum_content = module_ctx.read(sum_label)
+ return parse_go_sum(sum_content)
def parse_go_sum(content):
hashes = {}
@@ -264,6 +373,10 @@ def _check_go_mod_name(name):
if name != "go.mod":
fail("go_deps.from_file requires a 'go.mod' file, not '{}'".format(name))
+def _check_go_work_name(name):
+ if name != "go.work":
+ fail("go_deps.from_file requires a 'go.work' file, not '{}'".format(name))
+
def _canonicalize_raw_version(raw_version):
if raw_version.startswith("v"):
return raw_version[1:]
diff --git a/internal/bzlmod/semver.bzl b/internal/bzlmod/semver.bzl
index d79a4f4bf..cebd94a2d 100644
--- a/internal/bzlmod/semver.bzl
+++ b/internal/bzlmod/semver.bzl
@@ -78,3 +78,28 @@ def _semver_to_comparable(v, *, relaxed = False):
semver = struct(
to_comparable = _semver_to_comparable,
)
+
+def humanize_comparable_version(version):
+ """
+ Returns a human-readable representation of a comparable version object.
+
+ This is useful for providing more helpful error messages.
+
+ Please note, this is lossy as + meta segments are replaced with sentinal value to preserve expected sorting
+
+ Args:
+ version: The comparable version object.
+
+ Returns:
+ A human-readable representation of the version.
+ """
+ core = [_flatten_segment(segment) for segment in version[0]]
+ meta = [_flatten_segment(segment) for segment in version[1] if segment[0] != "{"]
+ result = ".".join(core)
+
+ if (len(meta) > 0):
+ result += "-" + ".".join(meta)
+ return "v" + result
+
+def _flatten_segment(segment):
+ return "".join([str(atom) for atom in segment])
diff --git a/repository.md b/repository.md
index ea7ea2175..406c69d4f 100644
--- a/repository.md
+++ b/repository.md
@@ -91,7 +91,7 @@ git_repository(
| commit | The git commit to check out. Either `commit` or `tag` may be specified. | String | optional | `""` |
| overlay | A set of files to copy into the downloaded repository. The keys in this dictionary are Bazel labels that point to the files to copy. These must be fully qualified labels (i.e., `@repo//pkg:name`) because relative labels are interpreted in the checked out repository, not the repository containing the WORKSPACE file. The values in this dictionary are root-relative paths where the overlay files should be written.
It's convenient to store the overlay dictionaries for all repositories in a separate .bzl file. See Gazelle's `manifest.bzl`_ for an example. | Dictionary: Label -> String | optional | `{}` |
| remote | The remote repository to download. | String | required | |
-| repo_mapping | In `WORKSPACE` context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.
For example, an entry `"@foo": "@bar"` declares that, for any time this repository depends on `@foo` (such as a dependency on `@foo//some:target`, it should actually resolve that dependency within globally-declared `@bar` (`@bar//some:target`).
This attribute is _not_ supported in `MODULE.bazel` context (when invoking a repository rule inside a module extension's implementation function). | Dictionary: String -> String | optional | |
+| repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.
For example, an entry `"@foo": "@bar"` declares that, for any time this repository depends on `@foo` (such as a dependency on `@foo//some:target`, it should actually resolve that dependency within globally-declared `@bar` (`@bar//some:target`). | Dictionary: String -> String | required | |
| tag | The git tag to check out. Either `commit` or `tag` may be specified. | String | optional | `""` |
@@ -172,7 +172,7 @@ go_repository(
| :------------- | :------------- | :------------- | :------------- | :------------- |
| name | A unique name for this repository. | Name | required | |
| auth_patterns | An optional dict mapping host names to custom authorization patterns.
If a URL's host name is present in this dict the value will be used as a pattern when generating the authorization header for the http request. This enables the use of custom authorization schemes used in a lot of common cloud storage providers.
The pattern currently supports 2 tokens: <login>
and <password>
, which are replaced with their equivalent value in the netrc file for the same host name. After formatting, the result is set as the value for the Authorization
field of the HTTP request.
Example attribute and netrc for a http download to an oauth2 enabled API using a bearer token:
auth_patterns = { "storage.cloudprovider.com": "Bearer <password>" }
machine storage.cloudprovider.com password RANDOM-TOKEN
Authorization: Bearer RANDOM-TOKEN| Dictionary: String -> String | optional | `{}` | -| build_config | A file that Gazelle should read to learn about external repositories before generating build files. This is useful for dependency resolution. For example, a `go_repository` rule in this file establishes a mapping between a repository name like `golang.org/x/tools` and a workspace name like `org_golang_x_tools`. Workspace directives like `# gazelle:repository_macro` are recognized.
For example, an entry `"@foo": "@bar"` declares that, for any time this repository depends on `@foo` (such as a dependency on `@foo//some:target`, it should actually resolve that dependency within globally-declared `@bar` (`@bar//some:target`). | Dictionary: String -> String | required | |
| sha256 | If the repository is downloaded via HTTP (`urls` is set), this is the SHA-256 sum of the downloaded archive. When set, Bazel will verify the archive against this sum before extracting it. For example, an entry `"@foo": "@bar"` declares that, for any time this repository depends on `@foo` (such as a dependency on `@foo//some:target`, it should actually resolve that dependency within globally-declared `@bar` (`@bar//some:target`). | Dictionary: String -> String | required | |
| sha256 | The SHA-256 sum of the downloaded archive. When set, Bazel will verify the archive against this sum before extracting it.
**CAUTION:** Do not use this with services that prepare source archives on demand, such as codeload.github.com. Any minor change in the server software can cause differences in file order, alignment, and compression that break SHA-256 sums. | String | optional | `""` |
| strip_prefix | If the repository is downloaded via HTTP (`urls` is set), this is a directory prefix to strip. See [`http_archive.strip_prefix`]. | String | optional | `""` |
| sum | A hash of the module contents. In module mode, `go_repository` will verify the downloaded module matches this sum. May only be set when `version` is also set.
A value for `sum` may be found in the `go.sum` file or by running `go mod download -json
It's convenient to store the overlay dictionaries for all repositories in a separate .bzl file. See Gazelle's `manifest.bzl`_ for an example. | Dictionary: Label -> String | optional | `{}` |
-| repo_mapping | In `WORKSPACE` context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.
For example, an entry `"@foo": "@bar"` declares that, for any time this repository depends on `@foo` (such as a dependency on `@foo//some:target`, it should actually resolve that dependency within globally-declared `@bar` (`@bar//some:target`).
This attribute is _not_ supported in `MODULE.bazel` context (when invoking a repository rule inside a module extension's implementation function). | Dictionary: String -> String | optional | |
+| repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.
**CAUTION:** Do not use this with services that prepare source archives on demand, such as codeload.github.com. Any minor change in the server software can cause differences in file order, alignment, and compression that break SHA-256 sums. | String | optional | `""` |
| strip_prefix | A directory prefix to strip. See [http_archive.strip_prefix]. | String | optional | `""` |
| type | One of `"zip"`, `"tar.gz"`, `"tgz"`, `"tar.bz2"`, `"tar.xz"`.
The file format of the repository archive. This is normally inferred from the downloaded file name. | String | optional | `""` |
diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel
index e2ebfeaf6..17f1aa607 100644
--- a/tests/BUILD.bazel
+++ b/tests/BUILD.bazel
@@ -3,7 +3,6 @@ load(
"gazelle_binary",
"gazelle_generation_test",
)
-
load("//tests:tools.bzl", "get_binary")
# Exclude this entire directly from having anything gnerated by Gazelle. That
diff --git a/tests/bcr/MODULE.bazel b/tests/bcr/MODULE.bazel
index cc0026e03..08ef0d7a1 100644
--- a/tests/bcr/MODULE.bazel
+++ b/tests/bcr/MODULE.bazel
@@ -15,7 +15,7 @@ local_path_override(
)
bazel_dep(name = "protobuf", version = "23.1", repo_name = "my_protobuf")
-bazel_dep(name = "rules_go", version = "0.42.0", repo_name = "my_rules_go")
+bazel_dep(name = "rules_go", version = "0.44.0", repo_name = "my_rules_go")
bazel_dep(name = "rules_proto", version = "6.0.0-rc2", repo_name = "my_rules_proto")
# This bazel_dep provides the Go dependency github.com/cloudflare/circl, which requires custom
@@ -25,6 +25,8 @@ bazel_dep(name = "circl", version = "1.3.7")
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
# Validate a go.mod replace directive works.
+# Validate a full go workspace
+go_deps.from_file(go_work = "//:go.work")
go_deps.from_file(go_mod = "//:go.mod")
go_deps.gazelle_default_attributes(
build_file_generation = "on",
@@ -56,8 +58,8 @@ go_deps.gazelle_override(
# respected.
go_deps.module(
path = "github.com/stretchr/testify",
- sum = "h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=",
- version = "v1.8.0",
+ sum = "h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=",
+ version = "v1.8.4",
)
go_deps.gazelle_override(
directives = [
@@ -118,6 +120,7 @@ go_deps.module(
)
use_repo(
go_deps,
+ "com_github_99designs_gqlgen",
"com_github_bazelbuild_buildtools",
"com_github_bmatcuk_doublestar_v4",
"com_github_datadog_sketches_go",
@@ -127,8 +130,6 @@ use_repo(
"com_github_stretchr_testify",
"org_golang_google_protobuf",
"org_golang_x_sys",
- # It is not necessary to list transitive dependencies here, only direct ones.
- # "in_gopkg_yaml_v3",
# Only used for testing.
"bazel_gazelle_go_repository_config",
)
diff --git a/tests/bcr/go.mod b/tests/bcr/go.mod
index d4f1957f5..8f806b156 100644
--- a/tests/bcr/go.mod
+++ b/tests/bcr/go.mod
@@ -1,25 +1,3 @@
-// This will stop go mod from descending into this directory.
module github.com/bazelbuild/bazel-gazelle/tests/bcr
-go 1.19
-
-// Validate go.mod replace directives can be properly used:
-replace github.com/bmatcuk/doublestar/v4 => github.com/bmatcuk/doublestar v1.3.4
-
-require (
- github.com/DataDog/sketches-go v1.4.1
- github.com/bazelbuild/rules_go v0.39.1
- github.com/bmatcuk/doublestar/v4 v4.6.0
- github.com/cloudflare/circl v1.3.7
- github.com/envoyproxy/protoc-gen-validate v1.0.1
- github.com/fmeum/dep_on_gazelle v1.0.0
- github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2
- golang.org/x/sys v0.15.0
- google.golang.org/protobuf v1.32.0
-)
-
-require (
- github.com/bazelbuild/bazel-gazelle v0.30.0 // indirect
- github.com/kr/text v0.2.0 // indirect
- github.com/pmezard/go-difflib v1.0.0 // indirect
-)
+go 1.21.5
diff --git a/tests/bcr/go.work b/tests/bcr/go.work
new file mode 100644
index 000000000..66fd10058
--- /dev/null
+++ b/tests/bcr/go.work
@@ -0,0 +1,6 @@
+go 1.21.5
+
+use (
+ ./pkg
+ ./tools
+)
diff --git a/tests/bcr/go.work.sum b/tests/bcr/go.work.sum
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/bcr/pkg/go.mod b/tests/bcr/pkg/go.mod
new file mode 100644
index 000000000..671161724
--- /dev/null
+++ b/tests/bcr/pkg/go.mod
@@ -0,0 +1,29 @@
+module github.com/bazelbuild/bazel-gazelle/tests/bcr/pkg
+
+go 1.21.5
+
+require (
+ github.com/DataDog/sketches-go v1.4.4
+ github.com/bazelbuild/buildtools v0.0.0-20240207142252-03bf520394af
+ github.com/bazelbuild/rules_go v0.44.0
+ github.com/bmatcuk/doublestar/v4 v4.6.1
+ github.com/cloudflare/circl v1.3.7
+ github.com/envoyproxy/protoc-gen-validate v1.0.4
+ github.com/fmeum/dep_on_gazelle v1.0.0
+ github.com/google/safetext v0.0.0-20240104143208-7a7d9b3d812f
+ github.com/stretchr/testify v1.8.4
+ golang.org/x/sys v0.17.0
+)
+
+require (
+ github.com/bazelbuild/bazel-gazelle v0.30.0 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/google/uuid v1.3.0 // indirect
+ github.com/pborman/uuid v1.2.1 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ google.golang.org/protobuf v1.32.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+)
+
+// Validate go.mod replace directives can be properly used:
+replace github.com/bmatcuk/doublestar/v4 => github.com/bmatcuk/doublestar v1.3.4
diff --git a/tests/bcr/pkg/go.sum b/tests/bcr/pkg/go.sum
new file mode 100644
index 000000000..d3b2c1dc6
--- /dev/null
+++ b/tests/bcr/pkg/go.sum
@@ -0,0 +1,119 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/DataDog/sketches-go v1.4.4 h1:dF52vzXRFSPOj2IjXSWLvXq3jubL4CI69kwYjJ1w5Z8=
+github.com/DataDog/sketches-go v1.4.4/go.mod h1:XR0ns2RtEEF09mDKXiKZiQg+nfZStrq1ZuL1eezeZe0=
+github.com/bazelbuild/bazel-gazelle v0.30.0 h1:q9XLWQSCA5NZPJ98WFqicHkq6fxrDPnfvMO1XycQBMg=
+github.com/bazelbuild/bazel-gazelle v0.30.0/go.mod h1:6RxhjM1v/lTpD3JlMpKUCcdus4tvdqsqdfbjYi+czYs=
+github.com/bazelbuild/buildtools v0.0.0-20240207142252-03bf520394af h1:wycIfuqZJzkloRT+fcazTM3NjvAMyAi1qC2QXmEZP4s=
+github.com/bazelbuild/buildtools v0.0.0-20240207142252-03bf520394af/go.mod h1:689QdV3hBP7Vo9dJMmzhoYIyo/9iMhEmHkJcnaPRCbo=
+github.com/bazelbuild/rules_go v0.45.1 h1:kuiC/mK1SKoZ0lyX5gD9uVBGFWOoXT3I4W/ose6Jouo=
+github.com/bazelbuild/rules_go v0.45.1/go.mod h1:Dhcz716Kqg1RHNWos+N6MlXNkjNP2EwZQ0LukRKJfMs=
+github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
+github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
+github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
+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/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
+github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
+github.com/fmeum/dep_on_gazelle v1.0.0 h1:7gEtQ2CoD77tYca+1iUnKjIBUZ4mX7mZwjdWp3uuN/E=
+github.com/fmeum/dep_on_gazelle v1.0.0/go.mod h1:VYCjwfsyRHOJL8oenaEjhIzgM7Oj70iTxgJ2RfXbYr0=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+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.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+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.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.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
+github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/safetext v0.0.0-20240104143208-7a7d9b3d812f h1:o2yGZLlsOj5H5uvtQNEdi6DeA0GbUP3lm0gWW5RvY0s=
+github.com/google/safetext v0.0.0-20240104143208-7a7d9b3d812f/go.mod h1:H3K1Iu/utuCfa10JO+GsmKUYSWi7ug57Rk6GaDRHaaQ=
+github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
+github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
+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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+go.starlark.net v0.0.0-20210223155950-e043a3d3c984/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
+golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+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-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+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.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.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
+google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/tests/bcr/test_dep/MODULE.bazel b/tests/bcr/test_dep/MODULE.bazel
index c2278edf2..340ade58b 100644
--- a/tests/bcr/test_dep/MODULE.bazel
+++ b/tests/bcr/test_dep/MODULE.bazel
@@ -28,7 +28,6 @@ go_deps.module_override(
],
path = "github.com/stretchr/testify",
)
-
go_deps.module(
indirect = True,
path = "gopkg.in/yaml.v3",
@@ -36,10 +35,10 @@ go_deps.module(
version = "v3.0.1",
)
go_deps.gazelle_override(
- path = "gopkg.in/yaml.v3",
directives = [
"gazelle:go_naming_convention import",
],
+ path = "gopkg.in/yaml.v3",
)
go_deps.module(
indirect = True,
diff --git a/tests/bcr/test_dep/go.mod b/tests/bcr/test_dep/go.mod
new file mode 100644
index 000000000..b990a2ae3
--- /dev/null
+++ b/tests/bcr/test_dep/go.mod
@@ -0,0 +1,11 @@
+module github.com/bazelbuild/bazel-gazelle/tests/bcr/test_dep
+
+go 1.21.5
+
+require github.com/stretchr/testify v1.8.4
+
+require (
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/tests/bcr/test_dep/go.sum b/tests/bcr/test_dep/go.sum
new file mode 100644
index 000000000..fa4b6e682
--- /dev/null
+++ b/tests/bcr/test_dep/go.sum
@@ -0,0 +1,10 @@
+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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/tests/bcr/tools/go.mod b/tests/bcr/tools/go.mod
index 29249d341..2646af128 100644
--- a/tests/bcr/tools/go.mod
+++ b/tests/bcr/tools/go.mod
@@ -4,7 +4,7 @@ go 1.21.0
require (
github.com/99designs/gqlgen v0.17.40
- github.com/bazelbuild/buildtools v0.0.0-20231115204819-d4c9dccdfbb1
+ github.com/bazelbuild/buildtools v0.0.0-20240207142252-03bf520394af
)
require (
@@ -18,9 +18,9 @@ require (
github.com/vektah/gqlparser/v2 v2.5.10 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/mod v0.10.0 // indirect
- golang.org/x/sys v0.8.0 // indirect
+ golang.org/x/sys v0.17.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/tools v0.9.3 // indirect
- google.golang.org/protobuf v1.30.0 // indirect
+ google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/tests/bcr/tools/go.sum b/tests/bcr/tools/go.sum
index 0804de90c..589dc7022 100644
--- a/tests/bcr/tools/go.sum
+++ b/tests/bcr/tools/go.sum
@@ -8,8 +8,8 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNg
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
-github.com/bazelbuild/buildtools v0.0.0-20231115204819-d4c9dccdfbb1 h1:2Gc2Q6hVR1SJ8bBI9Ybzoggp8u/ED2WkM4MfvEIn9+c=
-github.com/bazelbuild/buildtools v0.0.0-20231115204819-d4c9dccdfbb1/go.mod h1:689QdV3hBP7Vo9dJMmzhoYIyo/9iMhEmHkJcnaPRCbo=
+github.com/bazelbuild/buildtools v0.0.0-20240207142252-03bf520394af h1:wycIfuqZJzkloRT+fcazTM3NjvAMyAi1qC2QXmEZP4s=
+github.com/bazelbuild/buildtools v0.0.0-20240207142252-03bf520394af/go.mod h1:689QdV3hBP7Vo9dJMmzhoYIyo/9iMhEmHkJcnaPRCbo=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
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=
@@ -90,8 +90,8 @@ golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
+golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
@@ -122,8 +122,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
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.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
-google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
+google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
diff --git a/tests/bzlmod/go_deps_test.bzl b/tests/bzlmod/go_deps_test.bzl
new file mode 100644
index 000000000..796d02eb7
--- /dev/null
+++ b/tests/bzlmod/go_deps_test.bzl
@@ -0,0 +1,9 @@
+load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")
+load("//internal/bzlmod:go_deps.bzl", "fail_on_version_conflict")
+
+def _go_sum_test_impl(ctx):
+ env = unittest.begin(ctx)
+ asserts.equals(env, _EXPECTED_GO_SUM_PARSE_RESULT, parse_go_sum(_GO_SUM_CONTENT))
+ return unittest.end(env)
+
+go_sum_test = unittest.make(_go_sum_test_impl)
diff --git a/tests/bzlmod/go_mod_test.bzl b/tests/bzlmod/go_mod_test.bzl
index c4287074a..68cfb1105 100644
--- a/tests/bzlmod/go_mod_test.bzl
+++ b/tests/bzlmod/go_mod_test.bzl
@@ -1,5 +1,5 @@
load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")
-load("//internal/bzlmod:go_mod.bzl", "parse_go_mod", "parse_go_sum")
+load("//internal/bzlmod:go_mod.bzl", "parse_go_mod", "parse_go_sum", "parse_go_work", "use_spec_to_label")
_GO_MOD_CONTENT = """ go 1.18
@@ -64,6 +64,18 @@ _EXPECTED_GO_MOD_21_PARSE_RESULT = struct(
require = (),
)
+def _use_spec_to_label_test_impl(ctx):
+ env = unittest.begin(ctx)
+
+ asserts.equals(env, Label("@@org_example//:go.mod"), use_spec_to_label("org_example", "."))
+ asserts.equals(env, Label("@@org_example//go_mod_one:go.mod"), use_spec_to_label("org_example", "./go_mod_one"))
+ asserts.equals(env, Label("@@org_example//go_mod_one:go.mod"), use_spec_to_label("org_example", "./go_mod_one/"))
+ asserts.equals(env, Label("@@org_example//bar/go_mod_one:go.mod"), use_spec_to_label("org_example", "./bar/go_mod_one"))
+
+ return unittest.end(env)
+
+use_spec_test = unittest.make(_use_spec_to_label_test_impl)
+
def _go_mod_21_test_impl(ctx):
env = unittest.begin(ctx)
asserts.equals(env, _EXPECTED_GO_MOD_21_PARSE_RESULT, parse_go_mod(_GO_MOD_21_CONTENT, "/go.mod"))
@@ -91,10 +103,52 @@ def _go_sum_test_impl(ctx):
go_sum_test = unittest.make(_go_sum_test_impl)
+_GO_WORK_CONTENT = """go 1.18
+use ./go_mod_one
+use (
+ ./foo/go_mod_two
+ ./bar/baz/go_mod_three
+)
+
+replace github.com/go-fsnotify/fsnotify => github.com/fsnotify/fsnotify v1.4.2
+replace github.com/bmatcuk/doublestar/v4 v4.0.2 => github.com/bmatcuk/doublestar/v4 v4.0.3
+"""
+
+_EXPECTED_GO_WORK_PARSE_RESULT = struct(
+ go = (1, 18),
+ from_file_tags = [
+ struct(_is_dev_dependency = False, go_mod = Label("//go_mod_one:go.mod")),
+ struct(_is_dev_dependency = False, go_mod = Label("//foo/go_mod_two:go.mod")),
+ struct(_is_dev_dependency = False, go_mod = Label("//bar/baz/go_mod_three:go.mod")),
+ ],
+ module_tags = [
+ struct(indirect = False, parent_label = Label("//:go.work"), path = "github.com/fsnotify/fsnotify", version = "1.4.2"),
+ struct(indirect = False, parent_label = Label("//:go.work"), path = "github.com/bmatcuk/doublestar/v4", version = "4.0.3"),
+ ],
+ replace_map = {
+ "github.com/go-fsnotify/fsnotify": struct(from_version = None, to_path = "github.com/fsnotify/fsnotify", version = "1.4.2"),
+ "github.com/bmatcuk/doublestar/v4": struct(from_version = "4.0.2", to_path = "github.com/bmatcuk/doublestar/v4", version = "4.0.3"),
+ },
+ use = [
+ "./go_mod_one",
+ "./foo/go_mod_two",
+ "./bar/baz/go_mod_three",
+ ],
+)
+
+def _go_work_test_impl(ctx):
+ env = unittest.begin(ctx)
+ asserts.equals(env, _EXPECTED_GO_WORK_PARSE_RESULT, parse_go_work(_GO_WORK_CONTENT, Label("@@//:go.work")))
+ return unittest.end(env)
+
+go_work_test = unittest.make(_go_work_test_impl)
+
def go_mod_test_suite(name):
unittest.suite(
name,
go_mod_test,
go_mod_21_test,
go_sum_test,
+ go_work_test,
+ use_spec_test,
)
diff --git a/tests/bzlmod/semver_test.bzl b/tests/bzlmod/semver_test.bzl
index 610d3cfce..0f0bd30dc 100644
--- a/tests/bzlmod/semver_test.bzl
+++ b/tests/bzlmod/semver_test.bzl
@@ -1,5 +1,5 @@
load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")
-load("//internal/bzlmod:semver.bzl", "semver")
+load("//internal/bzlmod:semver.bzl", "humanize_comparable_version", "semver")
_SORTED_TEST_VERSIONS = [
"0.1-a",
@@ -77,8 +77,23 @@ def _semver_test_impl(ctx):
semver_test = unittest.make(_semver_test_impl)
+def _humanize_test_impl(ctx):
+ env = unittest.begin(ctx)
+
+ # remove everything after and including the frist + as it is not preserved in a comparable
+ RESTORABLE_VERSIONS = [version.split("+")[0] for version in _SORTED_TEST_VERSIONS]
+
+ for version in RESTORABLE_VERSIONS:
+ humanized = humanize_comparable_version(semver.to_comparable(version, relaxed = RESTORABLE_VERSIONS))
+ asserts.equals(env, "v" + version, humanized)
+
+ return unittest.end(env)
+
+humanize_test = unittest.make(_humanize_test_impl)
+
def semver_test_suite(name):
unittest.suite(
name,
semver_test,
+ humanize_test,
)
diff --git a/tests/bzlmod/utils_test.bzl b/tests/bzlmod/utils_test.bzl
index 99239822f..87cd9f98b 100644
--- a/tests/bzlmod/utils_test.bzl
+++ b/tests/bzlmod/utils_test.bzl
@@ -11,7 +11,7 @@ _EXPECT_REPLACED_STRUCT = struct(
direct = True,
path = "github.com/bazelbuild/buildtools",
replace = "path/to/add/replace",
- version = "v1.2.2"
+ version = "v1.2.2",
)
def _with_replaced_or_new_fields_test_impl(ctx):