bazelbuild / rules_rust

Rust rules for Bazel
https://bazelbuild.github.io/rules_rust/
Apache License 2.0
651 stars 412 forks source link

crate_universe: Start auto-populating missing lockfiles and cargo_lockfiles in Bazel 6 #1676

Open illicitonion opened 1 year ago

illicitonion commented 1 year ago

https://github.com/bazelbuild/bazel/pull/13417 added the ability to find the workspace root from a repository_ctx, and will be in Bazel 6.

Currently, if the lockfile or cargo_lockfile points at a file which doesn't exist, we give a really unclear error:

ERROR: An error occurred during the fetch of repository 'crate_index':
   Traceback (most recent call last):
    File "/private/var/tmp/_bazel_john/6ebb6fa28311e23a56b6491e5d493861/external/rules_rust/crate_universe/private/crates_repository.bzl", line 34, column 30, in _crates_repository_impl
        lockfiles = get_lockfiles(repository_ctx)
    File "/private/var/tmp/_bazel_john/6ebb6fa28311e23a56b6491e5d493861/external/rules_rust/crate_universe/private/generate_utils.bzl", line 299, column 36, in get_lockfiles
        cargo = repository_ctx.path(repository_ctx.attr.cargo_lockfile),
Error in path: Not a regular file: /Users/john/figma/rules_rust_built/Cargo.Bazel.lock

Instead, now that we have this API, we should be able to:

  1. Switch cargo_lockfile from being an attr.label to being an attr.string
  2. Parse it ourselves, and if it looks like it's in the workspace repo (i.e. starts @//, //, or :), resolve it relative to repository_ctx.workspace_root, and use that as the path; otherwise we should fall back to the existing code for remote repositories (though I'm not sure there's a reasonable use-case for using a remote repository for a lockfile).
  3. In the resolver rust code, make sure we handle the "does not exist" case by suggesting a repin (and modifying the error message to say the file doesn't exist, and will be created by a repin).
  4. In the resolver rust code, make sure the repin will create the file if missing.
illicitonion commented 1 year ago

Also, we should only do the above if we sniff the version to be Bazel 6 - in pre-Bazel 6 we'll need to keep the old behaviour (which we can do by just making the "parse out the label and resolve ourselves" stage of step 2 conditional).