Skip to content

Commit 3b93ee0

Browse files
authored
Add DefaultOutputPathInfo provider and update write_source_files to accept it (#48)
Also update write_source_files to accept DirectoryPathInfo
1 parent 7f2641c commit 3b93ee0

28 files changed

+622
-319
lines changed

.prettierignore

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
docs/*.md
22
lib/tests/jq/*.json
3-
lib/tests/write_source_files/a2.js
4-
lib/tests/write_source_files/b2.js
5-
lib/tests/write_source_files/e_dir/e.js
3+
lib/lib/tests/write_source_files/*.js
4+
lib/lib/tests/write_source_files/subdir/*.js
5+
lib/lib/tests/write_source_files/subdir/subsubdir/*.js

docs/BUILD.bazel

+5-2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ stardoc_with_diff_test(
4848
bzl_library_target = "//lib:directory_path",
4949
)
5050

51-
update_docs(
52-
name = "update",
51+
stardoc_with_diff_test(
52+
name = "default_info_files",
53+
bzl_library_target = "//lib:default_info_files",
5354
)
55+
56+
update_docs()

docs/default_info_files.md

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<!-- Generated with Stardoc: http://skydoc.bazel.build -->
2+
3+
A rule that provides file(s) from a given target's DefaultInfo
4+
5+
6+
<a id="#default_info_files"></a>
7+
8+
## default_info_files
9+
10+
<pre>
11+
default_info_files(<a href="#default_info_files-name">name</a>, <a href="#default_info_files-paths">paths</a>, <a href="#default_info_files-target">target</a>)
12+
</pre>
13+
14+
A rule that provides file(s) from a given target's DefaultInfo
15+
16+
**ATTRIBUTES**
17+
18+
19+
| Name | Description | Type | Mandatory | Default |
20+
| :------------- | :------------- | :------------- | :------------- | :------------- |
21+
| <a id="default_info_files-name"></a>name | A unique name for this target. | <a href="https://bazel.build/docs/build-ref.html#name">Name</a> | required | |
22+
| <a id="default_info_files-paths"></a>paths | the paths of the files to provide in the DefaultInfo of the target relative to its root | List of strings | required | |
23+
| <a id="default_info_files-target"></a>target | the target to look in for requested paths in its' DefaultInfo | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | required | |
24+
25+
26+
<a id="#make_default_info_files"></a>
27+
28+
## make_default_info_files
29+
30+
<pre>
31+
make_default_info_files(<a href="#make_default_info_files-name">name</a>, <a href="#make_default_info_files-target">target</a>, <a href="#make_default_info_files-paths">paths</a>)
32+
</pre>
33+
34+
Helper function to generate a default_info_files target and return its label.
35+
36+
**PARAMETERS**
37+
38+
39+
| Name | Description | Default Value |
40+
| :------------- | :------------- | :------------- |
41+
| <a id="make_default_info_files-name"></a>name | unique name for the generated <code>default_info_files</code> target. | none |
42+
| <a id="make_default_info_files-target"></a>target | the target to look in for requested paths in its' DefaultInfo | none |
43+
| <a id="make_default_info_files-paths"></a>paths | the paths of the files to provide in the DefaultInfo of the target relative to its root | none |
44+
45+
**RETURNS**
46+
47+
The label `name`
48+
49+

docs/directory_path.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Joins a label pointing to a TreeArtifact with a path nested within that director
5353
make_directory_path(<a href="#make_directory_path-name">name</a>, <a href="#make_directory_path-directory">directory</a>, <a href="#make_directory_path-path">path</a>)
5454
</pre>
5555

56-
Helper function to convert generate a directory_path target and return its label.
56+
Helper function to generate a directory_path target and return its label.
5757

5858
**PARAMETERS**
5959

docs/write_source_files.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ If you have many sources that you want to update as a group, we recommend wrappi
8787
| :------------- | :------------- | :------------- |
8888
| <a id="write_source_files-name"></a>name | Name of the executable target that creates or updates the source file | none |
8989
| <a id="write_source_files-files"></a>files | A dict where the keys are source files or folders to write to and the values are labels pointing to the desired content. Sources must be within the same bazel package as the target. | <code>{}</code> |
90-
| <a id="write_source_files-additional_update_targets"></a>additional_update_targets | (Optional) List of other write_source_files targets to update in the same run | <code>[]</code> |
91-
| <a id="write_source_files-suggested_update_target"></a>suggested_update_target | (Optional) Label of the write_source_files target to suggest running when files are out of date | <code>None</code> |
90+
| <a id="write_source_files-additional_update_targets"></a>additional_update_targets | (Optional) List of other write_source_file or other executable updater targets to call in the same run | <code>[]</code> |
91+
| <a id="write_source_files-suggested_update_target"></a>suggested_update_target | (Optional) Label of the write_source_file target to suggest running when files are out of date | <code>None</code> |
9292
| <a id="write_source_files-kwargs"></a>kwargs | Other common named parameters such as <code>tags</code> or <code>visibility</code> | none |
9393

9494

lib/BUILD.bazel

+16-2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ bzl_library(
6363
deps = ["//lib/private:directory_path"],
6464
)
6565

66+
bzl_library(
67+
name = "default_info_files",
68+
srcs = ["default_info_files.bzl"],
69+
visibility = ["//visibility:public"],
70+
deps = ["//lib/private:default_info_files"],
71+
)
72+
6673
bzl_library(
6774
name = "copy_to_directory",
6875
srcs = ["copy_to_directory.bzl"],
@@ -80,9 +87,16 @@ bzl_library(
8087
srcs = ["write_source_files.bzl"],
8188
visibility = ["//visibility:public"],
8289
deps = [
90+
":diff_test",
8391
":utils",
8492
"//lib/private:fail_with_message_test",
85-
"//lib/private:write_source_files",
86-
"@bazel_skylib//rules:diff_test",
93+
"//lib/private:write_source_file",
8794
],
8895
)
96+
97+
bzl_library(
98+
name = "diff_test",
99+
srcs = ["diff_test.bzl"],
100+
visibility = ["//visibility:public"],
101+
deps = ["//lib/private:diff_test"],
102+
)

lib/default_info_files.bzl

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"""A rule that provides file(s) from a given target's DefaultInfo
2+
"""
3+
4+
load(
5+
"//lib/private:default_info_files.bzl",
6+
_default_info_files = "default_info_files",
7+
_make_default_info_files = "make_default_info_files",
8+
)
9+
10+
default_info_files = _default_info_files
11+
make_default_info_files = _make_default_info_files

lib/directory_path.bzl

-14
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,3 @@
1-
# Copyright 2019 The Bazel Authors. All rights reserved.
2-
#
3-
# Licensed under the Apache License, Version 2.0 (the "License");
4-
# you may not use this file except in compliance with the License.
5-
# You may obtain a copy of the License at
6-
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# Unless required by applicable law or agreed to in writing, software
10-
# distributed under the License is distributed on an "AS IS" BASIS,
11-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
# See the License for the specific language governing permissions and
13-
# limitations under the License.
14-
151
"""Rule and corresponding provider that joins a label pointing to a TreeArtifact
162
with a path nested within that directory
173
"""

lib/private/BUILD.bazel

+21-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ bzl_library(
1010
srcs = ["copy_to_directory.bzl"],
1111
visibility = ["//lib:__subpackages__"],
1212
deps = [
13+
":default_info_files",
1314
":directory_path",
1415
":paths",
1516
"@bazel_skylib//lib:paths",
@@ -61,10 +62,14 @@ bzl_library(
6162
)
6263

6364
bzl_library(
64-
name = "write_source_files",
65-
srcs = ["write_source_files.bzl"],
65+
name = "write_source_file",
66+
srcs = ["write_source_file.bzl"],
6667
visibility = ["//lib:__subpackages__"],
67-
deps = ["//lib:utils"],
68+
deps = [
69+
":default_info_files",
70+
":directory_path",
71+
"//lib:utils",
72+
],
6873
)
6974

7075
bzl_library(
@@ -79,3 +84,16 @@ bzl_library(
7984
visibility = ["//lib:__subpackages__"],
8085
deps = ["//lib:utils"],
8186
)
87+
88+
bzl_library(
89+
name = "default_info_files",
90+
srcs = ["default_info_files.bzl"],
91+
visibility = ["//lib:__subpackages__"],
92+
deps = ["//lib:utils"],
93+
)
94+
95+
bzl_library(
96+
name = "diff_test",
97+
srcs = ["diff_test.bzl"],
98+
visibility = ["//lib:__subpackages__"],
99+
)

lib/private/copy_file.bzl

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def _copy_file_impl(ctx):
127127
src_path = "/".join([src_file.path, ctx.attr.src[DirectoryPathInfo].path])
128128
else:
129129
if len(ctx.files.src) != 1:
130-
fail("src must be a single file or a target with a DirectoryPathInfo provider")
130+
fail("src must be a single file or a target that provides a DirectoryPathInfo")
131131
src_file = ctx.files.src[0]
132132
src_path = src_file.path
133133
if ctx.attr.is_windows:

lib/private/default_info_files.bzl

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
"""default_info_files implementation
2+
"""
3+
4+
load("//lib:utils.bzl", _to_label = "to_label")
5+
6+
def _default_info_files(ctx):
7+
files = []
8+
for path in ctx.attr.paths:
9+
file = find_short_path_in_default_info(
10+
ctx.attr.target,
11+
path,
12+
)
13+
if not file:
14+
fail("%s file not found within the DefaultInfo of %s" % (ctx.attr.path, ctx.attr.target))
15+
files.append(file)
16+
return [DefaultInfo(
17+
files = depset(direct = files),
18+
runfiles = ctx.runfiles(files = files),
19+
)]
20+
21+
default_info_files = rule(
22+
doc = "A rule that provides file(s) from a given target's DefaultInfo",
23+
implementation = _default_info_files,
24+
attrs = {
25+
"target": attr.label(
26+
doc = "the target to look in for requested paths in its' DefaultInfo",
27+
mandatory = True,
28+
),
29+
"paths": attr.string_list(
30+
doc = "the paths of the files to provide in the DefaultInfo of the target relative to its root",
31+
mandatory = True,
32+
allow_empty = False,
33+
),
34+
},
35+
provides = [DefaultInfo],
36+
)
37+
38+
def make_default_info_files(name, target, paths):
39+
"""Helper function to generate a default_info_files target and return its label.
40+
41+
Args:
42+
name: unique name for the generated `default_info_files` target.
43+
target: the target to look in for requested paths in its' DefaultInfo
44+
paths: the paths of the files to provide in the DefaultInfo of the target relative to its root
45+
46+
Returns:
47+
The label `name`
48+
"""
49+
default_info_files(
50+
name = name,
51+
target = target,
52+
paths = paths,
53+
)
54+
return _to_label(name)
55+
56+
def find_short_path_in_default_info(default_info, short_path):
57+
"""Helper function find a file in a DefaultInfo by short path
58+
59+
Args:
60+
default_info: a DefaultInfo
61+
short_path: the short path (path relative to root) to search for
62+
63+
Returns:
64+
The File if found else None
65+
"""
66+
if default_info.files:
67+
for file in default_info.files.to_list():
68+
if file.short_path == short_path:
69+
return file
70+
return None

lib/private/diff_test.bzl

+27-7
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,33 @@ The rule uses a Bash command (diff) on Linux/macOS/non-Windows, and a cmd.exe
1818
command (fc.exe) on Windows (no Bash is required).
1919
"""
2020

21+
load(":directory_path.bzl", "DirectoryPathInfo")
22+
2123
def _runfiles_path(f):
2224
if f.root.path:
2325
return f.path[len(f.root.path) + 1:] # generated file
2426
else:
2527
return f.path # source file
2628

2729
def _diff_test_impl(ctx):
30+
if DirectoryPathInfo in ctx.attr.file1:
31+
file1 = ctx.attr.file1[DirectoryPathInfo].directory
32+
file1_path = "/".join([_runfiles_path(file1), ctx.attr.file1[DirectoryPathInfo].path])
33+
else:
34+
if len(ctx.files.file1) != 1:
35+
fail("file1 must be a single file or a target that provides a DirectoryPathInfo")
36+
file1 = ctx.files.file1[0]
37+
file1_path = _runfiles_path(file1)
38+
39+
if DirectoryPathInfo in ctx.attr.file2:
40+
file2 = ctx.attr.file2[DirectoryPathInfo].directory
41+
file2_path = "/".join([_runfiles_path(file2), ctx.attr.file2[DirectoryPathInfo].path])
42+
else:
43+
if len(ctx.files.file2) != 1:
44+
fail("file2 must be a single file or a target that provides a DirectoryPathInfo")
45+
file2 = ctx.files.file2[0]
46+
file2_path = _runfiles_path(file2)
47+
2848
if ctx.attr.is_windows:
2949
test_bin = ctx.actions.declare_file(ctx.label.name + "-test.bat")
3050
ctx.actions.write(
@@ -138,8 +158,8 @@ exit /b 0
138158
exit /b 1
139159
""".format(
140160
fail_msg = ctx.attr.failure_message,
141-
file1 = _runfiles_path(ctx.file.file1),
142-
file2 = _runfiles_path(ctx.file.file2),
161+
file1 = file1_path,
162+
file2 = file2_path,
143163
),
144164
is_executable = True,
145165
)
@@ -191,26 +211,26 @@ else
191211
fi
192212
""".format(
193213
fail_msg = ctx.attr.failure_message,
194-
file1 = _runfiles_path(ctx.file.file1),
195-
file2 = _runfiles_path(ctx.file.file2),
214+
file1 = file1_path,
215+
file2 = file2_path,
196216
),
197217
is_executable = True,
198218
)
199219
return DefaultInfo(
200220
executable = test_bin,
201221
files = depset(direct = [test_bin]),
202-
runfiles = ctx.runfiles(files = [test_bin, ctx.file.file1, ctx.file.file2]),
222+
runfiles = ctx.runfiles(files = [test_bin, file1, file2]),
203223
)
204224

205225
_diff_test = rule(
206226
attrs = {
207227
"failure_message": attr.string(),
208228
"file1": attr.label(
209-
allow_single_file = True,
229+
allow_files = True,
210230
mandatory = True,
211231
),
212232
"file2": attr.label(
213-
allow_single_file = True,
233+
allow_files = True,
214234
mandatory = True,
215235
),
216236
"is_windows": attr.bool(mandatory = True),

lib/private/directory_path.bzl

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ Otherwise there is no way to give a Bazel label for it.""",
3333
mandatory = True,
3434
),
3535
},
36+
provides = [DirectoryPathInfo],
3637
)
3738

3839
def make_directory_path(name, directory, path):
39-
"""Helper function to convert generate a directory_path target and return its label.
40+
"""Helper function to generate a directory_path target and return its label.
4041
4142
Args:
4243
name: Unique name for the generated `directory_path` target.

0 commit comments

Comments
 (0)