Skip to content

Commit

Permalink
repository_macro directive for referencing macros from WORKSPACE (#493)
Browse files Browse the repository at this point in the history
Added the repository_macro directive with the following format:
# gazelle:repository_macro repos.bzl%go_repositories

Gazelle only recognizes this directive when reading from the WORKSPACE file.

fix-update uses the directive to know about rules defined in a macro file, so they can be used during dependency resolution.

update-repos can now update repository rules in the corresponding macros without additional command line arguments instead of writing copies to WORKSPACE.

The to-macro flag functionality has been modified to only write new repository rules to the corresponding macro, and to update existing rules in macros and the WORKSPACE file. However, duplicates will still be written to the macro if the repository rule is not a go_repository rule.

Fixes #483
  • Loading branch information
blico authored and jayconrod committed Apr 17, 2019
1 parent 63ddd72 commit 4f524f2
Show file tree
Hide file tree
Showing 10 changed files with 533 additions and 92 deletions.
20 changes: 17 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -415,9 +415,9 @@ The following flags are accepted:
+----------------------------------------------------------------------------------------------------------+----------------------------------------------+
| :flag:`-to_macro macroFile%defName` | |
+----------------------------------------------------------------------------------------------------------+----------------------------------------------+
| Tells Gazelle to write repository rules into a .bzl macro function rather than the WORKSPACE file. |
| Currently, Gazelle won't see repositories declared in the macro when updating build files. This means that it won't use custom repository names, and it |
| will go out to the network when trying to determine repository roots. |
| Tells Gazelle to write new repository rules into a .bzl macro function rather than the WORKSPACE file. |
| |
| The ``repository_macro`` directive should be added to the WORKSPACE in order for future Gazelle calls to recognize the repos defined in the macro file. |
+----------------------------------------------------------------------------------------------------------+----------------------------------------------+
| :flag:`-build_file_names file1,file2,...` | |
+----------------------------------------------------------------------------------------------------------+----------------------------------------------+
Expand Down Expand Up @@ -669,6 +669,20 @@ The following directives are recognized:
| |
+---------------------------------------------------+----------------------------------------+

Gazelle also reads directives from the WORKSPACE file. They may be used to
discover custom repository names and known prefixes. The ``fix`` and ``update``
commands use these directives for dependency resolution. ``update-repos`` uses
them to learn about repository rules defined in alternate locations.

+-------------------------------------------------------+----------------------------------------+
| **WORKSPACE Directive** | **Default value** |
+=======================================================+========================================+
| :direc:`# gazelle:repository_macro macroFile%defName` | n/a |
+-------------------------------------------------------+----------------------------------------+
| Tells Gazelle to look for repository rules in a macro in a .bzl file. The directive can be |
| repeated multiple times. |
| The macro can be generated by calling ``update-repos`` with the ``to_macro`` flag. |
+-------------------------------------------------------+----------------------------------------+

Keep comments
~~~~~~~~~~~~~
Expand Down
37 changes: 28 additions & 9 deletions cmd/gazelle/fix-update.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,11 +360,23 @@ func newFixUpdateConfiguration(cmd command, args []string, cexts []config.Config
return nil, err
}
} else {
if err := fixWorkspace(c, workspace, loads); err != nil {
c.RepoName = findWorkspaceName(workspace)
var reposFiles map[*rule.File][]string
uc.repos, reposFiles, err = repo.ListRepositories(workspace)
if err != nil {
return nil, err
}
files := make([]*rule.File, 0, len(reposFiles))
seen := make(map[string]bool)
for f := range reposFiles {
if !seen[f.Path] {
files = append(files, f)
seen[f.Path] = true
}
}
if err := fixRepoFiles(c, files, loads); err != nil {
return nil, err
}
c.RepoName = findWorkspaceName(workspace)
uc.repos = repo.ListRepositories(workspace)
}
repoPrefixes := make(map[string]bool)
for _, r := range uc.repos {
Expand Down Expand Up @@ -413,7 +425,7 @@ FLAGS:
fs.PrintDefaults()
}

func fixWorkspace(c *config.Config, workspace *rule.File, loads []rule.LoadInfo) error {
func fixRepoFiles(c *config.Config, files []*rule.File, loads []rule.LoadInfo) error {
uc := getUpdateConfig(c)
if !c.ShouldFix {
return nil
Expand All @@ -428,12 +440,19 @@ func fixWorkspace(c *config.Config, workspace *rule.File, loads []rule.LoadInfo)
return nil
}

merger.FixWorkspace(workspace)
merger.FixLoads(workspace, loads)
if err := merger.CheckGazelleLoaded(workspace); err != nil {
return err
for _, f := range files {
merger.FixLoads(f, loads)
if f.Path == filepath.Join(c.RepoRoot, "WORKSPACE") {
merger.FixWorkspace(f)
if err := merger.CheckGazelleLoaded(f); err != nil {
return err
}
}
if err := uc.emit(c, f); err != nil {
return err
}
}
return uc.emit(c, workspace)
return nil
}

func findWorkspaceName(f *rule.File) string {
Expand Down
240 changes: 226 additions & 14 deletions cmd/gazelle/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1253,10 +1253,37 @@ go_repository(
}})
}

func TestImportReposFromDepToMacro(t *testing.T) {
func TestImportReposFromDepToWorkspaceWithMacro(t *testing.T) {
files := []testtools.FileSpec{
{Path: "WORKSPACE"},
{
Path: "WORKSPACE",
Content: `
http_archive(
name = "io_bazel_rules_go",
url = "https://github.com/bazelbuild/rules_go/releases/download/0.10.1/rules_go-0.10.1.tar.gz",
sha256 = "4b14d8dd31c6dbaf3ff871adcd03f28c3274e42abc855cb8fb4d01233c0154dc",
)
http_archive(
name = "bazel_gazelle",
url = "https://github.com/bazelbuild/bazel-gazelle/releases/download/0.10.0/bazel-gazelle-0.10.0.tar.gz",
sha256 = "6228d9618ab9536892aa69082c063207c91e777e51bd3c5544c9c060cafe1bd8",
)
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains", "go_repository")
go_rules_dependencies()
go_register_toolchains()
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
gazelle_dependencies()
http_archive(
name = "com_github_go_yaml_yaml",
urls = ["https://example.com/yaml.tar.gz"],
sha256 = "1234",
)
# gazelle:repository_macro repositories.bzl%go_repositories
`,
}, {
Path: "repositories.bzl",
Content: `
load("@bazel_gazelle//:deps.bzl", "go_repository")
Expand All @@ -1274,12 +1301,6 @@ def go_repositories():
importpath = "golang.org/x/sys",
remote = "https://github.com/golang/sys",
)
http_archive(
name = "com_github_go_yaml_yaml",
urls = ["https://example.com/yaml.tar.gz"],
sha256 = "1234",
)
`,
}, {
Path: "Gopkg.lock",
Expand Down Expand Up @@ -1322,13 +1343,53 @@ def go_repositories():
dir, cleanup := testtools.CreateFiles(t, files)
defer cleanup()

args := []string{"update-repos", "-build_file_generation", "off", "-from_file", "Gopkg.lock", "-to_macro", "repositories.bzl%go_repositories"}
args := []string{"update-repos", "-build_file_generation", "off", "-from_file", "Gopkg.lock"}
if err := runGazelle(dir, args); err != nil {
t.Fatal(err)
}

testtools.CheckFiles(t, dir, []testtools.FileSpec{
{
Path: "WORKSPACE",
Content: `
http_archive(
name = "io_bazel_rules_go",
url = "https://github.com/bazelbuild/rules_go/releases/download/0.10.1/rules_go-0.10.1.tar.gz",
sha256 = "4b14d8dd31c6dbaf3ff871adcd03f28c3274e42abc855cb8fb4d01233c0154dc",
)
http_archive(
name = "bazel_gazelle",
url = "https://github.com/bazelbuild/bazel-gazelle/releases/download/0.10.0/bazel-gazelle-0.10.0.tar.gz",
sha256 = "6228d9618ab9536892aa69082c063207c91e777e51bd3c5544c9c060cafe1bd8",
)
load("@io_bazel_rules_go//go:def.bzl", "go_register_toolchains", "go_rules_dependencies")
go_rules_dependencies()
go_register_toolchains()
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
gazelle_dependencies()
http_archive(
name = "com_github_go_yaml_yaml",
urls = ["https://example.com/yaml.tar.gz"],
sha256 = "1234",
)
# gazelle:repository_macro repositories.bzl%go_repositories
go_repository(
name = "com_github_pkg_errors",
build_file_generation = "off",
commit = "645ef00459ed84a119197bfb8d8205042c6df63d",
importpath = "github.com/pkg/errors",
)
`,
}, {
Path: "repositories.bzl",
Content: `
load("@bazel_gazelle//:deps.bzl", "go_repository")
Expand All @@ -1348,10 +1409,160 @@ def go_repositories():
remote = "https://github.com/golang/sys",
)
http_archive(
name = "com_github_go_yaml_yaml",
urls = ["https://example.com/yaml.tar.gz"],
sha256 = "1234",
`,
},
})
}

func TestImportReposFromDepToMacroWithWorkspace(t *testing.T) {
files := []testtools.FileSpec{
{
Path: "WORKSPACE",
Content: `
http_archive(
name = "io_bazel_rules_go",
url = "https://github.com/bazelbuild/rules_go/releases/download/0.10.1/rules_go-0.10.1.tar.gz",
sha256 = "4b14d8dd31c6dbaf3ff871adcd03f28c3274e42abc855cb8fb4d01233c0154dc",
)
http_archive(
name = "bazel_gazelle",
url = "https://github.com/bazelbuild/bazel-gazelle/releases/download/0.10.0/bazel-gazelle-0.10.0.tar.gz",
sha256 = "6228d9618ab9536892aa69082c063207c91e777e51bd3c5544c9c060cafe1bd8",
)
load("@io_bazel_rules_go//go:def.bzl", "go_register_toolchains", "go_rules_dependencies")
go_rules_dependencies()
go_register_toolchains()
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
gazelle_dependencies()
http_archive(
name = "com_github_go_yaml_yaml",
urls = ["https://example.com/yaml.tar.gz"],
sha256 = "1234",
)
# gazelle:repository_macro repositories.bzl%go_repositories
# gazelle:repository_macro repositories.bzl%foo_repositories
`,
}, {
Path: "repositories.bzl",
Content: `
load("@bazel_gazelle//:deps.bzl", "go_repository")
def go_repositories():
go_repository(
name = "org_golang_x_sys",
importpath = "golang.org/x/sys",
remote = "https://github.com/golang/sys",
)
def foo_repositories():
go_repository(
name = "org_golang_x_net",
importpath = "golang.org/x/net",
tag = "1.2",
)
`,
}, {
Path: "Gopkg.lock",
Content: `# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
name = "github.com/pkg/errors"
packages = ["."]
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
version = "v0.8.0"
[[projects]]
branch = "master"
name = "golang.org/x/net"
packages = ["context"]
revision = "66aacef3dd8a676686c7ae3716979581e8b03c47"
[[projects]]
branch = "master"
name = "golang.org/x/sys"
packages = ["unix"]
revision = "bb24a47a89eac6c1227fbcb2ae37a8b9ed323366"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "05c1cd69be2c917c0cc4b32942830c2acfa044d8200fdc94716aae48a8083702"
solver-name = "gps-cdcl"
solver-version = 1
`,
},
}
dir, cleanup := testtools.CreateFiles(t, files)
defer cleanup()

args := []string{"update-repos", "-build_file_generation", "off", "-from_file", "Gopkg.lock", "-to_macro", "repositories.bzl%foo_repositories"}
if err := runGazelle(dir, args); err != nil {
t.Fatal(err)
}

testtools.CheckFiles(t, dir, []testtools.FileSpec{
{
Path: "WORKSPACE",
Content: `
http_archive(
name = "io_bazel_rules_go",
url = "https://github.com/bazelbuild/rules_go/releases/download/0.10.1/rules_go-0.10.1.tar.gz",
sha256 = "4b14d8dd31c6dbaf3ff871adcd03f28c3274e42abc855cb8fb4d01233c0154dc",
)
http_archive(
name = "bazel_gazelle",
url = "https://github.com/bazelbuild/bazel-gazelle/releases/download/0.10.0/bazel-gazelle-0.10.0.tar.gz",
sha256 = "6228d9618ab9536892aa69082c063207c91e777e51bd3c5544c9c060cafe1bd8",
)
load("@io_bazel_rules_go//go:def.bzl", "go_register_toolchains", "go_rules_dependencies")
go_rules_dependencies()
go_register_toolchains()
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
gazelle_dependencies()
http_archive(
name = "com_github_go_yaml_yaml",
urls = ["https://example.com/yaml.tar.gz"],
sha256 = "1234",
)
# gazelle:repository_macro repositories.bzl%go_repositories
# gazelle:repository_macro repositories.bzl%foo_repositories
`,
}, {
Path: "repositories.bzl",
Content: `
load("@bazel_gazelle//:deps.bzl", "go_repository")
def go_repositories():
go_repository(
name = "org_golang_x_sys",
build_file_generation = "off",
commit = "bb24a47a89eac6c1227fbcb2ae37a8b9ed323366",
importpath = "golang.org/x/sys",
)
def foo_repositories():
go_repository(
name = "org_golang_x_net",
build_file_generation = "off",
commit = "66aacef3dd8a676686c7ae3716979581e8b03c47",
importpath = "golang.org/x/net",
)
go_repository(
name = "com_github_pkg_errors",
Expand All @@ -1360,7 +1571,8 @@ def go_repositories():
importpath = "github.com/pkg/errors",
)
`,
}})
},
})
}

func TestImportReposFromDepToEmptyMacro(t *testing.T) {
Expand Down
Loading

0 comments on commit 4f524f2

Please sign in to comment.