Add instructions for doing mass renames easily (#6865)
This commit is contained in:
parent
d9add4a01f
commit
0ffa47cc1e
|
@ -36,5 +36,6 @@
|
|||
- [Network Architecture](dev/diagrams/zebra-network.md)
|
||||
- [Continuous Integration](dev/continuous-integration.md)
|
||||
- [Continuous Delivery](dev/continuous-delivery.md)
|
||||
- [zebra-checkpoints](dev/zebra-checkpoints.md)
|
||||
- [Generating Zebra Checkpoints](dev/zebra-checkpoints.md)
|
||||
- [Doing Mass Renames](dev/mass-renames.md)
|
||||
- [API Reference](api.md)
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
# Doing Mass Renames in Zebra Code
|
||||
|
||||
Sometimes we want to rename a Rust type or function, or change a log message.
|
||||
|
||||
But our types and functions are also used in our documentation,
|
||||
so the compiler can sometimes miss when their names are changed.
|
||||
|
||||
Our log messages are also used in our integration tests,
|
||||
so changing them can lead to unexpected test failures or hangs.
|
||||
|
||||
## Universal Renames with `sed`
|
||||
|
||||
You can use `sed` to rename all the instances of a name in Zebra's code, documentation, and tests:
|
||||
```sh
|
||||
git ls-tree --full-tree -r --name-only HEAD | \
|
||||
xargs sed -i 's/OldName/NewName/g'
|
||||
```
|
||||
|
||||
Or excluding specific paths:
|
||||
```sh
|
||||
git ls-tree --full-tree -r --name-only HEAD | \
|
||||
grep -v 'path-to-skip' | \
|
||||
xargs sed -i 's/OldName/NewName/g'
|
||||
```
|
||||
|
||||
`sed` also supports regular expressions to replace a pattern with another pattern.
|
||||
|
||||
Here's how to make a PR with these replacements:
|
||||
1. Run the `sed` commands
|
||||
2. Run `cargo fmt --all` after doing all the replacements
|
||||
3. Put the commands in the commit message and pull request, so the reviewer can check them
|
||||
|
||||
Here's how to review that PR:
|
||||
1. Check out two copies of the repository, one with the PR, and one without:
|
||||
```sh
|
||||
cd zebra
|
||||
git fetch --all
|
||||
# clear the checkout so we can use main elsewhere
|
||||
git checkout main^
|
||||
# Use the base branch or commit for the PR, which is usually main
|
||||
git worktree add ../zebra-sed main
|
||||
git worktree add ../zebra-pr origin/pr-branch-name
|
||||
```
|
||||
|
||||
2. Run the scripts on the repository without the PR:
|
||||
```sh
|
||||
cd ../zebra-sed
|
||||
# run the scripts in the PR or commit message
|
||||
git ls-tree --full-tree -r --name-only HEAD | \
|
||||
xargs sed -i 's/OldName/NewName/g'
|
||||
cargo fmt --all
|
||||
```
|
||||
|
||||
3. Automatically check that they match
|
||||
```sh
|
||||
cd ..
|
||||
git diff zebra-sed zebra-pr
|
||||
```
|
||||
|
||||
If there are no differences, then the PR can be approved.
|
||||
|
||||
If there are differences, then post them as a review in the PR,
|
||||
and ask the author to re-run the script on the latest `main`.
|
||||
|
||||
## Interactive Renames with `fastmod`
|
||||
|
||||
You can use `fastmod` to rename some instances, but skip others:
|
||||
```sh
|
||||
fastmod --fixed-strings "OldName" "NewName" [paths to change]
|
||||
```
|
||||
|
||||
`fastmod` also supports regular expressions to replace a pattern with another pattern.
|
||||
|
||||
Here's how to make a PR with these replacements:
|
||||
1. Run the `fastmod` commands, choosing which instances to replace
|
||||
2. Run `cargo fmt --all` after doing all the replacements
|
||||
3. Put the commands in the commit message and pull request, so the reviewer can check them
|
||||
4. If there are a lot of renames:
|
||||
- use `sed` on any directories or files that are always renamed, and put them in the first PR,
|
||||
- do a cleanup using `fastmod` in the next PR.
|
||||
|
||||
Here's how to review that PR:
|
||||
1. Manually review each replacement (there's no shortcut)
|
||||
|
||||
## Using `rustdoc` links to detect name changes
|
||||
|
||||
When you're referencing a type or function in a doc comment,
|
||||
use a `rustdoc` link to refer to it.
|
||||
|
||||
This makes the documentation easier to navigate,
|
||||
and our `rustdoc` lint will detect any typos or name changes.
|
||||
|
||||
```rust
|
||||
//! This is what `rustdoc` links look like:
|
||||
//! - [`u32`] type or trait
|
||||
//! - [`drop()`] function
|
||||
//! - [`Clone::clone()`] method
|
||||
//! - [`Option::None`] enum variant
|
||||
//! - [`Option::Some(_)`](Option::Some) enum variant with data
|
||||
//! - [`HashMap`](std::collections::HashMap) fully-qualified path
|
||||
//! - [`BTreeSet<String>`](std::collections::BTreeSet) fully-qualified path with generics
|
||||
```
|
||||
|
||||
If a type isn't imported in the module or Rust prelude,
|
||||
then it needs a fully-qualified path in the docs, or an unused import:
|
||||
```rust
|
||||
// For rustdoc
|
||||
#[allow(unused_imports)]
|
||||
use std::collections::LinkedList;
|
||||
|
||||
//! Link to [`LinkedList`].
|
||||
struct Type;
|
||||
```
|
Loading…
Reference in New Issue