Patches for third-party Rust crates from crates.io

This directory contains patches for third-party Rust crates. The patches are applied when running the tools/crates/run_gnrt.py vendor tool which first downloads original crates into //third_party/rust/chromium_crates_io/vendor and then applies the patches from this directory.

For broader context, please see tools/crates/gnrt/README.md and docs/rust.md.

Prefer upstream PRs instead of patches

If possible, please avoid patches and instead submit PRs (pull requests) to the upstream repo of the crate. This helps to avoid the small, but non-zero burden required to maintain the patches (they need to be refreshed when they eventually don't apply cleanly anymore). Additionally, PRs also benefit the broader community of crates.io users.

That said, patches may sometimes be required:

  • If upstream maintainers have accepted and merged a PR, but didn't yet release a new version to crates.io, then a short-lived, temporary patch may expedite adopting the PR in Chromium.
  • If patches are very Chromium-specific (and therefore are unlikely to be accepted by upstream maintainers), then a long-lived patch may be the right way forward.

Note that in theory any crate file may be patched, but in practice patching Cargo.toml is quite tricky, because tools/crates/run_gnrt.py vendor builds Chromium's dependency graph based on original, unpatched crate versions, while tools/crates/run_gnrt.py gen uses the graph derived from the patched versions. This discrepancy can confuse other tools (e.g. create_update_cl.py may think that it adds a new crate, when in reality the new crate has no BUILD.gn and is effectively unused after patching).

Steps for creating new patches

You may patch a crate in tree, but save any changes made into a diff file in a //third_party/rust/chromium_crates_io/patches/ directory for the crate. The diff file should be generated by git-format-patch, with each new patch numbered consecutively so that they can be applied in order. For example, these files might exist if the “foo” crate was patched with a couple of changes:

//third_party/rust/chromium_crates_io/patches/foo/patches/0001-Some-changes.diff
//third_party/rust/chromium_crates_io/patches/foo/patches/0002-Other-changes.diff

Patches are applied with -p6 --directory third_party/rust/chromium_crates_io/vendor/<crate>-<epoch>, effectively ignoring the version numbers in the patch files.

The recommended procedure to create such patches is:

  1. Commit the plain new version of the crate to your local git branch

  2. Modify the crate as necessary

  3. Commit that modified version

  4. Use git format-patch to generate the patch files. For example:

    git format-patch \
        --start-number=101 \
        --output-directory \
            $CHROMIUM_SRC/third_party/rust/chromium_crates_io/patches/some-crate/ \
        HEAD^
    
  5. Add the patch files in a new, third, commit

  6. Squash them, or rely on git cl upload doing so

Recovering from patching errors

If gnrt vendor fails to apply a patch for a crate, it will cancel the download of that crate rather than leave it in a broken state. To recreate patches, first get a pristine copy of the crate by using the --no-patches argument:

  1. Download the crate without applying patches:
    • vpython3 ./tools/crates/run_gnrt.py vendor --no-patches=<CRATE_NAME>
  2. Then recreate the patches as described in Steps for creating new patches.

To verify the patches work, remove the vendored crate directory in //third_party/rust/chromium_crates_io/vendor/, named after the crate name and version. Then run the vendor action without --no-patches which will download the crate and apply the patches:

  • vpython3 ./tools/crates/run_gnrt.py vendor