diff --git a/cmd/fetch_repo/BUILD.bazel b/cmd/fetch_repo/BUILD.bazel
index c488904c4..4e089c907 100644
--- a/cmd/fetch_repo/BUILD.bazel
+++ b/cmd/fetch_repo/BUILD.bazel
@@ -3,8 +3,11 @@ load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
go_library(
name = "fetch_repo_lib",
srcs = [
+ "copy_tree.go",
"fetch_repo.go",
+ "go_mod_download.go",
"module.go",
+ "path.go",
"vcs.go",
],
importpath = "github.com/bazelbuild/bazel-gazelle/cmd/fetch_repo",
@@ -33,9 +36,12 @@ filegroup(
testonly = True,
srcs = [
"BUILD.bazel",
+ "copy_tree.go",
"fetch_repo.go",
"fetch_repo_test.go",
+ "go_mod_download.go",
"module.go",
+ "path.go",
"vcs.go",
],
visibility = ["//visibility:public"],
diff --git a/cmd/fetch_repo/copy_tree.go b/cmd/fetch_repo/copy_tree.go
new file mode 100644
index 000000000..1d2bf4d9c
--- /dev/null
+++ b/cmd/fetch_repo/copy_tree.go
@@ -0,0 +1,59 @@
+/* Copyright 2019 The Bazel Authors. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package main
+
+import (
+ "io"
+ "os"
+ "path/filepath"
+)
+
+func copyTree(destRoot, srcRoot string) error {
+ return filepath.Walk(srcRoot, func(src string, info os.FileInfo, e error) (err error) {
+ if e != nil {
+ return e
+ }
+ rel, err := filepath.Rel(srcRoot, src)
+ if err != nil {
+ return err
+ }
+ if rel == "." {
+ return nil
+ }
+ dest := filepath.Join(destRoot, rel)
+
+ if info.IsDir() {
+ return os.Mkdir(dest, 0o777)
+ } else {
+ r, err := os.Open(src)
+ if err != nil {
+ return err
+ }
+ defer r.Close()
+ w, err := os.Create(dest)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if cerr := w.Close(); err == nil && cerr != nil {
+ err = cerr
+ }
+ }()
+ _, err = io.Copy(w, r)
+ return err
+ }
+ })
+}
diff --git a/cmd/fetch_repo/fetch_repo.go b/cmd/fetch_repo/fetch_repo.go
index e45a9260a..3406ec944 100644
--- a/cmd/fetch_repo/fetch_repo.go
+++ b/cmd/fetch_repo/fetch_repo.go
@@ -4,7 +4,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
+http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
@@ -26,14 +26,14 @@ package main
import (
"flag"
- "log"
-
"golang.org/x/tools/go/vcs"
+ "log"
)
var (
// Common flags
importpath = flag.String("importpath", "", "Go importpath to the repository fetch")
+ path = flag.String("path", "", "path to a local go module")
dest = flag.String("dest", "", "destination directory")
// Repository flags
@@ -54,9 +54,11 @@ func main() {
log.SetPrefix("fetch_repo: ")
flag.Parse()
- if *importpath == "" {
+
+ if *importpath == "" && *path == "" {
log.Fatal("-importpath must be set")
}
+
if *dest == "" {
log.Fatal("-dest must be set")
}
@@ -64,7 +66,31 @@ func main() {
log.Fatal("fetch_repo does not accept positional arguments")
}
- if *version != "" {
+ if *path != "" {
+ if *importpath != "" {
+ log.Fatal("-importpath must not be set")
+ }
+ if *remote != "" {
+ log.Fatal("-remote must not be set in module path mode")
+ }
+ if *cmd != "" {
+ log.Fatal("-vcs must not be set in module path mode")
+ }
+ if *rev != "" {
+ log.Fatal("-rev must not be set in module path mode")
+ }
+ if *version != "" {
+ log.Fatal("-version must not be set in module path mode")
+ }
+ if *sum != "" {
+ log.Fatal("-sum must not be set in module path mode")
+ }
+ log.Printf("module from\n from: %s,\n to: %s", *path, *dest)
+
+ if err := moduleFromPath(*path, *dest); err != nil {
+ log.Fatal(err)
+ }
+ } else if *version != "" {
if *remote != "" {
log.Fatal("-remote must not be set in module mode")
}
diff --git a/cmd/fetch_repo/go_mod_download.go b/cmd/fetch_repo/go_mod_download.go
new file mode 100644
index 000000000..7fc8ae4ce
--- /dev/null
+++ b/cmd/fetch_repo/go_mod_download.go
@@ -0,0 +1,93 @@
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "go/build"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+)
+
+type GoModDownloadResult struct {
+ Dir string
+ Sum string
+ Error string
+}
+
+func isModeCacherwSupported() bool {
+ // Check whether -modcacherw is supported.
+ // Assume that fetch_repo was built with the same version of Go we're running.
+ modcacherw := false
+ for _, tag := range build.Default.ReleaseTags {
+ if tag == "go1.14" {
+ modcacherw = true
+ break
+ }
+ }
+
+ return modcacherw
+}
+func findGoPath() string {
+ // Locate the go binary. If GOROOT is set, we'll use that one; otherwise,
+ // we'll use PATH.
+ goPath := "go"
+ if runtime.GOOS == "windows" {
+ goPath += ".exe"
+ }
+ if goroot, ok := os.LookupEnv("GOROOT"); ok {
+ goPath = filepath.Join(goroot, "bin", goPath)
+ }
+ return goPath
+}
+
+func runGoModDownload(dl *GoModDownloadResult, dest string, importpath string, version string) error {
+ buf := &bytes.Buffer{}
+ bufErr := &bytes.Buffer{}
+ cmd := exec.Command(findGoPath(), "mod", "download", "-json")
+ cmd.Dir = dest
+ if isModeCacherwSupported() {
+ cmd.Args = append(cmd.Args, "-modcacherw")
+ }
+
+ if version != "" && importpath != "" {
+ cmd.Args = append(cmd.Args, importpath+"@"+version)
+ }
+
+ cmd.Stdout = buf
+ cmd.Stderr = bufErr
+ fmt.Printf("Running: %s %s\n", cmd.Path, strings.Join(cmd.Args, " "))
+ dlErr := cmd.Run()
+ if dlErr != nil {
+ if _, ok := dlErr.(*exec.ExitError); !ok {
+ if bufErr.Len() > 0 {
+ return fmt.Errorf("!%s %s: %s", cmd.Path, strings.Join(cmd.Args, " "), bufErr.Bytes())
+ } else {
+ return fmt.Errorf("!!%s %s: %v", cmd.Path, strings.Join(cmd.Args, " "), dlErr)
+ }
+ }
+ }
+
+ // Parse the JSON output.
+ if err := json.Unmarshal(buf.Bytes(), &dl); err != nil {
+ if bufErr.Len() > 0 {
+ return fmt.Errorf("3%s %s: %s", cmd.Path, strings.Join(cmd.Args, " "), bufErr.Bytes())
+ } else {
+ return fmt.Errorf("4%s %s: error parsing JSON: %v error: %v", cmd.Path, strings.Join(cmd.Args, " "), buf, err)
+ }
+ }
+ if dl.Error != "" {
+ return errors.New(dl.Error)
+ }
+ if dlErr != nil {
+ return dlErr
+ }
+
+ fmt.Printf("Downloaded: %s\n", dl.Dir)
+
+ return nil
+}
diff --git a/cmd/fetch_repo/module.go b/cmd/fetch_repo/module.go
index 3ff2fedc9..5442bb2fa 100644
--- a/cmd/fetch_repo/module.go
+++ b/cmd/fetch_repo/module.go
@@ -16,19 +16,9 @@ limitations under the License.
package main
import (
- "bytes"
- "encoding/json"
- "errors"
"fmt"
- "go/build"
- "io"
- "os"
- "os/exec"
- "path/filepath"
- "runtime"
- "strings"
-
"golang.org/x/mod/sumdb/dirhash"
+ "os"
)
func fetchModule(dest, importpath, version, sum string) error {
@@ -39,30 +29,11 @@ func fetchModule(dest, importpath, version, sum string) error {
return fmt.Errorf("-version must be a complete semantic version. %q is a prefix.", version)
}
- // Locate the go binary. If GOROOT is set, we'll use that one; otherwise,
- // we'll use PATH.
- goPath := "go"
- if runtime.GOOS == "windows" {
- goPath += ".exe"
- }
- if goroot, ok := os.LookupEnv("GOROOT"); ok {
- goPath = filepath.Join(goroot, "bin", goPath)
- }
-
- // Check whether -modcacherw is supported.
- // Assume that fetch_repo was built with the same version of Go we're running.
- modcacherw := false
- for _, tag := range build.Default.ReleaseTags {
- if tag == "go1.14" {
- modcacherw = true
- break
- }
- }
-
// Download the module. In Go 1.11, this command must be run in a module,
// so we create a dummy module in the current directory (which should be
// empty).
w, err := os.OpenFile("go.mod", os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o666)
+
if err != nil {
return fmt.Errorf("error creating temporary go.mod: %v", err)
}
@@ -75,44 +46,12 @@ func fetchModule(dest, importpath, version, sum string) error {
return fmt.Errorf("error closing temporary go.mod: %v", err)
}
- buf := &bytes.Buffer{}
- bufErr := &bytes.Buffer{}
- cmd := exec.Command(goPath, "mod", "download", "-json")
- if modcacherw {
- cmd.Args = append(cmd.Args, "-modcacherw")
- }
- cmd.Args = append(cmd.Args, importpath+"@"+version)
- cmd.Stdout = buf
- cmd.Stderr = bufErr
- dlErr := cmd.Run()
+ var dl = GoModDownloadResult{}
+ err = runGoModDownload(&dl, dest, importpath, version)
os.Remove("go.mod")
- if dlErr != nil {
- if _, ok := dlErr.(*exec.ExitError); !ok {
- if bufErr.Len() > 0 {
- return fmt.Errorf("%s %s: %s", cmd.Path, strings.Join(cmd.Args, " "), bufErr.Bytes())
- } else {
- return fmt.Errorf("%s %s: %v", cmd.Path, strings.Join(cmd.Args, " "), dlErr)
- }
- }
- }
- // Parse the JSON output.
- var dl struct{ Dir, Sum, Error string }
- if err := json.Unmarshal(buf.Bytes(), &dl); err != nil {
- if bufErr.Len() > 0 {
- return fmt.Errorf("%s %s: %s", cmd.Path, strings.Join(cmd.Args, " "), bufErr.Bytes())
- } else {
- return fmt.Errorf("%s %s: %v", cmd.Path, strings.Join(cmd.Args, " "), err)
- }
- }
- if dl.Error != "" {
- return errors.New(dl.Error)
- }
- if dlErr != nil {
- return dlErr
- }
- if dl.Sum != sum {
- return fmt.Errorf("downloaded module with sum %s; expected sum %s", dl.Sum, sum)
+ if err != nil {
+ return err
}
// Copy the module to the destination.
@@ -134,43 +73,6 @@ func fetchModule(dest, importpath, version, sum string) error {
return nil
}
-func copyTree(destRoot, srcRoot string) error {
- return filepath.Walk(srcRoot, func(src string, info os.FileInfo, e error) (err error) {
- if e != nil {
- return e
- }
- rel, err := filepath.Rel(srcRoot, src)
- if err != nil {
- return err
- }
- if rel == "." {
- return nil
- }
- dest := filepath.Join(destRoot, rel)
-
- if info.IsDir() {
- return os.Mkdir(dest, 0o777)
- } else {
- r, err := os.Open(src)
- if err != nil {
- return err
- }
- defer r.Close()
- w, err := os.Create(dest)
- if err != nil {
- return err
- }
- defer func() {
- if cerr := w.Close(); err == nil && cerr != nil {
- err = cerr
- }
- }()
- _, err = io.Copy(w, r)
- return err
- }
- })
-}
-
// semantic version parsing functions below this point were copied from
// cmd/go/internal/semver and cmd/go/internal/modload at go1.12beta2.
diff --git a/cmd/fetch_repo/path.go b/cmd/fetch_repo/path.go
new file mode 100644
index 000000000..3cf6c12d9
--- /dev/null
+++ b/cmd/fetch_repo/path.go
@@ -0,0 +1,49 @@
+/* Copyright 2019 The Bazel Authors. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "os/exec"
+ "strings"
+)
+
+func moduleFromPath(from string, dest string) error {
+ err := copyTree(dest, from)
+ if err != nil {
+ return err
+ }
+
+ cmd := exec.Command(findGoPath(), "mod", "download", "-json")
+ cmd.Dir = dest
+ if isModeCacherwSupported() {
+ cmd.Args = append(cmd.Args, "-modcacherw")
+ }
+
+ buf := &bytes.Buffer{}
+ bufErr := &bytes.Buffer{}
+ cmd.Stdout = buf
+ cmd.Stderr = bufErr
+ fmt.Printf("Running: %s %s\n", cmd.Path, strings.Join(cmd.Args, " "))
+ // TODO: handle errors
+ cmd.Run()
+
+ // if _, ok := dlErr.(*exec.ExitError); !ok {
+ // return fmt.Errorf("error running 'go mod download': %v", dlErr)
+ // }
+ return nil
+}
diff --git a/internal/bzlmod/go_deps.bzl b/internal/bzlmod/go_deps.bzl
index 455fbdbd4..ee425fbdb 100644
--- a/internal/bzlmod/go_deps.bzl
+++ b/internal/bzlmod/go_deps.bzl
@@ -13,7 +13,7 @@
# limitations under the License.
load("//internal:go_repository.bzl", "go_repository")
-load(":go_mod.bzl", "deps_from_go_mod", "parse_go_work", "sums_from_go_mod", "sums_from_go_work")
+load(":go_mod.bzl", "deps_from_go_mod", "go_work_from_label", "sums_from_go_mod", "sums_from_go_work")
load(
":default_gazelle_overrides.bzl",
"DEFAULT_BUILD_EXTRA_ARGS_BY_PATH",
@@ -83,12 +83,6 @@ _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
@@ -299,6 +293,10 @@ def check_for_version_conflict(version, previous, module_tag, module_name_to_go_
# version is the same, skip because we won't error
return
+ if hasattr(module_tag, "file_path"):
+ # overrides are not considered for version conflicts
+ 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
@@ -432,7 +430,10 @@ def _go_deps_impl(module_ctx):
]
if module.is_root or getattr(module_ctx, "is_isolated", False):
- replace_map.update(go_mod_replace_map)
+ # for the replace_map, first in wins
+ for mod_path, mod in go_mod_replace_map.items():
+ if not mod_path in replace_map:
+ replace_map[mod_path] = mod
else:
# Register this Bazel module as providing the specified Go module. It participates
# in version resolution using its registry version, which uses a relaxed variant of
@@ -487,7 +488,7 @@ def _go_deps_impl(module_ctx):
# for direct dependencies. For manually specified go_deps.module
# tags, we always report version upgrades unless users override with
# the "indirect" attribute.
- if module.is_root and not module_tag.indirect:
+ if module.is_root and not module_tag.indirect: # and not module_tag.file_path:
root_versions[module_tag.path] = raw_version
if _is_dev_dependency(module_ctx, module_tag):
root_module_direct_dev_deps[_repo_name(module_tag.path)] = None
@@ -504,10 +505,21 @@ def _go_deps_impl(module_ctx):
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:
+ to_path = None
+ file_path = None
+
+ if module_tag.path in replace_map:
+ replacement = replace_map[module_tag.path]
+
+ to_path = replacement.to_path
+ file_path = replacement.file_path
+
module_resolutions[module_tag.path] = struct(
repo_name = _repo_name(module_tag.path),
version = version,
raw_version = raw_version,
+ to_path = to_path,
+ file_path = file_path,
)
_fail_on_unmatched_overrides(archive_overrides.keys(), module_resolutions, "archive_overrides")
@@ -533,6 +545,7 @@ def _go_deps_impl(module_ctx):
version = new_version,
raw_version = replace.version,
)
+
if path in root_versions:
if replace != replace.to_path:
# If the root module replaces a Go module with a completely different one, do
@@ -542,7 +555,6 @@ def _go_deps_impl(module_ctx):
root_versions[path] = replace.version
for path, bazel_dep in bazel_deps.items():
- # We can't apply overrides to Bazel dependencies and thus fall back to using the Go module.
if path in archive_overrides or path in gazelle_overrides or path in module_overrides or path in replace_map:
continue
@@ -582,7 +594,6 @@ def _go_deps_impl(module_ctx):
# Do not create a go_repository for a dep shared with the non-isolated instance of
# go_deps.
continue
-
go_repository_args = {
"name": module.repo_name,
"importpath": path,
@@ -602,6 +613,12 @@ def _go_deps_impl(module_ctx):
"patches": _get_patches(path, archive_overrides),
"patch_args": _get_patch_args(path, archive_overrides),
})
+ elif module.file_path:
+ go_repository_args.update({
+ # the version is now meaningless
+ "version": None,
+ "file_path": module.file_path,
+ })
else:
go_repository_args.update({
"sum": _get_sum_from_module(path, module, sums),
@@ -656,7 +673,12 @@ def _get_sum_from_module(path, module, sums):
entry = (module.replace, module.raw_version)
if entry not in sums:
- fail("No sum for {}@{} found. You may need to run: bazel run @rules_go//go -- mod tidy".format(path, module.raw_version))
+ if module.raw_version == "{":
+ # replacement have no sums, so we can skip this
+ return None
+ elif module.file_path == None:
+ # TODO: this error likely needs to convey where to run go mod tidy, as it may be in a subdir
+ fail("No sum for {}@{} from {} found. You may need to run: bazel run @rules_go//go -- mod tidy".format(path, module.raw_version, "parent-label-todo")) #module.parent_label))
return sums[entry]
@@ -703,6 +725,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 = ""),
+ "file_path": attr.string(
+ doc = """For when a module is replaced by one residing in a local directory path """,
+ mandatory = False,
+ ),
},
)
diff --git a/internal/bzlmod/go_mod.bzl b/internal/bzlmod/go_mod.bzl
index a87fa4e43..2434ff8a3 100644
--- a/internal/bzlmod/go_mod.bzl
+++ b/internal/bzlmod/go_mod.bzl
@@ -28,6 +28,9 @@ def use_spec_to_label(repo_name, use_directive):
if use_directive.startswith("../") or "/../" in use_directive or use_directive.endswith("/.."):
fail("go.work use directive: '{}' contains '..' which is not currently supported.".format(use_directive))
+ if use_directive.startswith("/"):
+ fail("go.work use directive: '{}' is an absolute path, which is not currently supported.".format(use_directive))
+
if use_directive.startswith("./"):
use_directive = use_directive[2:]
@@ -36,6 +39,14 @@ def use_spec_to_label(repo_name, use_directive):
return Label("@@{}//{}:go.mod".format(repo_name, use_directive))
+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)
+ go_work = parse_go_work(go_work_content, go_work_label)
+
+ return _relativize_replace_paths(go_work, go_work_path)
+
def parse_go_work(content, go_work_label):
# see: https://go.dev/ref/mod#go-work-file
@@ -91,7 +102,7 @@ def parse_go_work(content, go_work_label):
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()]
+ module_tags = [struct(version = mod.version, path = mod.to_path, _parent_label = go_work_label, file_path = mod.file_path, indirect = False) for mod in state["replace"].values()]
return struct(
go = (int(major), int(minor)),
@@ -101,6 +112,35 @@ def parse_go_work(content, go_work_label):
use = state["use"],
)
+# this exists because we are unable to create a path object in unit tests, we
+# must do this as a post-process step or we cannot unit test go_mod parsing
+def _relativize_replace_paths(go_mod, go_mod_path):
+ new_replace_map = {}
+
+ for key in go_mod.replace_map:
+ value = go_mod.replace_map[key]
+
+ file_path = value.file_path
+
+ if value.file_path:
+ file_path = str(go_mod_path.get_child(value.file_path))
+
+ new_replace_map[key] = struct(
+ from_version = value.from_version,
+ to_path = value.to_path,
+ version = value.version,
+ file_path = file_path,
+ )
+
+ new_go_mod = {
+ attr: getattr(go_mod, attr)
+ for attr in ["go", "module", "require", "module_tags", "from_file_tags"]
+ if hasattr(go_mod, attr)
+ }
+
+ new_go_mod["replace_map"] = new_replace_map
+ return struct(**new_go_mod)
+
def deps_from_go_mod(module_ctx, go_mod_label):
"""Loads the entries from a go.mod file.
@@ -118,6 +158,7 @@ def deps_from_go_mod(module_ctx, go_mod_label):
go_mod_path = module_ctx.path(go_mod_label)
go_mod_content = module_ctx.read(go_mod_path)
go_mod = parse_go_mod(go_mod_content, go_mod_path)
+ go_mod = _relativize_replace_paths(go_mod, go_mod_path)
if go_mod.go[0] != 1 or go_mod.go[1] < 17:
# go.mod files only include entries for all transitive dependencies as
@@ -130,6 +171,7 @@ def deps_from_go_mod(module_ctx, go_mod_label):
path = require.path,
version = require.version,
indirect = require.indirect,
+ file_path = None,
_parent_label = go_mod_label,
))
@@ -225,11 +267,6 @@ def _parse_directive(state, directive, tokens, comment, 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]
@@ -238,6 +275,7 @@ def _parse_replace_directive(state, tokens, path, line_no):
state["replace"][from_path] = struct(
from_version = None,
to_path = tokens[2],
+ file_path = None,
version = _canonicalize_raw_version(tokens[3]),
)
# pattern: replace from_path from_version => to_path to_version
@@ -247,14 +285,38 @@ def _parse_replace_directive(state, tokens, path, line_no):
from_version = _canonicalize_raw_version(tokens[1]),
to_path = tokens[3],
version = _canonicalize_raw_version(tokens[4]),
+ file_path = None,
)
- 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'",
- "but got: '{} {} {}'".format(*tokens),
+ # pattern: replace from_path from_version => file_path
+
+ elif len(tokens) == 4 and tokens[2] == "=>":
+ file_path = tokens[3]
+ # if file_path.startswith("."):
+ # file_path = str(path.get_child(file_path))
+
+ # TODO: add test
+ state["replace"][from_path] = struct(
+ from_version = _canonicalize_raw_version(tokens[1]),
+ to_path = from_path,
+ file_path = file_path,
+ version = "{",
+ )
+ # pattern: replace from_path => to_path
+
+ elif len(tokens) == 3 and tokens[1] == "=>":
+ file_path = tokens[2]
+
+ # if file_path.startswith("."):
+ # file_path = str(path.get_child(file_path))
+
+ state["replace"][from_path] = struct(
+ from_version = None,
+ to_path = from_path,
+ file_path = file_path,
+ version = "{",
)
+ else:
+ fail("{}:{}: unexpected tokens '{}'".format(path, line_no, tokens))
def _tokenize_line(line, path, line_no):
tokens = []
diff --git a/internal/bzlmod/semver.bzl b/internal/bzlmod/semver.bzl
index d79a4f4bf..ba24ffb27 100644
--- a/internal/bzlmod/semver.bzl
+++ b/internal/bzlmod/semver.bzl
@@ -34,6 +34,8 @@ def _identifier_to_comparable(ident, *, numeric_only):
# 11.4.3:
# "Numeric identifiers always have lower precedence than non-numeric identifiers."
return (_COMPARES_LOWEST_SENTINEL, int(ident))
+ elif ident == _COMPARES_HIGHEST_SENTINEL:
+ return (ident,)
elif numeric_only:
fail("Expected a numeric identifier, got: " + ident)
else:
@@ -67,7 +69,7 @@ def _semver_to_comparable(v, *, relaxed = False):
prerelease = [(_COMPARES_HIGHEST_SENTINEL,)]
release = release_str.split(".")
- if not relaxed and len(release) != 3:
+ if not v == "{" and not relaxed and len(release) != 3:
fail("Semantic version strings must have exactly three dot-separated components, got: " + v)
return (
diff --git a/internal/go_repository.bzl b/internal/go_repository.bzl
index d7e74f90e..3a62adb3a 100644
--- a/internal/go_repository.bzl
+++ b/internal/go_repository.bzl
@@ -133,7 +133,9 @@ def _go_repository_impl(ctx):
if generate:
gazelle_path = ctx.path(Label(_gazelle))
- if ctx.attr.urls:
+ if ctx.attr.file_path:
+ pass
+ elif ctx.attr.urls:
# HTTP mode
for key in ("commit", "tag", "vcs", "remote", "version", "sum", "replace"):
if getattr(ctx.attr, key):
@@ -178,7 +180,7 @@ def _go_repository_impl(ctx):
for key in ("urls", "strip_prefix", "type", "sha256", "commit", "tag", "vcs", "remote"):
if getattr(ctx.attr, key):
fail("cannot specify both version and %s" % key)
- if not ctx.attr.sum:
+ if ctx.attr.version and not ctx.attr.sum:
fail("if version is specified, sum must also be")
fetch_path = ctx.attr.replace if ctx.attr.replace else ctx.attr.importpath
@@ -244,6 +246,38 @@ def _go_repository_impl(ctx):
env.update({k: ctx.os.environ[k] for k in env_keys if k in ctx.os.environ})
+ if ctx.attr.file_path:
+ local_path_env = dict(env)
+ local_path_env["GOSUMDB"] = "off"
+
+ # Override external GO111MODULE, because it is needed by module mode, no-op in repository mode
+ local_path_env["GO111MODULE"] = "on"
+
+ if hasattr(ctx, "watch_tree"):
+ # https://github.com/bazelbuild/bazel/commit/fffa0affebbacf1961a97ef7cd248be64487d480
+ ctx.watch_tree(ctx.attr.file_path)
+ else:
+ print("""
+ WARNING: go.mod replace directives to module paths is only supported in bazel 7.1.0-rc1 or later,
+ Because of this changes to %s will not be detected by bazel in previous versions.""" % ctx.attr.file_path)
+
+ command = [fetch_repo, "--path", ctx.attr.file_path, "--dest", ctx.path("")]
+ result = env_execute(
+ ctx,
+ command,
+ environment = local_path_env,
+ timeout = _GO_REPOSITORY_TIMEOUT,
+ )
+
+ if result.return_code:
+ fail(command)
+
+ if result.stderr:
+ print("mod download: %s", result.stderr)
+
+ if result.return_code:
+ fail(command)
+
if fetch_repo_args:
# Disable sumdb in fetch_repo. In module mode, the sum is a mandatory
# attribute of go_repository, so we don't need to look it up.
@@ -253,16 +287,18 @@ def _go_repository_impl(ctx):
# Override external GO111MODULE, because it is needed by module mode, no-op in repository mode
fetch_repo_env["GO111MODULE"] = "on"
+ # if ctx.attr.name.endswith("com_github_google_safetext"):
+ # fail("fetch_repo(%s) %s %s" % (ctx.attr.file_path, fetch_repo_args, fetch_repo_env))
+
result = env_execute(
ctx,
[fetch_repo] + fetch_repo_args,
environment = fetch_repo_env,
timeout = _GO_REPOSITORY_TIMEOUT,
)
+
if result.return_code:
- fail("failed to fetch %s: %s" % (ctx.name, result.stderr))
- if ctx.attr.debug_mode and result.stderr:
- print("fetch_repo: " + result.stderr)
+ fail("%s: %s" % (ctx.name, result.stderr))
# Repositories are fetched. Determine if build file generation is needed.
build_file_names = ctx.attr.build_file_name.split(",")
@@ -314,7 +350,7 @@ def _go_repository_impl(ctx):
"-repo_config",
repo_config,
]
- if ctx.attr.version:
+ if ctx.attr.version or ctx.attr.file_path:
cmd.append("-go_repository_module_mode")
if ctx.attr.build_file_name:
cmd.extend(["-build_file_name", ctx.attr.build_file_name])
@@ -331,6 +367,7 @@ def _go_repository_impl(ctx):
cmd.extend(ctx.attr.build_extra_args)
cmd.append(ctx.path(""))
ctx.report_progress("running Gazelle")
+
result = env_execute(ctx, cmd, environment = env, timeout = _GO_REPOSITORY_TIMEOUT)
if result.return_code:
fail("failed to generate BUILD files for %s: %s" % (
@@ -428,6 +465,11 @@ go_repository = repository_rule(
doc = _AUTH_PATTERN_DOC,
),
+ # Attributes for a module that should be loaded from the local file system.
+ "file_path": attr.string(
+ doc = """ If specified, `go_repository` will load the module from this local directory""",
+ ),
+
# Attributes for a module that should be downloaded with the Go toolchain.
"version": attr.string(
doc = """If specified, `go_repository` will download the module at this version
diff --git a/internal/go_repository_tools_srcs.bzl b/internal/go_repository_tools_srcs.bzl
index b135dd24c..0a2c4033d 100644
--- a/internal/go_repository_tools_srcs.bzl
+++ b/internal/go_repository_tools_srcs.bzl
@@ -8,8 +8,11 @@ GO_REPOSITORY_TOOLS_SRCS = [
Label("//cmd/autogazelle:client_unix.go"),
Label("//cmd/autogazelle:server_unix.go"),
Label("//cmd/fetch_repo:BUILD.bazel"),
+ Label("//cmd/fetch_repo:copy_tree.go"),
Label("//cmd/fetch_repo:fetch_repo.go"),
+ Label("//cmd/fetch_repo:go_mod_download.go"),
Label("//cmd/fetch_repo:module.go"),
+ Label("//cmd/fetch_repo:path.go"),
Label("//cmd/fetch_repo:vcs.go"),
Label("//cmd/gazelle:BUILD.bazel"),
Label("//cmd/gazelle:diff.go"),
diff --git a/repository.md b/repository.md
index b5c2eb926..0a46cffa3 100644
--- a/repository.md
+++ b/repository.md
@@ -102,9 +102,9 @@ git_repository(
go_repository(name, auth_patterns, build_config, build_directives, build_external, build_extra_args,
build_file_generation, build_file_name, build_file_proto_mode, build_naming_convention,
- build_tags, canonical_id, commit, debug_mode, importpath, patch_args, patch_cmds,
- patch_tool, patches, remote, replace, repo_mapping, sha256, strip_prefix, sum, tag,
- type, urls, vcs, version)
+ build_tags, canonical_id, commit, debug_mode, file_path, importpath, patch_args,
+ patch_cmds, patch_tool, patches, remote, replace, repo_mapping, sha256, strip_prefix,
+ sum, tag, type, urls, vcs, version)
`go_repository` downloads a Go project and generates build files with Gazelle
@@ -186,6 +186,7 @@ go_repository(
| canonical_id | If the repository is downloaded via HTTP (`urls` is set) and this is set, restrict cache hits to those cases where the repository was added to the cache with the same canonical id. | String | optional | `""` |
| commit | If the repository is downloaded using a version control tool, this is the commit or revision to check out. With git, this would be a sha1 commit id. `commit` and `tag` may not both be set. | String | optional | `""` |
| debug_mode | Enables logging of fetch_repo and Gazelle output during succcesful runs. Gazelle can be noisy so this defaults to `False`. However, setting to `True` can be useful for debugging build failures and unexpected behavior for the given rule. | Boolean | optional | `False` |
+| file_path | If specified, `go_repository` will load the module from this local directory | String | optional | `""` |
| importpath | The Go import path that matches the root directory of this repository.
In module mode (when `version` is set), this must be the module path. If neither `urls` nor `remote` is specified, `go_repository` will automatically find the true path of the module, applying import path redirection.
If build files are generated for this repository, libraries will have their `importpath` attributes prefixed with this `importpath` string. | String | required | |
| patch_args | Arguments passed to the patch tool when applying patches. | List of strings | optional | `["-p0"]` |
| patch_cmds | Commands to run in the repository after patches are applied. | List of strings | optional | `[]` |
diff --git a/tests/bcr/go_mod/MODULE.bazel b/tests/bcr/go_mod/MODULE.bazel
index 90572eb69..858a52782 100644
--- a/tests/bcr/go_mod/MODULE.bazel
+++ b/tests/bcr/go_mod/MODULE.bazel
@@ -138,6 +138,7 @@ use_repo(
# "in_gopkg_yaml_v3",
# Only used for testing.
"bazel_gazelle_go_repository_config",
+ "org_example_hello",
)
# Use an isolated usage to bring in Go tools from the tools package with their own dependency
diff --git a/tests/bcr/go_mod/go.mod b/tests/bcr/go_mod/go.mod
index 9becf5d60..c858c3c55 100644
--- a/tests/bcr/go_mod/go.mod
+++ b/tests/bcr/go_mod/go.mod
@@ -1,25 +1,35 @@
// This will stop go mod from descending into this directory.
module github.com/bazelbuild/bazel-gazelle/tests/bcr/go_mod
-go 1.19
+go 1.21.5
// Validate go.mod replace directives can be properly used:
replace github.com/bmatcuk/doublestar/v4 => github.com/bmatcuk/doublestar v1.3.4
require (
+ example.org/hello v1.0.0
github.com/DataDog/sketches-go v1.4.1
+ github.com/bazelbuild/buildtools v0.0.0-20230317132445-9c3c1fc0106e
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
+ github.com/stretchr/testify v1.6.1
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/davecgh/go-spew v1.1.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
+ golang.org/x/text v0.9.0 // indirect
+ google.golang.org/protobuf v1.32.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+ rsc.io/quote v1.5.2 // indirect
+ rsc.io/sampler v1.3.0 // indirect
)
+
+replace example.org/hello => ../../../fixtures/hello
diff --git a/tests/bcr/go_mod/go.sum b/tests/bcr/go_mod/go.sum
index ee03e8091..9e6056a54 100644
--- a/tests/bcr/go_mod/go.sum
+++ b/tests/bcr/go_mod/go.sum
@@ -1,27 +1,54 @@
+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.1 h1:j5G6as+9FASM2qC36lvpvQAj9qsv/jUs3FtO8CwZNAY=
github.com/DataDog/sketches-go v1.4.1/go.mod h1:xJIXldczJyyjnbDop7ZZcLxJdV3+7Kra7H1KMgpgkLk=
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-20230317132445-9c3c1fc0106e h1:XmPu4mXICgdGnC5dXGjUGbwUD/kUmS0l5Aop3LaevBM=
+github.com/bazelbuild/buildtools v0.0.0-20230317132445-9c3c1fc0106e/go.mod h1:689QdV3hBP7Vo9dJMmzhoYIyo/9iMhEmHkJcnaPRCbo=
github.com/bazelbuild/rules_go v0.39.1 h1:wkJLUDx59dntWMghuL8++GteoU1To6sRoKJXuyFtmf8=
github.com/bazelbuild/rules_go v0.39.1/go.mod h1:TMHmtfpvyfsxaqfL9WnahCsXMWDMICTw7XeK9yVb+YU=
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/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
-github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
+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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/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.1 h1:kt9FtLiooDc0vbwTLhdg3dyNX1K9Qwa1EK9LcD4jVUQ=
github.com/envoyproxy/protoc-gen-validate v1.0.1/go.mod h1:0vj8bNkYbSTNS2PIyH87KZaeN4x9zpL9Qt8fQC7d+vs=
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/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+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-20220905092116-b49f7bc46da2 h1:SJ+NtwL6QaZ21U+IrK7d0gGgpjGGvd2kz+FzTHVzdqI=
@@ -29,26 +56,73 @@ github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2/go.mod h1:Tv1PlzqC
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
-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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/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 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+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.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+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.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+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.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
+gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/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=
+rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/tests/bcr/go_mod/pkg/BUILD.bazel b/tests/bcr/go_mod/pkg/BUILD.bazel
index 7d6c40305..ab8a846cd 100644
--- a/tests/bcr/go_mod/pkg/BUILD.bazel
+++ b/tests/bcr/go_mod/pkg/BUILD.bazel
@@ -61,5 +61,6 @@ go_test(
"@com_github_google_safetext//yamltemplate",
"@com_github_stretchr_testify//require:go_default_library",
"@my_rules_go//go/runfiles",
+ "@org_example_hello//:hello",
],
)
diff --git a/tests/bcr/go_mod/pkg/pkg_test.go b/tests/bcr/go_mod/pkg/pkg_test.go
index bc93a2f90..610210480 100644
--- a/tests/bcr/go_mod/pkg/pkg_test.go
+++ b/tests/bcr/go_mod/pkg/pkg_test.go
@@ -5,6 +5,7 @@ import (
"os"
"testing"
+ "example.org/hello"
"github.com/DataDog/sketches-go/ddsketch"
"github.com/bazelbuild/bazel-gazelle/tests/bcr/go_mod/pkg/data"
"github.com/bazelbuild/buildtools/labels"
@@ -20,9 +21,7 @@ import (
func TestReplace(t *testing.T) {
// doublestar.StandardOS does NOT exist in doublestar/v4
- // See: https://pkg.go.dev/github.com/bmatcuk/doublestar#OS
- // If we are able to initialize this variable, it validates that the dependency is properly
- // being replaced with github.com/bmatcuk/doublestar@v1.3.4
+ // See: https://pkg.go.dev/github.com/bmatcuk/doublestar#OS If we are able to initialize this variable, it validates that the dependency is properly being replaced with github.com/bmatcuk/doublestar@v1.3.4
_ = doublestar.StandardOS
}
@@ -77,3 +76,9 @@ func TestArchiveOverrideUsed(t *testing.T) {
func TestArchiveOverrideWithPatch(t *testing.T) {
require.Equal(t, labels.Patched, "hello")
}
+
+func TestGodModReplaceToFilePath(t *testing.T) {
+ // This test is used to validate that the go.mod replace directive is being used to replace
+ // the module path with a file path.
+ require.Equal(t, "Hello, world.", hello.Hello())
+}
diff --git a/tests/bcr/go_work/MODULE.bazel b/tests/bcr/go_work/MODULE.bazel
index b13d9b399..0e4220acb 100644
--- a/tests/bcr/go_work/MODULE.bazel
+++ b/tests/bcr/go_work/MODULE.bazel
@@ -137,6 +137,7 @@ use_repo(
"org_golang_x_sys",
# Only used for testing.
"bazel_gazelle_go_repository_config",
+ "org_example_hello",
)
# Use an isolated usage to bring in Go tools from the tools package with their own dependency
diff --git a/tests/bcr/go_work/go.work b/tests/bcr/go_work/go.work
index c4a80cf5b..f4e48d11b 100644
--- a/tests/bcr/go_work/go.work
+++ b/tests/bcr/go_work/go.work
@@ -1,7 +1,9 @@
go 1.21.5
use (
- ./pkg
- ./tools
- ./proto
+ ./pkg
+ ./tools
+ ./proto
)
+
+replace example.org/hello => ../../../fixtures/hello
diff --git a/tests/bcr/go_work/go.work.sum b/tests/bcr/go_work/go.work.sum
index e69de29bb..a1b2e5b57 100644
--- a/tests/bcr/go_work/go.work.sum
+++ b/tests/bcr/go_work/go.work.sum
@@ -0,0 +1,37 @@
+github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
+github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs=
+github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
+github.com/kevinmbeaulieu/eq-go v1.0.0/go.mod h1:G3S8ajA56gKBZm4UB9AOyoOS37JO3roToPzKNM8dtdM=
+github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc=
+github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk=
+github.com/matryer/moq v0.2.7/go.mod h1:kITsx543GOENm48TUAQyJ9+SAvFSr7iGQXPoth/VUBk=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
+github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
+golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
+golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
+golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
+google.golang.org/genproto v0.0.0-20231127180814-3a041ad873d4/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc=
+google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
+google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8=
diff --git a/tests/bcr/go_work/pkg/BUILD.bazel b/tests/bcr/go_work/pkg/BUILD.bazel
index 1e75d93df..21333bf5b 100644
--- a/tests/bcr/go_work/pkg/BUILD.bazel
+++ b/tests/bcr/go_work/pkg/BUILD.bazel
@@ -61,5 +61,6 @@ go_test(
"@com_github_google_safetext//yamltemplate",
"@com_github_stretchr_testify//require:go_default_library",
"@my_rules_go//go/runfiles",
+ "@org_example_hello//:hello",
],
)
diff --git a/tests/bcr/go_work/pkg/go.mod b/tests/bcr/go_work/pkg/go.mod
index 202fdd260..486876b27 100644
--- a/tests/bcr/go_work/pkg/go.mod
+++ b/tests/bcr/go_work/pkg/go.mod
@@ -3,6 +3,7 @@ module github.com/bazelbuild/bazel-gazelle/tests/bcr/go_work/pkg
go 1.21.5
require (
+ example.org/hello v0.0.0-00010101000000-000000000000
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
@@ -21,9 +22,14 @@ require (
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
+ golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
+ rsc.io/quote v1.5.2 // indirect
+ rsc.io/sampler v1.3.0 // indirect
)
// Validate go.mod replace directives can be properly used:
replace github.com/bmatcuk/doublestar/v4 => github.com/bmatcuk/doublestar v1.3.4
+
+// replace example.org/hello => ../../../fixtures/hello
diff --git a/tests/bcr/go_work/pkg/go.sum b/tests/bcr/go_work/pkg/go.sum
index d3b2c1dc6..c5d9f6e1b 100644
--- a/tests/bcr/go_work/pkg/go.sum
+++ b/tests/bcr/go_work/pkg/go.sum
@@ -6,8 +6,8 @@ github.com/bazelbuild/bazel-gazelle v0.30.0 h1:q9XLWQSCA5NZPJ98WFqicHkq6fxrDPnfv
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/bazelbuild/rules_go v0.44.0 h1:uJStI9o5obVWSwquy9WxKNWfZxf2sKA2rpEsX6x5RVM=
+github.com/bazelbuild/rules_go v0.44.0/go.mod h1:z7Y8GZ90V4mwgYizbNbEQKmOmx93Q3Btcel4vX7pXoc=
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=
@@ -82,7 +82,10 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
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.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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
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=
@@ -117,3 +120,7 @@ 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=
+rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/tests/bcr/go_work/pkg/pkg_test.go b/tests/bcr/go_work/pkg/pkg_test.go
index 85227abd6..e81dcc076 100644
--- a/tests/bcr/go_work/pkg/pkg_test.go
+++ b/tests/bcr/go_work/pkg/pkg_test.go
@@ -5,6 +5,7 @@ import (
"os"
"testing"
+ "example.org/hello"
"github.com/DataDog/sketches-go/ddsketch"
"github.com/bazelbuild/bazel-gazelle/tests/bcr/go_work/pkg/data"
"github.com/bazelbuild/buildtools/labels"
@@ -77,3 +78,9 @@ func TestArchiveOverrideUsed(t *testing.T) {
func TestArchiveOverrideWithPatch(t *testing.T) {
require.Equal(t, labels.Patched, "hello")
}
+
+func TestGodModReplaceToFilePath(t *testing.T) {
+ // This test is used to validate that the go.mod replace directive is being used to replace
+ // the module path with a file path.
+ require.Equal(t, "Hello, world.", hello.Hello())
+}
diff --git a/tests/bzlmod/go_mod_test.bzl b/tests/bzlmod/go_mod_test.bzl
index e1abba0f9..93db2b1b1 100644
--- a/tests/bzlmod/go_mod_test.bzl
+++ b/tests/bzlmod/go_mod_test.bzl
@@ -14,6 +14,7 @@ github.com/bmatcuk/doublestar/v4 v4.0.2 // indirect
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
+replace example.org/hello => ../fixtures/hello
module github.com/bazelbuild/bazel-gazelle
@@ -30,8 +31,9 @@ _EXPECTED_GO_MOD_PARSE_RESULT = struct(
go = (1, 18),
module = "github.com/bazelbuild/bazel-gazelle",
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"),
+ "github.com/go-fsnotify/fsnotify": struct(file_path = None, from_version = None, to_path = "github.com/fsnotify/fsnotify", version = "1.4.2"),
+ "github.com/bmatcuk/doublestar/v4": struct(file_path = None, from_version = "4.0.2", to_path = "github.com/bmatcuk/doublestar/v4", version = "4.0.3"),
+ "example.org/hello": struct(file_path = "../fixtures/hello", from_version = None, to_path = "example.org/hello", version = "{"),
},
require = (
struct(indirect = False, path = "github.com/bazelbuild/buildtools", version = "v0.0.0-20220531122519-a43aed7014c8"),
@@ -111,6 +113,7 @@ use (
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
+replace example.org/hello => ../fixtures/hello
"""
_EXPECTED_GO_WORK_PARSE_RESULT = struct(
@@ -121,12 +124,14 @@ _EXPECTED_GO_WORK_PARSE_RESULT = struct(
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"),
+ struct(indirect = False, _parent_label = Label("//:go.work"), file_path = None, path = "github.com/fsnotify/fsnotify", version = "1.4.2"),
+ struct(indirect = False, _parent_label = Label("//:go.work"), file_path = None, path = "github.com/bmatcuk/doublestar/v4", version = "4.0.3"),
+ struct(indirect = False, _parent_label = Label("//:go.work"), file_path = "../fixtures/hello", path = "example.org/hello", version = "{"),
],
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"),
+ "github.com/go-fsnotify/fsnotify": struct(file_path = None, from_version = None, to_path = "github.com/fsnotify/fsnotify", version = "1.4.2"),
+ "github.com/bmatcuk/doublestar/v4": struct(file_path = None, from_version = "4.0.2", to_path = "github.com/bmatcuk/doublestar/v4", version = "4.0.3"),
+ "example.org/hello": struct(file_path = "../fixtures/hello", from_version = None, to_path = "example.org/hello", version = "{"),
},
use = [
"./go_mod_one",
diff --git a/tests/fixtures/hello/go.mod b/tests/fixtures/hello/go.mod
new file mode 100644
index 000000000..7f8835865
--- /dev/null
+++ b/tests/fixtures/hello/go.mod
@@ -0,0 +1,12 @@
+module example.com/hello
+
+go 1.21.5
+
+require rsc.io/quote v1.5.2
+
+require (
+ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
+ rsc.io/sampler v1.3.0 // indirect
+)
+
+replace example.org/my-non-existent-go-mod => /Users/spenner/src/bazelbuild/bazel-gazelle/tests/fixtures/my-non-existent-go-mod/
diff --git a/tests/fixtures/hello/go.sum b/tests/fixtures/hello/go.sum
new file mode 100644
index 000000000..4a8bcd704
--- /dev/null
+++ b/tests/fixtures/hello/go.sum
@@ -0,0 +1,6 @@
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/tests/fixtures/hello/hello.go b/tests/fixtures/hello/hello.go
new file mode 100644
index 000000000..83891ff60
--- /dev/null
+++ b/tests/fixtures/hello/hello.go
@@ -0,0 +1,7 @@
+package hello
+
+import "rsc.io/quote"
+
+func Hello() string {
+ return quote.Hello()
+}
diff --git a/tests/fixtures/hello/hello_test.go b/tests/fixtures/hello/hello_test.go
new file mode 100644
index 000000000..b01b58f6e
--- /dev/null
+++ b/tests/fixtures/hello/hello_test.go
@@ -0,0 +1,10 @@
+package hello
+
+import "testing"
+
+func TestHello(t *testing.T) {
+ want := "Hello, world."
+ if got := Hello(); got != want {
+ t.Errorf("Hello() = %q, want %q", got, want)
+ }
+}
diff --git a/tests/fixtures/my-non-existent-go-mod/go.mod b/tests/fixtures/my-non-existent-go-mod/go.mod
new file mode 100644
index 000000000..0c4cdf7f9
--- /dev/null
+++ b/tests/fixtures/my-non-existent-go-mod/go.mod
@@ -0,0 +1,10 @@
+module example.org/my-non-existent-go-mod
+
+go 1.21.5
+
+require rsc.io/quote v1.5.2
+
+require (
+ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
+ rsc.io/sampler v1.3.0 // indirect
+)