diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkBaseExternalContext.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkBaseExternalContext.java index c250dfe966049c..e295a2b45892dd 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkBaseExternalContext.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkBaseExternalContext.java @@ -556,8 +556,10 @@ public boolean cancel() { @StarlarkMethod( name = "wait", doc = - "Blocks until the completion of the download and returns or throws as blocking " - + " download() call would") + """ + Blocks until the completion of the download and returns or throws as blocking \ + download() call would. + """) public StructImpl await() throws InterruptedException, RepositoryFunctionException { return completeDownload(this); } @@ -599,10 +601,15 @@ private StructImpl completeDownload(PendingDownload pendingDownload) @StarlarkMethod( name = "download", doc = - "Downloads a file to the output path for the provided url and returns a struct" - + " containing success, a flag which is true if the" - + " download completed successfully, and if successful, a hash of the file" - + " with the fields sha256 and integrity.", + """ +Downloads a file to the output path for the provided url and returns a struct \ +containing success, a flag which is true if the \ +download completed successfully, and if successful, a hash of the file \ +with the fields sha256 and integrity. \ +When sha256 or integrity is user specified, setting an explicit \ +canonical_id is highly recommended. e.g. \ +get_default_canonical_id +""", useStarlarkThread = true, parameters = { @Param( @@ -628,34 +635,40 @@ private StructImpl completeDownload(PendingDownload pendingDownload) defaultValue = "''", named = true, doc = - "the expected SHA-256 hash of the file downloaded." - + " This must match the SHA-256 hash of the file downloaded. It is a security" - + " risk to omit the SHA-256 as remote files can change. At best omitting this" - + " field will make your build non-hermetic. It is optional to make development" - + " easier but should be set before shipping." - + " If provided, the repository cache will first be checked for a file with the" - + " given hash; a download will only be attempted if the file was not found in" - + " the cache. After a successful download, the file will be added to the cache."), + """ + The expected SHA-256 hash of the file downloaded. \ + This must match the SHA-256 hash of the file downloaded. It is a security \ + risk to omit the SHA-256 as remote files can change. At best omitting this \ + field will make your build non-hermetic. It is optional to make development \ + easier but should be set before shipping. \ + If provided, the repository cache will first be checked for a file with the \ + given hash; a download will only be attempted if the file was not found in \ + the cache. After a successful download, the file will be added to the cache. + """), @Param( name = "executable", defaultValue = "False", named = true, - doc = "set the executable flag on the created file, false by default."), + doc = "Set the executable flag on the created file, false by default."), @Param( name = "allow_fail", defaultValue = "False", named = true, doc = - "If set, indicate the error in the return value" - + " instead of raising an error for failed downloads"), + """ + If set, indicate the error in the return value \ + instead of raising an error for failed downloads. + """), @Param( name = "canonical_id", defaultValue = "''", named = true, doc = - "If set, restrict cache hits to those cases where the file was added to the cache" - + " with the same canonical id. By default caching uses the checksum" - + "(sha256 or integrity)."), + """ + If set, restrict cache hits to those cases where the file was added to the cache \ + with the same canonical id. By default caching uses the checksum \ + (sha256 or integrity). + """), @Param( name = "auth", defaultValue = "{}", @@ -672,24 +685,28 @@ private StructImpl completeDownload(PendingDownload pendingDownload) named = true, positional = false, doc = - "Expected checksum of the file downloaded, in Subresource Integrity format." - + " This must match the checksum of the file downloaded. It is a security" - + " risk to omit the checksum as remote files can change. At best omitting this" - + " field will make your build non-hermetic. It is optional to make development" - + " easier but should be set before shipping." - + " If provided, the repository cache will first be checked for a file with the" - + " given checksum; a download will only be attempted if the file was not found in" - + " the cache. After a successful download, the file will be added to the cache."), + """ + Expected checksum of the file downloaded, in Subresource Integrity format. \ + This must match the checksum of the file downloaded. It is a security \ + risk to omit the checksum as remote files can change. At best omitting this \ + field will make your build non-hermetic. It is optional to make development \ + easier but should be set before shipping. \ + If provided, the repository cache will first be checked for a file with the \ + given checksum; a download will only be attempted if the file was not found in \ + the cache. After a successful download, the file will be added to the cache. + """), @Param( name = "block", defaultValue = "True", named = true, positional = false, doc = - "If set to false, the call returns immediately and instead of the regular return" - + " value, it returns a token with one single method, wait(), which blocks" - + " until the download is finished and returns the usual return value or" - + " throws as usual.") + """ + If set to false, the call returns immediately and instead of the regular return \ + value, it returns a token with one single method, wait(), which blocks \ + until the download is finished and returns the usual return value or \ + throws as usual. + """) }) public Object download( Object url, @@ -786,10 +803,15 @@ public Object download( @StarlarkMethod( name = "download_and_extract", doc = - "Downloads a file to the output path for the provided url, extracts it, and returns a" - + " struct containing success, a flag which is true if the" - + " download completed successfully, and if successful, a hash of the file with the" - + " fields sha256 and integrity.", + """ +Downloads a file to the output path for the provided url, extracts it, and returns a \ +struct containing success, a flag which is true if the \ +download completed successfully, and if successful, a hash of the file with the \ +fields sha256 and integrity. \ +When sha256 or integrity is user specified, setting an explicit \ +canonical_id is highly recommended. e.g. \ +get_default_canonical_id +""", useStarlarkThread = true, parameters = { @Param( @@ -810,57 +832,69 @@ public Object download( defaultValue = "''", named = true, doc = - "path to the directory where the archive will be unpacked," - + " relative to the repository directory."), + """ + Path to the directory where the archive will be unpacked, \ + relative to the repository directory. + """), @Param( name = "sha256", defaultValue = "''", named = true, doc = - "the expected SHA-256 hash of the file downloaded." - + " This must match the SHA-256 hash of the file downloaded. It is a security" - + " risk to omit the SHA-256 as remote files can change. At best omitting this" - + " field will make your build non-hermetic. It is optional to make development" - + " easier but should be set before shipping." - + " If provided, the repository cache will first be checked for a file with the" - + " given hash; a download will only be attempted if the file was not found in" - + " the cache. After a successful download, the file will be added to the" - + " cache."), + """ + The expected SHA-256 hash of the file downloaded. \ + This must match the SHA-256 hash of the file downloaded. It is a security \ + risk to omit the SHA-256 as remote files can change. At best omitting this \ + field will make your build non-hermetic. It is optional to make development \ + easier but should be set before shipping. \ + If provided, the repository cache will first be checked for a file with the \ + given hash; a download will only be attempted if the file was not found in \ + the cache. After a successful download, the file will be added to the \ + cache. + """), @Param( name = "type", defaultValue = "''", named = true, doc = - "the archive type of the downloaded file. By default, the archive type is" - + " determined from the file extension of the URL. If the file has no" - + " extension, you can explicitly specify either \"zip\", \"jar\", \"war\"," - + " \"aar\", \"tar\", \"tar.gz\", \"tgz\", \"tar.xz\", \"txz\", \".tar.zst\"," - + " \".tzst\", \"tar.bz2\", \".tbz\", \".ar\", or \".deb\" here."), + """ + The archive type of the downloaded file. By default, the archive type is \ + determined from the file extension of the URL. If the file has no \ + extension, you can explicitly specify either "zip", "jar", "war", \ + "aar", "tar", "tar.gz", "tgz", "tar.xz", "txz", ".tar.zst", \ + ".tzst", "tar.bz2", ".tbz", ".ar", or ".deb" here. + """), @Param( name = "stripPrefix", defaultValue = "''", named = true, doc = - "a directory prefix to strip from the extracted files." - + "\nMany archives contain a top-level directory that contains all files in the" - + " archive. Instead of needing to specify this prefix over and over in the" - + " build_file, this field can be used to strip it from extracted" - + " files."), + """ + A directory prefix to strip from the extracted files. + Many archives contain a top-level directory that contains all files in the \ + archive. Instead of needing to specify this prefix over and over in the \ + build_file, this field can be used to strip it from extracted \ + files. + """), @Param( name = "allow_fail", defaultValue = "False", named = true, doc = - "If set, indicate the error in the return value" - + " instead of raising an error for failed downloads"), + """ + If set, indicate the error in the return value \ + instead of raising an error for failed downloads. + """), @Param( name = "canonical_id", defaultValue = "''", named = true, doc = - "If set, restrict cache hits to those cases where the file was added to the cache" - + " with the same canonical id. By default caching uses the checksum" - + "(sha256 or integrity)."), + """ + If set, restrict cache hits to those cases where the file was added to the cache \ + with the same canonical id. By default caching uses the checksum" + (sha256 or integrity). + """), @Param( name = "auth", defaultValue = "{}", @@ -877,25 +911,29 @@ public Object download( named = true, positional = false, doc = - "Expected checksum of the file downloaded, in Subresource Integrity format." - + " This must match the checksum of the file downloaded. It is a security" - + " risk to omit the checksum as remote files can change. At best omitting this" - + " field will make your build non-hermetic. It is optional to make development" - + " easier but should be set before shipping." - + " If provided, the repository cache will first be checked for a file with the" - + " given checksum; a download will only be attempted if the file was not found in" - + " the cache. After a successful download, the file will be added to the cache."), + """ + Expected checksum of the file downloaded, in Subresource Integrity format. \ + This must match the checksum of the file downloaded. It is a security \ + risk to omit the checksum as remote files can change. At best omitting this \ + field will make your build non-hermetic. It is optional to make development \ + easier but should be set before shipping. \ + If provided, the repository cache will first be checked for a file with the \ + given checksum; a download will only be attempted if the file was not found in \ + the cache. After a successful download, the file will be added to the cache. \ + """), @Param( name = "rename_files", defaultValue = "{}", named = true, positional = false, doc = - "An optional dict specifying files to rename during the extraction. Archive entries" - + " with names exactly matching a key will be renamed to the value, prior to" - + " any directory prefix adjustment. This can be used to extract archives that" - + " contain non-Unicode filenames, or which have files that would extract to" - + " the same path on case-insensitive filesystems."), + """ +An optional dict specifying files to rename during the extraction. Archive entries \ +with names exactly matching a key will be renamed to the value, prior to \ +any directory prefix adjustment. This can be used to extract archives that \ +contain non-Unicode filenames, or which have files that would extract to \ +the same path on case-insensitive filesystems. +"""), }) public StructImpl downloadAndExtract( Object url, @@ -1190,24 +1228,26 @@ public boolean isFinished() { @ParamType(type = Label.class), @ParamType(type = StarlarkPath.class) }, - doc = "path of the file to create, relative to the repository directory."), + doc = "Path of the file to create, relative to the repository directory."), @Param( name = "content", named = true, defaultValue = "''", - doc = "the content of the file to create, empty by default."), + doc = "The content of the file to create, empty by default."), @Param( name = "executable", named = true, defaultValue = "True", - doc = "set the executable flag on the created file, true by default."), + doc = "Set the executable flag on the created file, true by default."), @Param( name = "legacy_utf8", named = true, defaultValue = "True", doc = - "encode file content to UTF-8, true by default. Future versions will change" - + " the default and remove this parameter."), + """ + Encode file content to UTF-8, true by default. Future versions will change \ + the default and remove this parameter. + """), }) public void createFile( Object path, String content, Boolean executable, Boolean legacyUtf8, StarlarkThread thread) @@ -1254,18 +1294,20 @@ private static T nullIfNone(Object object, Class type) { @StarlarkMethod( name = "getenv", doc = - "Returns the value of an environment variable name as a string if exists, " - + "or default if it doesn't." - + "

When building incrementally, any change to the value of the variable named by " - + "name will cause this repository to be re-fetched.", + """ + Returns the value of an environment variable name as a string if exists, \ + or default if it doesn't. \ +

When building incrementally, any change to the value of the variable named by \ + name will cause this repository to be re-fetched. + """, parameters = { @Param( name = "name", - doc = "name of desired environment variable", + doc = "Name of desired environment variable.", allowedTypes = {@ParamType(type = String.class)}), @Param( name = "default", - doc = "Default value to return if `name` is not found", + doc = "Default value to return if name is not found.", allowedTypes = {@ParamType(type = String.class), @ParamType(type = NoneType.class)}, defaultValue = "None") }, @@ -1289,12 +1331,14 @@ public String getEnvironmentValue(String name, Object defaultValue) @StarlarkMethod( name = "path", doc = - "Returns a path from a string, label or path. If the path is relative, it will resolve " - + "relative to the repository directory. If the path is a label, it will resolve to " - + "the path of the corresponding file. Note that remote repositories are executed " - + "during the analysis phase and thus cannot depends on a target result (the " - + "label should point to a non-generated file). If path is a path, it will return " - + "that path as is.", + """ + Returns a path from a string, label or path. If the path is relative, it will resolve \ + relative to the repository directory. If the path is a label, it will resolve to \ + the path of the corresponding file. Note that remote repositories are executed \ + during the analysis phase and thus cannot depends on a target result (the \ + label should point to a non-generated file). If path is a path, it will return \ + that path as is. + """, parameters = { @Param( name = "path", @@ -1303,7 +1347,9 @@ public String getEnvironmentValue(String name, Object defaultValue) @ParamType(type = Label.class), @ParamType(type = StarlarkPath.class) }, - doc = "string, label or path from which to create a path from") + doc = + "string, Label or path from which to create" + + " a path from.") }) public StarlarkPath path(Object path) throws EvalException, InterruptedException { return getPath("path()", path); @@ -1335,19 +1381,21 @@ protected StarlarkPath getPath(String method, Object path) @ParamType(type = Label.class), @ParamType(type = StarlarkPath.class) }, - doc = "path of the file to read from."), + doc = "Path of the file to read from."), @Param( name = "watch", defaultValue = "'auto'", positional = false, named = true, doc = - "whether to watch the file. Can be the string 'yes', 'no', " - + "or 'auto'. Passing 'yes' is equivalent to immediately invoking the " - + "watch() method; passing 'no' does not " - + "attempt to watch the file; passing 'auto' will only attempt to watch the " - + "file when it is legal to do so (see watch() docs for more " - + "information.") + """ + Whether to watch the file. Can be the string 'yes', 'no', \ + or 'auto'. Passing 'yes' is equivalent to immediately invoking the \ + watch() method; passing 'no' does not \ + attempt to watch the file; passing 'auto' will only attempt to watch the \ + file when it is legal to do so (see watch() docs for more \ + information. + """) }) public String readFile(Object path, String watch, StarlarkThread thread) throws RepositoryFunctionException, EvalException, InterruptedException { @@ -1480,18 +1528,20 @@ protected void maybeWatchDirents(Path path, ShouldWatch shouldWatch) @StarlarkMethod( name = "watch", doc = - "Tells Bazel to watch for changes to the given path, whether or not it exists, or " - + "whether it's a file or a directory. Any changes to the file or directory will " - + "invalidate this repository or module extension, and cause it to be refetched or " - + "re-evaluated next time.

\"Changes\" include changes to the contents of the file " - + "(if the path is a file); if the path was a file but is now a directory, or vice " - + "versa; and if the path starts or stops existing. Notably, this does not " - + "include changes to any files under the directory if the path is a directory. For " - + "that, use path.readdir() " - + "instead.

Note that attempting to watch paths inside the repo currently being " - + "fetched, or inside the working directory of the current module extension, will " - + "result in an error. A module extension attempting to watch a path outside the " - + "current Bazel workspace will also result in an error.", + """ + Tells Bazel to watch for changes to the given path, whether or not it exists, or \ + whether it's a file or a directory. Any changes to the file or directory will \ + invalidate this repository or module extension, and cause it to be refetched or \ + re-evaluated next time.

"Changes" include changes to the contents of the file \ + (if the path is a file); if the path was a file but is now a directory, or vice \ + versa; and if the path starts or stops existing. Notably, this does not \ + include changes to any files under the directory if the path is a directory. For \ + that, use path.readdir() \ + instead.

Note that attempting to watch paths inside the repo currently being \ + fetched, or inside the working directory of the current module extension, will \ + result in an error. A module extension attempting to watch a path outside the \ + current Bazel workspace will also result in an error. + """, parameters = { @Param( name = "path", @@ -1500,7 +1550,7 @@ protected void maybeWatchDirents(Path path, ShouldWatch shouldWatch) @ParamType(type = Label.class), @ParamType(type = StarlarkPath.class) }, - doc = "path of the file to watch."), + doc = "Path of the file to watch."), }) public void watchForStarlark(Object path) throws RepositoryFunctionException, EvalException, InterruptedException { @@ -1517,13 +1567,13 @@ protected static void makeDirectories(Path path) throws IOException { @StarlarkMethod( name = "report_progress", - doc = "Updates the progress status for the fetching of this repository or module extension", + doc = "Updates the progress status for the fetching of this repository or module extension.", parameters = { @Param( name = "status", defaultValue = "''", allowedTypes = {@ParamType(type = String.class)}, - doc = "string describing the current status of the fetch progress") + doc = "string describing the current status of the fetch progress.") }) public void reportProgress(String status) { env.getListener() @@ -1692,28 +1742,32 @@ private static String profileArgsDesc(String method, List args) { @StarlarkMethod( name = "execute", doc = - "Executes the command given by the list of arguments. The execution time of the command" - + " is limited by timeout (in seconds, default 600 seconds). This method" - + " returns an exec_result structure containing the output of the" - + " command. The environment map can be used to override some" - + " environment variables to be passed to the process.", + """ + Executes the command given by the list of arguments. The execution time of the command \ + is limited by timeout (in seconds, default 600 seconds). This method \ + returns an exec_result structure containing the output of the \ + command. The environment map can be used to override some \ + environment variables to be passed to the process. + """, useStarlarkThread = true, parameters = { @Param( name = "arguments", doc = - "List of arguments, the first element should be the path to the program to " - + "execute."), + """ + List of arguments, the first element should be the path to the program to \ + execute. + """), @Param( name = "timeout", named = true, defaultValue = "600", - doc = "maximum duration of the command in seconds (default is 600 seconds)."), + doc = "Maximum duration of the command in seconds (default is 600 seconds)."), @Param( name = "environment", defaultValue = "{}", named = true, - doc = "force some environment variables to be set to be passed to the process."), + doc = "Force some environment variables to be set to be passed to the process."), @Param( name = "quiet", defaultValue = "True", @@ -1724,8 +1778,11 @@ private static String profileArgsDesc(String method, List args) { defaultValue = "\"\"", named = true, doc = - "Working directory for command execution.\n" - + "Can be relative to the repository root or absolute."), + """ + Working directory for command execution. + Can be relative to the repository root or absolute. + The default is the repository root. + """), }) public StarlarkExecutionResult execute( Sequence arguments, // or or

NOTE: Retrieving an environment variable from this dictionary does not " - + "establish a dependency from a repository rule or module extension to the " - + "environment variable. To establish a dependency when looking up an " - + "environment variable, use either repository_ctx.getenv or " - + "module_ctx.getenv instead.") + """ + The dictionary of environment variables. \ +

NOTE: Retrieving an environment variable from this dictionary does not \ + establish a dependency from a repository rule or module extension to the \ + environment variable. To establish a dependency when looking up an \ + environment variable, use either repository_ctx.getenv or \ + module_ctx.getenv instead. + """) public ImmutableMap getEnvironmentVariables() { return environ; } @@ -60,8 +62,10 @@ public ImmutableMap getEnvironmentVariables() { name = "name", structField = true, doc = - "A string identifying the operating system Bazel is running on (the value of the" - + " \"os.name\" Java property converted to lower case).") + """ + A string identifying the operating system Bazel is running on (the value of the \ + "os.name" Java property converted to lower case). + """) public String getName() { return System.getProperty("os.name").toLowerCase(Locale.ROOT); } @@ -70,8 +74,10 @@ public String getName() { name = "arch", structField = true, doc = - "A string identifying the architecture Bazel is running on (the value of the \"os.arch\"" - + " Java property converted to lower case).") + """ + A string identifying the architecture Bazel is running on (the value of the \ + "os.arch" Java property converted to lower case). + """) public String getArch() { return System.getProperty("os.arch").toLowerCase(Locale.ROOT); } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkPath.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkPath.java index 3e676ecfdb8d78..0fda30e10f1911 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkPath.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkPath.java @@ -84,8 +84,10 @@ public String getBasename() { @StarlarkMethod( name = "readdir", doc = - "Returns the list of entries in the directory denoted by this path. Each entry is a " - + "path object itself.", + """ + Returns the list of entries in the directory denoted by this path. Each entry is a \ + path object itself. + """, parameters = { @Param( name = "watch", @@ -93,15 +95,16 @@ public String getBasename() { positional = false, named = true, doc = - "whether Bazel should watch the list of entries in this directory and refetch the " - + "repository or re-evaluate the module extension next time when any changes " - + "are detected. Changes to detect include entry creation, deletion, and " - + "renaming. Note that this doesn't watch the contents of any entries " - + "in the directory.

Can be the string 'yes', 'no', or 'auto'. If set to " - + "'auto', Bazel will only watch this directory when it is legal to do so (see " - + "repository_ctx.watch() " - + "docs for more information)."), + """ + whether Bazel should watch the list of entries in this directory and refetch the \ + repository or re-evaluate the module extension next time when any changes \ + are detected. Changes to detect include entry creation, deletion, and \ + renaming. Note that this doesn't watch the contents of any entries \ + in the directory.

Can be the string 'yes', 'no', or 'auto'. If set to \ + 'auto', Bazel will only watch this directory when it is legal to do so (see \ + repository_ctx.watch() \ + docs for more information). + """), }) public ImmutableList readdir(String watch) throws EvalException, RepositoryFunctionException, InterruptedException { @@ -138,8 +141,10 @@ public StarlarkPath getDirname() { @Param( name = "relative_paths", doc = - "Zero or more relative path strings to append to this path with path separators" - + "added as needed.")) + """ + Zero or more relative path strings to append to this path with path separators \ + added as needed. + """)) public StarlarkPath getChild(Tuple relativePaths) throws EvalException { return new StarlarkPath( ctx, @@ -153,10 +158,12 @@ public StarlarkPath getChild(Tuple relativePaths) throws EvalException { name = "exists", structField = true, doc = - "Returns true if the file or directory denoted by this path exists.

Note that " - + "accessing this field does not cause the path to be watched. If you'd " - + "like the repo rule or module extension to be sensitive to the path's existence, " - + "use the watch() method on the context object.") + """ + Returns true if the file or directory denoted by this path exists.

Note that \ + accessing this field does not cause the path to be watched. If you'd \ + like the repo rule or module extension to be sensitive to the path's existence, \ + use the watch() method on the context object. + """) public boolean exists() { return path.exists(); } @@ -165,10 +172,12 @@ public boolean exists() { name = "is_dir", structField = true, doc = - "Returns true if this path points to a directory.

Note that accessing this field does " - + "not cause the path to be watched. If you'd like the repo rule or module " - + "extension to be sensitive to whether the path is a directory or a file, use the " - + "watch() method on the context object.") + """ + Returns true if this path points to a directory.

Note that accessing this field does \ + not cause the path to be watched. If you'd like the repo rule or module \ + extension to be sensitive to whether the path is a directory or a file, use the \ + watch() method on the context object. + """) public boolean isDir() { return path.isDirectory(); } @@ -177,8 +186,10 @@ public boolean isDir() { name = "realpath", structField = true, doc = - "Returns the canonical path for this path by repeatedly replacing all symbolic links " - + "with their referents.") + """ + Returns the canonical path for this path by repeatedly replacing all symbolic links \ + with their referents. + """) public StarlarkPath realpath() throws IOException { return new StarlarkPath(ctx, path.resolveSymbolicLinks()); } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryContext.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryContext.java index 05a98da4e115f7..4c5ed3d3a6f040 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryContext.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryContext.java @@ -58,7 +58,6 @@ import net.starlark.java.annot.StarlarkMethod; import net.starlark.java.eval.Dict; import net.starlark.java.eval.EvalException; -import net.starlark.java.eval.Sequence; import net.starlark.java.eval.Starlark; import net.starlark.java.eval.StarlarkInt; import net.starlark.java.eval.StarlarkSemantics; @@ -69,10 +68,12 @@ name = "repository_ctx", category = DocCategory.BUILTIN, doc = - "The context of the repository rule containing" - + " helper functions and information about attributes. You get a repository_ctx object" - + " as an argument to the implementation function when you create a" - + " repository rule.") + """ + The context of the repository rule containing \ + helper functions and information about attributes. You get a repository_ctx object \ + as an argument to the implementation function when you create a \ + repository rule. + """) public class StarlarkRepositoryContext extends StarlarkBaseExternalContext { private final Rule rule; private final PathPackageLocator packageLocator; @@ -158,8 +159,10 @@ public StarlarkPath getWorkspaceRoot() { name = "attr", structField = true, doc = - "A struct to access the values of the attributes. The values are provided by " - + "the user (if not, a default value is used).") + """ + A struct to access the values of the attributes. The values are provided by \ + the user (if not, a default value is used). + """) public StructImpl getAttr() { return attrObject; } @@ -243,11 +246,13 @@ public void symlink(Object target, Object linkName, StarlarkThread thread) @StarlarkMethod( name = "template", doc = - "Generates a new file using a template. Every occurrence in " - + "template of a key of substitutions will be replaced by " - + "the corresponding value. The result is written in path. An optional" - + "executable argument (default to true) can be set to turn on or off" - + "the executable bit.", + """ + Generates a new file using a template. Every occurrence in \ + template of a key of substitutions will be replaced by \ + the corresponding value. The result is written in path. An optional \ + executable argument (default to true) can be set to turn on or off \ + the executable bit. + """, useStarlarkThread = true, parameters = { @Param( @@ -257,7 +262,7 @@ public void symlink(Object target, Object linkName, StarlarkThread thread) @ParamType(type = Label.class), @ParamType(type = StarlarkPath.class) }, - doc = "path of the file to create, relative to the repository directory."), + doc = "Path of the file to create, relative to the repository directory."), @Param( name = "template", allowedTypes = { @@ -265,29 +270,31 @@ public void symlink(Object target, Object linkName, StarlarkThread thread) @ParamType(type = Label.class), @ParamType(type = StarlarkPath.class) }, - doc = "path to the template file."), + doc = "Path to the template file."), @Param( name = "substitutions", defaultValue = "{}", named = true, - doc = "substitutions to make when expanding the template."), + doc = "Substitutions to make when expanding the template."), @Param( name = "executable", defaultValue = "True", named = true, - doc = "set the executable flag on the created file, true by default."), + doc = "Set the executable flag on the created file, true by default."), @Param( name = "watch_template", defaultValue = "'auto'", positional = false, named = true, doc = - "whether to watch the template file. Can be the string " - + "'yes', 'no', or 'auto'. Passing 'yes' is equivalent to immediately invoking " - + "the watch() method; passing 'no' does " - + "not attempt to watch the file; passing 'auto' will only attempt to watch " - + "the file when it is legal to do so (see watch() docs for more " - + "information."), + """ + Whether to watch the template file. Can be the string \ + 'yes', 'no', or 'auto'. Passing 'yes' is equivalent to immediately invoking \ + the watch() method; passing 'no' does \ + not attempt to watch the file; passing 'auto' will only attempt to watch \ + the file when it is legal to do so (see watch() docs for more \ + information. + """), }) public void createFileFromTemplate( Object path, @@ -356,16 +363,20 @@ protected ImmutableMap getRemoteExecProperties() throws EvalExce @StarlarkMethod( name = "delete", doc = - "Deletes a file or a directory. Returns a bool, indicating whether the file or directory" - + " was actually deleted by this call.", + """ + Deletes a file or a directory. Returns a bool, indicating whether the file or directory \ + was actually deleted by this call. + """, useStarlarkThread = true, parameters = { @Param( name = "path", allowedTypes = {@ParamType(type = String.class), @ParamType(type = StarlarkPath.class)}, doc = - "Path of the file to delete, relative to the repository directory, or absolute." - + " Can be a path or a string."), + """ + Path of the file to delete, relative to the repository directory, or absolute. \ + Can be a path or a string. + """), }) public boolean delete(Object pathObject, StarlarkThread thread) throws EvalException, RepositoryFunctionException, InterruptedException { @@ -386,12 +397,14 @@ public boolean delete(Object pathObject, StarlarkThread thread) @StarlarkMethod( name = "patch", doc = - "Apply a patch file to the root directory of external repository. " - + "The patch file should be a standard " - + "" - + "unified diff format file. " - + "The Bazel-native patch implementation doesn't support fuzz match and binary patch " - + "like the patch command line tool.", + """ + Apply a patch file to the root directory of external repository. \ + The patch file should be a standard \ + \ + unified diff format file. \ + The Bazel-native patch implementation doesn't support fuzz match and binary patch \ + like the patch command line tool. + """, useStarlarkThread = true, parameters = { @Param( @@ -402,25 +415,29 @@ public boolean delete(Object pathObject, StarlarkThread thread) @ParamType(type = StarlarkPath.class) }, doc = - "The patch file to apply, it can be label, relative path or absolute path. " - + "If it's a relative path, it will resolve to the repository directory."), + """ + The patch file to apply, it can be label, relative path or absolute path. \ + If it's a relative path, it will resolve to the repository directory. + """), @Param( name = "strip", named = true, defaultValue = "0", - doc = "strip the specified number of leading components from file names."), + doc = "Strip the specified number of leading components from file names."), @Param( name = "watch_patch", defaultValue = "'auto'", positional = false, named = true, doc = - "whether to watch the patch file. Can be the string " - + "'yes', 'no', or 'auto'. Passing 'yes' is equivalent to immediately invoking " - + "the watch() method; passing 'no' does " - + "not attempt to watch the file; passing 'auto' will only attempt to watch " - + "the file when it is legal to do so (see watch() docs for more " - + "information."), + """ + Whether to watch the patch file. Can be the string \ + 'yes', 'no', or 'auto'. Passing 'yes' is equivalent to immediately invoking \ + the watch() method; passing 'no' does \ + not attempt to watch the file; passing 'auto' will only attempt to watch \ + the file when it is legal to do so (see watch() docs for more \ + information. + """), }) public void patch(Object patchFile, StarlarkInt stripI, String watchPatch, StarlarkThread thread) throws EvalException, RepositoryFunctionException, InterruptedException { @@ -451,11 +468,13 @@ public void patch(Object patchFile, StarlarkInt stripI, String watchPatch, Starl @StarlarkMethod( name = "watch_tree", doc = - "Tells Bazel to watch for changes to any files or directories transitively under the " - + "given path. Any changes to the contents of files, the existence of files or " - + "directories, file names or directory names, will cause this repo to be " - + "refetched.

Note that attempting to watch paths inside the repo currently being " - + "fetched will result in an error. ", + """ + Tells Bazel to watch for changes to any files or directories transitively under the \ + given path. Any changes to the contents of files, the existence of files or \ + directories, file names or directory names, will cause this repo to be \ + refetched.

Note that attempting to watch paths inside the repo currently being \ + fetched will result in an error. + """, parameters = { @Param( name = "path", @@ -464,7 +483,7 @@ public void patch(Object patchFile, StarlarkInt stripI, String watchPatch, Starl @ParamType(type = Label.class), @ParamType(type = StarlarkPath.class) }, - doc = "path of the directory tree to watch."), + doc = "Path of the directory tree to watch."), }) public void watchTree(Object path) throws EvalException, InterruptedException, RepositoryFunctionException { @@ -496,66 +515,4 @@ public void watchTree(Object path) public String toString() { return "repository_ctx[" + rule.getLabel() + "]"; } - - /** - * Try to compute the paths of all attributes that are labels, including labels in list and dict - * arguments. - * - *

The value is ignored, but any missing information from the environment is detected (and an - * exception thrown). In this way, we can enforce that all arguments are evaluated before we start - * potentially more expensive operations. - */ - // TODO(wyv): somehow migrate this to the base context too. - public void enforceLabelAttributes() - throws EvalException, InterruptedException, NeedsSkyframeRestartException { - // TODO: If a labels fails to resolve to an existing regular file, we do not add a dependency on - // that fact - if the file is created later or changes its type, it will not trigger a rerun of - // the repository function. - StructImpl attr = getAttr(); - // Batch restarts as they are expensive - boolean needsRestart = false; - for (String name : attr.getFieldNames()) { - Object value = attr.getValue(name); - if (value instanceof Label) { - if (dependOnLabelIgnoringErrors((Label) value)) { - needsRestart = true; - } - } - if (value instanceof Sequence) { - for (Object entry : (Sequence) value) { - if (entry instanceof Label) { - if (dependOnLabelIgnoringErrors((Label) entry)) { - needsRestart = true; - } - } - } - } - if (value instanceof Dict) { - for (Object entry : ((Dict) value).keySet()) { - if (entry instanceof Label) { - if (dependOnLabelIgnoringErrors((Label) entry)) { - needsRestart = true; - } - } - } - } - } - - if (needsRestart) { - throw new NeedsSkyframeRestartException(); - } - } - - private boolean dependOnLabelIgnoringErrors(Label label) throws InterruptedException { - try { - getPathFromLabel(label); - } catch (NeedsSkyframeRestartException e) { - return true; - } catch (EvalException e) { - // EvalExceptions indicate labels not referring to existing files. This is fine, - // as long as they are never resolved to files in the execution of the rule; we allow - // non-strict rules. - } - return false; - } } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryFunction.java index b546dabc2f79ab..0f71e8a9fef4e4 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryFunction.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryFunction.java @@ -302,15 +302,6 @@ private RepositoryDirectoryValue.Builder fetchInternal( PrecomputedValue.REMOTE_EXECUTION_ENABLED.get(env); } - // Since restarting a repository function can be really expensive, we first ensure that - // all label-arguments can be resolved to paths. - try { - starlarkRepositoryContext.enforceLabelAttributes(); - } catch (NeedsSkyframeRestartException e) { - // Missing values are expected; just restart before we actually start the rule - return null; - } - // This rule is mainly executed for its side effect. Nevertheless, the return value is // of importance, as it provides information on how the call has to be modified to be a // reproducible rule. diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryModule.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryModule.java index aa0a813e273757..dabbd64778246c 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryModule.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/starlark/StarlarkRepositoryModule.java @@ -142,9 +142,11 @@ public StarlarkCallable repositoryRule( name = "repository_rule", category = DocCategory.BUILTIN, doc = - "A callable value that may be invoked during evaluation of the WORKSPACE file or within" - + " the implementation function of a module extension to instantiate and return a" - + " repository rule.") + """ + A callable value that may be invoked during evaluation of the WORKSPACE file or within \ + the implementation function of a module extension to instantiate and return a \ + repository rule. + """) public static final class RepositoryRuleFunction implements StarlarkCallable, StarlarkExportable, RuleFunction { private final RuleClass.Builder builder; diff --git a/src/test/shell/bazel/BUILD b/src/test/shell/bazel/BUILD index 22025b222c56db..fdfbc8cbfe2a97 100644 --- a/src/test/shell/bazel/BUILD +++ b/src/test/shell/bazel/BUILD @@ -844,13 +844,6 @@ sh_test( tags = ["no_windows"], ) -sh_test( - name = "starlark_prefetching_test", - srcs = ["starlark_prefetching_test.sh"], - data = [":test-deps"], - tags = ["no_windows"], -) - sh_test( name = "external_starlark_load_test", size = "large", diff --git a/src/test/shell/bazel/external_integration_test.sh b/src/test/shell/bazel/external_integration_test.sh index d416f0cee1f916..4efa706a937fc2 100755 --- a/src/test/shell/bazel/external_integration_test.sh +++ b/src/test/shell/bazel/external_integration_test.sh @@ -2665,7 +2665,7 @@ EOF mkdir main cd main - cat > foo.bzl <<'EOF' + cat > foo.bzl < bar.bzl <<'EOF' + cat > bar.bzl < repo.bzl < MODULE.bazel <$TEST_log || fail 'Expected fetch to succeed' + expect_log "canonical_id \"url-1 url-2\"" +} + +function test_default_canonical_id_disabled() { + cat > repo.bzl < MODULE.bazel <$TEST_log || fail 'Expected fetch to succeed' + expect_log "canonical_id \"\"" +} + function test_environ_incrementally() { # Set up workspace with a repository rule to examine env vars. Assert that undeclared # env vars don't trigger reevaluations. diff --git a/src/test/shell/bazel/starlark_prefetching_test.sh b/src/test/shell/bazel/starlark_prefetching_test.sh deleted file mode 100755 index dfceb7f261a4ae..00000000000000 --- a/src/test/shell/bazel/starlark_prefetching_test.sh +++ /dev/null @@ -1,281 +0,0 @@ -#!/bin/bash -# -# Copyright 2017 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. -# -# Verify that declared arguments of a repository rule are present before -# the first execution attempt of the rule is done. - -# Load the test setup defined in the parent directory -CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -source "${CURRENT_DIR}/../integration_test_setup.sh" \ - || { echo "integration_test_setup.sh not found!" >&2; exit 1; } - -test_label_arg() { - # Verify that a repository rule does not get restarted, if accessing - # one of its label arguments as file. - WRKDIR=`pwd` - rm -rf repo - rm -rf log - mkdir repo - cd repo - touch BUILD - cat > rule.bzl <> ${WRKDIR}/log"]) - ctx.file("WORKSPACE", "workspace(name = \"%s\")\n" % ctx.name) - ctx.symlink(ctx.attr.build_file, "BUILD") - -myrule=repository_rule(implementation=_impl, - attrs={ - "build_file" : attr.label(), - }) -EOF - cat > ext.BUILD <<'EOF' -genrule( - name="foo", - outs=["foo.txt"], - cmd = "echo foo > $@", -) -EOF - cat > WORKSPACE <<'EOF' -load("//:rule.bzl", "myrule") -myrule(name="ext", build_file="//:ext.BUILD") -EOF - write_default_lockfile "MODULE.bazel.lock" - bazel build @ext//:foo || fail "expected success" - [ `cat "${WRKDIR}/log" | wc -l` -eq 1 ] \ - || fail "did not find precisely one invocation of the action" -} - -test_unused_invalid_label_arg() { - # Verify that we preserve the behavior of allowing to pass labels that - # do referring to an non-existing path, if they are never used. - WRKDIR=`pwd` - rm -rf repo - mkdir repo - cd repo - touch BUILD - cat > rule.bzl <<'EOF' -def _impl(ctx): - ctx.file("WORKSPACE", "workspace(name = \"%s\")\n" % ctx.name) - ctx.file("BUILD", - "genrule(name=\"foo\", outs=[\"foo.txt\"], cmd = \"echo foo > $@\")") - -myrule=repository_rule(implementation=_impl, - attrs={ - "unused" : attr.label(), - }) -EOF - cat > WORKSPACE <<'EOF' -load("//:rule.bzl", "myrule") -myrule(name="ext", unused="//does/not/exist:file") -EOF - write_default_lockfile "MODULE.bazel.lock" - bazel build @ext//:foo || fail "expected success" -} - - -test_label_list_arg() { - # Verify that a repository rule does not get restarted, if accessing - # the entries of a label list as files. - WRKDIR=`pwd` - rm -rf repo - rm -rf log - mkdir repo - cd repo - touch BUILD - cat > rule.bzl <> ${WRKDIR}/log"]) - ctx.file("WORKSPACE", "workspace(name = \"%s\")\n" % ctx.name) - ctx.file("BUILD", """ -genrule( - name="foo", - srcs= ["src.txt"], - outs=["foo.txt"], - cmd = "cp \$< \$@", -) -""") - for f in ctx.attr.data: - ctx.execute(["/bin/sh", "-c", "cat %s >> src.txt" % ctx.path(f)]) - -myrule=repository_rule(implementation=_impl, - attrs={ - "data" : attr.label_list(), - }) -EOF - cat > WORKSPACE <<'EOF' -load("//:rule.bzl", "myrule") -myrule(name="ext", data = ["//:a.txt", "//:b.txt"]) -EOF - write_default_lockfile "MODULE.bazel.lock" - echo Hello > a.txt - echo World > b.txt - bazel build @ext//:foo || fail "expected success" - [ `cat "${WRKDIR}/log" | wc -l` -eq 1 ] \ - || fail "did not find precisely one invocation of the action" -} - -test_unused_invalid_label_list_arg() { - # Verify that we preserve the behavior of allowing to pass labels that - # do referring to an non-existing path, if they are never used. - # Here, test it if such labels are passed in a label list. - WRKDIR=`pwd` - rm -rf repo - mkdir repo - cd repo - touch BUILD - cat > rule.bzl <<'EOF' -def _impl(ctx): - ctx.file("WORKSPACE", "workspace(name = \"%s\")\n" % ctx.name) - ctx.file("BUILD", - "genrule(name=\"foo\", outs=[\"foo.txt\"], cmd = \"echo foo > $@\")") - -myrule=repository_rule(implementation=_impl, - attrs={ - "unused_list" : attr.label_list(), - }) -EOF - cat > WORKSPACE <<'EOF' -load("//:rule.bzl", "myrule") -myrule(name="ext", unused_list=["//does/not/exist:file1", - "//does/not/exists:file2"]) -EOF - write_default_lockfile "MODULE.bazel.lock" - bazel build @ext//:foo || fail "expected success" -} - -# Regression test for https://github.com/bazelbuild/bazel/issues/10515 -test_label_keyed_string_dict_arg() { - # Verify that Bazel preloads Labels from label_keyed_string_dict, and as a - # result, it runs the repository's implementation only once (i.e. it won't - # restart the corresponding SkyFunction). - WRKDIR=`pwd` - rm -rf repo - rm -rf log - mkdir repo - cd repo - touch BUILD - cat > rule.bzl <> ${WRKDIR}/log"]) - ctx.file("WORKSPACE", "workspace(name = \"%s\")\n" % ctx.name) - ctx.file("BUILD", """ -genrule( - name = "foo", - srcs = ["src.txt"], - outs = ["foo.txt"], - cmd = "cp \$< \$@", -) -""") - for f in ctx.attr.data: - # ctx.path(f) shouldn't trigger a restart since we've prefetched the value. - ctx.execute(["/bin/sh", "-c", "cat %s >> src.txt" % ctx.path(f)]) - -myrule = repository_rule( - implementation = _impl, - attrs = { - "data": attr.label_keyed_string_dict(), - }, -) -EOF - cat > WORKSPACE <<'EOF' -load("//:rule.bzl", "myrule") -myrule(name="ext", data = {"//:a.txt": "a", "//:b.txt": "b"}) -EOF - write_default_lockfile "MODULE.bazel.lock" - echo Hello > a.txt - echo World > b.txt - bazel build @ext//:foo || fail "expected success" - [ `cat "${WRKDIR}/log" | wc -l` -eq 1 ] \ - || fail "did not find precisely one invocation of the action" -} - -test_unused_invalid_label_keyed_string_dict_arg() { - # Verify that we preserve the behavior of allowing to pass labels that - # do referring to an non-existing path, if they are never used. - # Here, test it if such labels are passed in a label_keyed_string_dict. - WRKDIR=`pwd` - rm -rf repo - mkdir repo - cd repo - touch BUILD - cat > rule.bzl <<'EOF' -def _impl(ctx): - ctx.file("WORKSPACE", "workspace(name = \"%s\")\n" % ctx.name) - ctx.file("BUILD", - "genrule(name=\"foo\", outs=[\"foo.txt\"], cmd = \"echo foo > $@\")") - -myrule=repository_rule(implementation=_impl, - attrs={ - "unused_dict" : attr.label_keyed_string_dict(), - }) -EOF - cat > WORKSPACE <<'EOF' -load("//:rule.bzl", "myrule") -myrule(name="ext", unused_dict={"//does/not/exist:file1": "file1", - "//does/not/exists:file2": "file2"}) -EOF - write_default_lockfile "MODULE.bazel.lock" - bazel build @ext//:foo || fail "expected success" -} - -# Regression test for https://github.com/bazelbuild/bazel/issues/13441 -function test_files_tracked_with_non_existing_files() { - cat > rules.bzl <<'EOF' -def _repo_impl(ctx): - ctx.symlink(ctx.path(Label("@//:WORKSPACE")).dirname, "link") - print("b.txt: " + ctx.read("link/b.txt")) - print("c.txt: " + ctx.read("link/c.txt")) - - ctx.file("BUILD") - ctx.file("WORKSPACE") - -repo = repository_rule( - _repo_impl, - attrs = {"_files": attr.label_list( - default = [ - Label("@//:a.txt"), - Label("@//:b.txt"), - Label("@//:c.txt"), - ], - )}, -) -EOF - - cat > WORKSPACE <<'EOF' -load(":rules.bzl", "repo") -repo(name = "ext") -EOF - write_default_lockfile "MODULE.bazel.lock" - touch BUILD - - # a.txt is intentionally not created - echo "bbbb" > b.txt - echo "cccc" > c.txt - - # The missing file dependency is tolerated. - bazel build @ext//:all &> "$TEST_log" || fail "Expected repository rule to build" - expect_log "b.txt: bbbb" - expect_log "c.txt: cccc" - - echo "not_cccc" > c.txt - bazel build @ext//:all &> "$TEST_log" || fail "Expected repository rule to build" - expect_log "b.txt: bbbb" - expect_log "c.txt: not_cccc" -} - -run_suite "Starlark repo prefetching tests" diff --git a/src/test/tools/bzlmod/MODULE.bazel.lock b/src/test/tools/bzlmod/MODULE.bazel.lock index 2752940820ed82..2e91b9c460b717 100644 --- a/src/test/tools/bzlmod/MODULE.bazel.lock +++ b/src/test/tools/bzlmod/MODULE.bazel.lock @@ -108,7 +108,7 @@ }, "@@rules_jvm_external~//:extensions.bzl%maven": { "general": { - "bzlTransitiveDigest": "06WDcwoMOciaDDX09JBCxhi9KiKFGUIcXpQjCSle5AE=", + "bzlTransitiveDigest": "nCJBnRI68ndNaTFBoEY+PPV6B9hLz1V4M3YjjxCQFhk=", "usagesDigest": "G7bV9l+zJ2RkplFf3E987nj8RPcxAqfzTHS5Zdc3rZw=", "recordedFileInputs": { "@@rules_jvm_external~//rules_jvm_external_deps_install.json": "10442a5ae27d9ff4c2003e5ab71643bf0d8b48dcf968b4173fa274c3232a8c06" @@ -1132,7 +1132,7 @@ }, "@@rules_jvm_external~//:non-module-deps.bzl%non_module_deps": { "general": { - "bzlTransitiveDigest": "l6SlNloqPvd60dcuPdWiJNi3g3jfK76fcZc0i/Yr0dQ=", + "bzlTransitiveDigest": "Lxr/sC3jorQDfvqpluvFC7JhOi41kaZ6ESxDVC2LZ5s=", "usagesDigest": "Ogn82YkpKa5kvheD/dv6YN0tP3nfvTIqAuPJrebCbWM=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, @@ -1160,7 +1160,7 @@ }, "@@rules_python~//python/extensions:python.bzl%python": { "general": { - "bzlTransitiveDigest": "GnREFVYskmF5MZu1H3nyqMWFZ2U/bty7gcbHX+l45kY=", + "bzlTransitiveDigest": "M7E/O6D+cJQoC4ZmcJ+cmXXJT2JMff2FRpQyHtoDQCQ=", "usagesDigest": "dMk5TOHswAZLEIKE5VenuXubFWbTzMdJplFIkYHPSSU=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, @@ -1190,7 +1190,7 @@ }, "@@rules_python~//python/extensions/private:internal_deps.bzl%internal_deps": { "general": { - "bzlTransitiveDigest": "PiT9IOA5dSBSmnfZRUrvgo71zttPpvs3cNPbxftlChs=", + "bzlTransitiveDigest": "X9KNWFFpQp2+YidRYA7/EpZiRW/JtKz7Qh788dYYBlM=", "usagesDigest": "B/G2N6d9Y4VpHFgkQT4wRYFBJ9RP+vFT/Ngiwz7Ejt8=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, diff --git a/tools/build_defs/repo/BUILD b/tools/build_defs/repo/BUILD index 5106cd4aa4a06e..7f4421ec4a22bf 100644 --- a/tools/build_defs/repo/BUILD +++ b/tools/build_defs/repo/BUILD @@ -40,6 +40,7 @@ genrule( ) REPO_BZL_FILES = [ + "cache", "git", "http", "local", diff --git a/tools/build_defs/repo/cache.bzl b/tools/build_defs/repo/cache.bzl index 8381446da242ff..578ed72c6fabfb 100644 --- a/tools/build_defs/repo/cache.bzl +++ b/tools/build_defs/repo/cache.bzl @@ -20,7 +20,7 @@ """Returns the default canonical id to use for downloads.""" -visibility("private") +visibility("public") DEFAULT_CANONICAL_ID_ENV = "BAZEL_HTTP_RULES_URLS_AS_DEFAULT_CANONICAL_ID" @@ -37,7 +37,28 @@ machines without the file in the cache. This behavior can be disabled with """.format(env = DEFAULT_CANONICAL_ID_ENV) def get_default_canonical_id(repository_ctx, urls): - """Returns the default canonical id to use for downloads.""" + """Returns the default canonical id to use for downloads. + + Returns `""` (empty string) when Bazel is run with + `--repo_env=BAZEL_HTTP_RULES_URLS_AS_DEFAULT_CANONICAL_ID=0`. + + e.g. + ```python + load("@bazel_tools//tools/build_defs/repo:cache.bzl", "get_default_canonical_id") + # ... + repository_ctx.download_and_extract( + url = urls, + integrity = integrity + canonical_id = get_default_canonical_id(repository_ctx, urls), + ), + ``` + + Args: + repository_ctx: The repository context of the repository rule calling this utility + function. + urls: A list of URLs matching what is passed to `repository_ctx.download` and + `repository_ctx.download_and_extract`. + """ if repository_ctx.os.environ.get(DEFAULT_CANONICAL_ID_ENV) == "0": return ""