| # 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]( |
| #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` |
| |