allow buildozer to operate on WORKSPACE files
WORKSPACE files are written in the same format as BUILD files and can be formatted by buildifier. I would like to use buildozer in a script that queries the contents of a WORKSPACE file, uses that output to check for newer upstream versions of the packages, then writes out the updates to the WORKSPACE as buildozer commands.
If I rename my WORKSPACE to BUILD, it works just fine. For example:
$ bazel run //tools:buildozer -- 'print label urls strip_prefix' //:%http_archive
INFO: Analysed target //tools:buildozer (0 packages loaded).
INFO: Found 1 target...
Target //tools:buildozer up-to-date:
bazel-bin/tools/buildozer
INFO: Elapsed time: 0.460s, Critical Path: 0.00s
INFO: Build completed successfully, 1 total action
rule "//:gmaven_rules" has no attribute "urls"
//:io_grpc_grpc_java [https://github.com/grpc/grpc-java/archive/v1.12.0.tar.gz] grpc-java-1.12.0
//:gmaven_rules (missing) "gmaven_rules-%s" % GMAVEN_TAG
//:com_google_protobuf [https://github.com/google/protobuf/archive/3.5.1.1.zip] protobuf-3.5.1.1
//:com_google_googletest [https://github.com/google/googletest/archive/08d5b1f33af8c18785fb8ca02792b5fac81e248f.zip] googletest-08d5b1f33af8c18785fb8ca02792b5fac81e248f
//:com_github_google_benchmark [https://github.com/google/benchmark/archive/6d74c0625b8e88c1afce72b4f383c91b9a99dbe6.zip] benchmark-6d74c0625b8e88c1afce72b4f383c91b9a99dbe6
//:com_google_absl [https://github.com/abseil/abseil-cpp/archive/59ae4d5a0e833bedd9d7cc059ac15a9dc130e3f7.zip] abseil-cpp-59ae4d5a0e833bedd9d7cc059ac15a9dc130e3f7
Another way to achieve this would be to allow the user to pass in the path to a single BUILD file, though I'm not sure whether buildozer needs to open other BUILD files relative to the first.
current hack: buildozer does accept input on stdin which it writes to stdout.
Problem if there is a BUILD and WORKSPACE file in //, how does buildozer distinguish? Maybe a distinguishing syntax, like @@xxx where @ is already used to mean this repo, and then after that @ rather than // or : means 'this workspace' followed by the name of the workspace entry. No such standard labeling exists in bazel so it is a stretch.
If we add a syntax for workspaces I would suggest it have a special name like __workspace__
similar to __pkg__, for instance @workspace//__workspace__:com_google_absl. Thanks for the stdin trick!
ah, that could work, then it could just be
//__workspace__:com_google_absl
@laurentlb what do you think?
@laurentlb what do you think?
@laurentlb Ping.
Looks good to me. Instead of adding it a special case for WORKSPACE (as proposed), we could also imagine a generic way to refer to any file on the disk.
For example, //foo/bar:baz could mean with either the target baz in foo/bar/BUILD or in foo/bar (if bar is a file and not a directory).
I just recently tested this, and I think this is fixed?
@jgavris Maybe I'm blind to a recent change but I don't think this is fixed -- can you provide a working example?
@sudoforge My mistake, I actually meant to say that buildifier works on WORKSPACE files. It had not previously and then this was fixed. I haven't tried to use buildozer directly, sorry.
Bummer, thanks for the heads up.
For the record, it doesn't appear that buildozer supports reading from stdin anymore (I'm unsure if it ever did, except for the earlier comments in this thread):
➜ buildozer 'print urls' //:%http_archive <<< WORKSPACE
<no output>
➜ cat WORKSPACE | buildozer 'print urls' //:%http_archive
<no output>
I'm going to take a stab at solving this using the __workspace__ idea from @nlewycky. This is a pretty necessary feature and would really simplify repository management.
I just found a neat work-around for this.
tmp="$(mktemp -d)"
touch "$tmp/WORKSPACE"
ln WORKSPACE "$tmp/BUILD"
buildozer -root_dir="$tmp" '<buildozer commands>' //:<target>
rm -rf "$tmp"
Yeah, that and similar methods have been the only way to accomplish the goal here thus far. I haven't had time to work on the __workspace__ implementation so far, but will over the next couple of weeks.
This works too, but I'm not sure why I have to use echo. I feel like I should be able to redirect the output directly to WORKSPACE, but it doesn't work.
echo "$(cat WORKSPACE | buildozer '<buildozer commands>' -:<target>)" > WORKSPACE
This works too, but I'm not sure why I have to use
echo. I feel like I should be able to redirect the output directly toWORKSPACE, but it doesn't work.echo "$(cat WORKSPACE | buildozer '<buildozer commands>' -:<target>)" > WORKSPACE
The shell truncates WORKSPACE to zero bytes for writing due to the > WORKSPACE before the cat runs to dump its contents.
Ah. Makes sense. Thanks!
While looking into fixing this issue, I learned that this had already been implemented well before this issue was created: https://github.com/bazelbuild/buildtools/commit/5fa18d247b23dd7a66e4ce5f829fda1d1bf06dc0
The syntax is:
buildozer '<buildozer commands>' WORKSPACE:<target>
More generally, WORKSPACE can be replaced with any file name. A good reminder to add docs when adding features - I will submit a PR.