-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add instructions for doing mass renames easily (#6865)
- Loading branch information
Showing
2 changed files
with
115 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
``` |