1# Copyright 2020 The gRPC authors.
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
15def _generate_copied_files_impl(ctx):
16    srcs = ctx.attr.srcs[0]
17    strip_prefix = ctx.attr.strip_prefix
18    dest = ctx.attr.dest
19
20    outs = []
21    for f in srcs.files.to_list():
22        destination_path = f.path
23        if f.path.startswith("external"):
24            external_separator = f.path.find("/")
25            repository_separator = f.path.find("/", external_separator + 1)
26            destination_path = f.path[repository_separator + 1:]
27        if not destination_path.startswith(strip_prefix):
28            fail("File '{}' did not start with '{}'.".format(
29                destination_path,
30                strip_prefix,
31            ))
32        destination_path = dest + destination_path[len(strip_prefix):]
33        destination_dir = destination_path.rfind("/")
34        out_file = ctx.actions.declare_file(destination_path)
35        outs.append(out_file)
36        ctx.actions.run_shell(
37            inputs = [f],
38            outputs = [out_file],
39            command = "mkdir -p {0} && cp {1} {2}".format(
40                out_file.dirname,
41                f.path,
42                out_file.path,
43            ),
44        )
45
46    return [DefaultInfo(files = depset(direct = outs))]
47
48_generate_copied_files = rule(
49    attrs = {
50        "srcs": attr.label_list(
51            mandatory = True,
52            allow_empty = False,
53        ),
54        "strip_prefix": attr.string(
55            default = "",
56        ),
57        "dest": attr.string(
58            mandatory = True,
59        ),
60    },
61    implementation = _generate_copied_files_impl,
62)
63
64def internal_copied_filegroup(name, srcs, strip_prefix, dest):
65    """Copies a file group to the current package.
66
67    Useful for using an existing filegroup as a data dependency.
68
69    Args:
70      name: The name of the rule.
71      srcs: A single filegroup.
72      strip_prefix: An optional string to strip from the beginning
73        of the path of each file in the filegroup. Must end in a slash.
74      dest: The directory in which to put the files, relative to the
75        current package. Must end in a slash.
76    """
77    if len(srcs) != 1:
78        fail("srcs must be a single filegroup.")
79
80    if not dest.endswith("/"):
81        fail("dest must end with a '/' character.")
82
83    _symlink_target = name + "_symlink"
84    _generate_copied_files(
85        name = _symlink_target,
86        srcs = srcs,
87        strip_prefix = strip_prefix,
88        dest = dest,
89    )
90
91    native.filegroup(
92        name = name,
93        srcs = [":" + _symlink_target],
94    )
95