Skip to content

Commit 969f85c

Browse files
committed
modify setup to choose pre-push hook with spellcheck
It changes setup for pre-push hook to use 3 options (tidy, with spellcheck, and skip). Since spellceck binary is installed everytime under ./build if the user clean up the build folder, it should be optional.
1 parent 8188f6c commit 969f85c

File tree

2 files changed

+113
-17
lines changed

2 files changed

+113
-17
lines changed

src/bootstrap/src/core/build_steps/setup.rs

Lines changed: 77 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,52 @@ impl Step for Hook {
484484
}
485485
}
486486

487+
/// It handles Git hook setup
488+
#[derive(Clone, Debug, Eq, PartialEq)]
489+
enum GitHookKind {
490+
Tidy,
491+
TidyWithSpellcheck,
492+
}
493+
494+
impl GitHookKind {
495+
fn prompt_user() -> io::Result<Option<GitHookKind>> {
496+
let prompt_str = "Available options:
497+
1. Set tidy as pre-push hook
498+
2. Set tidy with spellcheck as pre-push hook
499+
500+
Please select [default: None]:";
501+
502+
let mut input = String::new();
503+
loop {
504+
print!("{prompt_str}");
505+
io::stdout().flush()?;
506+
io::stdin().read_line(&mut input)?;
507+
508+
let mut modified_input = input.to_lowercase();
509+
modified_input.retain(|ch| !ch.is_whitespace());
510+
511+
match modified_input.as_str() {
512+
"1" => return Ok(Some(GitHookKind::Tidy)),
513+
"2" => return Ok(Some(GitHookKind::TidyWithSpellcheck)),
514+
"" | "none" => return Ok(None),
515+
_ => {
516+
eprintln!("ERROR: unrecognized option '{}'", input.trim());
517+
eprintln!("NOTE: press Ctrl+C to exit");
518+
}
519+
}
520+
521+
input.clear();
522+
}
523+
}
524+
525+
fn settings_path(&self) -> PathBuf {
526+
PathBuf::new().join("src").join("etc").join(match self {
527+
GitHookKind::Tidy => "pre-push.sh",
528+
GitHookKind::TidyWithSpellcheck => "pre-push-spellcheck.sh",
529+
})
530+
}
531+
}
532+
487533
// install a git hook to automatically run tidy, if they want
488534
fn install_git_hook_maybe(builder: &Builder<'_>, config: &Config) -> io::Result<()> {
489535
let git = helpers::git(Some(&config.src))
@@ -493,37 +539,51 @@ fn install_git_hook_maybe(builder: &Builder<'_>, config: &Config) -> io::Result<
493539
let git = PathBuf::from(git.trim());
494540
let hooks_dir = git.join("hooks");
495541
let dst = hooks_dir.join("pre-push");
496-
if dst.exists() {
497-
// The git hook has already been set up, or the user already has a custom hook.
498-
return Ok(());
499-
}
500542

501543
println!(
502544
"\nRust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
503545
If you'd like, x.py can install a git hook for you that will automatically run `test tidy` before
504546
pushing your code to ensure your code is up to par. If you decide later that this behavior is
505-
undesirable, simply delete the `pre-push` file from .git/hooks."
547+
undesirable, simply delete the `pre-push` file from .git/hooks.
548+
You have two choices of hooks, the first just runs `test tidy`, the second runs the tidy command with spellcheck.
549+
Since the spellcheck will be installed if the binary doesn't exist under `build/`, we'll recommend you to choose the first one if you frequently clean up the build directory.
550+
It overrides the existing pre-push hook if you already have."
506551
);
507552

508-
if prompt_user("Would you like to install the git hook?: [y/N]")? != Some(PromptResult::Yes) {
509-
println!("Ok, skipping installation!");
510-
return Ok(());
511-
}
553+
let src = match GitHookKind::prompt_user() {
554+
Ok(git_hook_kind) => {
555+
if let Some(git_hook_kind) = git_hook_kind {
556+
git_hook_kind.settings_path()
557+
} else {
558+
println!("Skip setting pre-push hook");
559+
return Ok(());
560+
}
561+
}
562+
Err(e) => {
563+
eprintln!("ERROR: could not determine pre push hook: {e}");
564+
return Err(e);
565+
}
566+
};
567+
512568
if !hooks_dir.exists() {
513569
// We need to (try to) create the hooks directory first.
514570
let _ = fs::create_dir(hooks_dir);
515571
}
516-
let src = config.src.join("src").join("etc").join("pre-push.sh");
517-
match fs::hard_link(src, &dst) {
572+
573+
if let Ok(true) = fs::exists(&dst) {
574+
// Remove the existing pre-push file.
575+
if let Err(e) = fs::remove_file(&dst) {
576+
eprintln!("ERROR: could not remove the existing hook\n{}", e);
577+
return Err(e);
578+
}
579+
}
580+
581+
match fs::hard_link(config.src.join(&src), &dst) {
518582
Err(e) => {
519-
eprintln!(
520-
"ERROR: could not create hook {}: do you already have the git hook installed?\n{}",
521-
dst.display(),
522-
e
523-
);
583+
eprintln!("ERROR: could not create hook {}:\n{}", dst.display(), e);
524584
return Err(e);
525585
}
526-
Ok(_) => println!("Linked `src/etc/pre-push.sh` to `.git/hooks/pre-push`"),
586+
Ok(_) => println!("Linked `{}` to `{}`", src.display(), dst.display()),
527587
};
528588
Ok(())
529589
}

src/etc/pre-push-spellcheck.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Call `tidy` before git push
4+
# Copy this script to .git/hooks to activate,
5+
# and remove it from .git/hooks to deactivate.
6+
#
7+
8+
set -Euo pipefail
9+
10+
# Check if the push is doing anything other than deleting remote branches
11+
SKIP=true
12+
while read LOCAL_REF LOCAL_SHA REMOTE_REF REMOTE_SHA; do
13+
if [[ "$LOCAL_REF" != "(delete)" || \
14+
"$LOCAL_SHA" != "0000000000000000000000000000000000000000" ]]; then
15+
SKIP=false
16+
fi
17+
done
18+
19+
if $SKIP; then
20+
echo "Skipping tidy check for branch deletion"
21+
exit 0
22+
fi
23+
24+
ROOT_DIR="$(git rev-parse --show-toplevel)"
25+
26+
echo "Running pre-push script $ROOT_DIR/x test tidy"
27+
28+
cd "$ROOT_DIR"
29+
# The env var is necessary for printing diffs in py (fmt/lint) and cpp.
30+
TIDY_PRINT_DIFF=1 ./x test tidy \
31+
--set build.locked-deps=true \
32+
--extra-checks auto:py,auto:cpp,auto:js,spellcheck
33+
if [ $? -ne 0 ]; then
34+
echo "You may use \`git push --no-verify\` to skip this check."
35+
exit 1
36+
fi

0 commit comments

Comments
 (0)