| #!/bin/bash |
| |
| set -e |
| |
| function print_usage() { |
| echo "usage check_diff REMOTE_REPO FEATURE_BRANCH [COMMIT_HASH] [OPTIONAL_RUSTFMT_CONFIGS]" |
| } |
| |
| if [ $# -le 1 ]; then |
| print_usage |
| exit 1 |
| fi |
| |
| REMOTE_REPO=$1 |
| FEATURE_BRANCH=$2 |
| OPTIONAL_COMMIT_HASH=$3 |
| OPTIONAL_RUSTFMT_CONFIGS=$4 |
| |
| # OUTPUT array used to collect all the status of running diffs on various repos |
| STATUSES=() |
| |
| # Clone a git repository and cd into it. |
| # |
| # Parameters: |
| # $1: git clone url |
| # $2: directory where the repo should be cloned |
| function clone_repo() { |
| GIT_TERMINAL_PROMPT=0 git clone --quiet $1 --depth 1 $2 && cd $2 |
| } |
| |
| # Initialize Git submodules for the repo. |
| # |
| # Parameters |
| # $1: list of directories to initialize |
| function init_submodules() { |
| git submodule update --init $1 |
| } |
| |
| # Run rusfmt with the --check flag to see if a diff is produced. |
| # |
| # Parameters: |
| # $1: Path to a rustfmt binary |
| # $2: Output file path for the diff |
| # $3: Any additional configuration options to pass to rustfmt |
| # |
| # Globals: |
| # $OPTIONAL_RUSTFMT_CONFIGS: Optional configs passed to the script from $4 |
| function create_diff() { |
| local config; |
| if [ -z "$3" ]; then |
| config="--config=error_on_line_overflow=false,error_on_unformatted=false" |
| else |
| config="--config=error_on_line_overflow=false,error_on_unformatted=false,$OPTIONAL_RUSTFMT_CONFIGS" |
| fi |
| |
| for i in `find . | grep "\.rs$"` |
| do |
| $1 --unstable-features --skip-children --check --color=always $config $i >> $2 2>/dev/null |
| done |
| } |
| |
| # Run the master rustfmt binary and the feature branch binary in the current directory and compare the diffs |
| # |
| # Parameters |
| # $1: Name of the repository (used for logging) |
| # |
| # Globals: |
| # $RUSFMT_BIN: Path to the rustfmt master binary. Created when running `compile_rustfmt` |
| # $FEATURE_BIN: Path to the rustfmt feature binary. Created when running `compile_rustfmt` |
| # $OPTIONAL_RUSTFMT_CONFIGS: Optional configs passed to the script from $4 |
| function check_diff() { |
| echo "running rustfmt (master) on $1" |
| create_diff $RUSFMT_BIN rustfmt_diff.txt |
| |
| echo "running rustfmt (feature) on $1" |
| create_diff $FEATURE_BIN feature_diff.txt $OPTIONAL_RUSTFMT_CONFIGS |
| |
| echo "checking diff" |
| local diff; |
| # we don't add color to the diff since we added color when running rustfmt --check. |
| # tail -n + 6 removes the git diff header info |
| # cut -c 2- removes the leading diff characters("+","-"," ") from running git diff. |
| # Again, the diff output we care about was already added when we ran rustfmt --check |
| diff=$( |
| git --no-pager diff --color=never \ |
| --unified=0 --no-index rustfmt_diff.txt feature_diff.txt 2>&1 | tail -n +6 | cut -c 2- |
| ) |
| |
| if [ -z "$diff" ]; then |
| echo "no diff detected between rustfmt and the feature branch" |
| return 0 |
| else |
| echo "$diff" |
| return 1 |
| fi |
| } |
| |
| # Compiles and produces two rustfmt binaries. |
| # One for the current master, and another for the feature branch |
| # |
| # Parameters: |
| # $1: Directory where rustfmt will be cloned |
| # |
| # Globals: |
| # $REMOTE_REPO: Clone URL to the rustfmt fork that we want to test |
| # $FEATURE_BRANCH: Name of the feature branch |
| # $OPTIONAL_COMMIT_HASH: Optional commit hash that will be checked out if provided |
| function compile_rustfmt() { |
| RUSTFMT_REPO="https://github.com/rust-lang/rustfmt.git" |
| clone_repo $RUSTFMT_REPO $1 |
| git remote add feature $REMOTE_REPO |
| git fetch feature $FEATURE_BRANCH |
| |
| CARGO_VERSION=$(cargo --version) |
| echo -e "\ncompiling with $CARGO_VERSION\n" |
| |
| # Because we're building standalone binaries we need to set `LD_LIBRARY_PATH` so each |
| # binary can find it's runtime dependencies. See https://github.com/rust-lang/rustfmt/issues/5675 |
| # This will prepend the `LD_LIBRARY_PATH` for the master rustfmt binary |
| export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH |
| |
| echo "Building rustfmt from src" |
| cargo build -q --release --bin rustfmt && cp target/release/rustfmt $1/rustfmt |
| |
| if [ -z "$OPTIONAL_COMMIT_HASH" ] || [ "$FEATURE_BRANCH" = "$OPTIONAL_COMMIT_HASH" ]; then |
| git switch $FEATURE_BRANCH |
| else |
| git switch $OPTIONAL_COMMIT_HASH --detach |
| fi |
| |
| # This will prepend the `LD_LIBRARY_PATH` for the feature branch rustfmt binary. |
| # In most cases the `LD_LIBRARY_PATH` should be the same for both rustfmt binaries that we build |
| # in `compile_rustfmt`, however, there are scenarios where each binary has different runtime |
| # dependencies. For example, during subtree syncs we bump the nightly toolchain required to build |
| # rustfmt, and therefore the feature branch relies on a newer set of runtime dependencies. |
| export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH |
| |
| echo "Building feature rustfmt from src" |
| cargo build -q --release --bin rustfmt && cp target/release/rustfmt $1/feature_rustfmt |
| |
| echo -e "\nRuntime dependencies for rustfmt -- LD_LIBRARY_PATH: $LD_LIBRARY_PATH" |
| |
| RUSFMT_BIN=$1/rustfmt |
| RUSTFMT_VERSION=$($RUSFMT_BIN --version) |
| echo -e "\nRUSFMT_BIN $RUSTFMT_VERSION\n" |
| |
| FEATURE_BIN=$1/feature_rustfmt |
| FEATURE_VERSION=$($FEATURE_BIN --version) |
| echo -e "FEATURE_BIN $FEATURE_VERSION\n" |
| } |
| |
| # Check the diff for running rustfmt and the feature branch on all the .rs files in the repo. |
| # |
| # Parameters |
| # $1: Clone URL for the repo |
| # $2: Name of the repo (mostly used for logging) |
| # $3: Path to any submodules that should be initialized |
| function check_repo() { |
| WORKDIR=$(pwd) |
| REPO_URL=$1 |
| REPO_NAME=$2 |
| SUBMODULES=$3 |
| |
| local tmp_dir; |
| tmp_dir=$(mktemp -d -t $REPO_NAME-XXXXXXXX) |
| clone_repo $REPO_URL $tmp_dir |
| |
| if [ ! -z "$SUBMODULES" ]; then |
| init_submodules $SUBMODULES |
| fi |
| |
| |
| # rustfmt --check returns 1 if a diff was found |
| # Also check_diff returns 1 if there was a diff between master rustfmt and the feature branch |
| # so we want to ignore the exit status check |
| set +e |
| check_diff $REPO_NAME |
| # append the status of running `check_diff` to the STATUSES array |
| STATUSES+=($?) |
| set -e |
| |
| echo -e "removing tmp_dir $tmp_dir\n\n" |
| rm -rf $tmp_dir |
| cd $WORKDIR |
| } |
| |
| function main() { |
| tmp_dir=$(mktemp -d -t rustfmt-XXXXXXXX) |
| echo Created tmp_dir $tmp_dir |
| |
| compile_rustfmt $tmp_dir |
| |
| # run checks |
| check_repo "https://github.com/rust-lang/rust.git" rust-lang-rust |
| check_repo "https://github.com/rust-lang/cargo.git" cargo |
| check_repo "https://github.com/rust-lang/miri.git" miri |
| check_repo "https://github.com/rust-lang/rust-analyzer.git" rust-analyzer |
| check_repo "https://github.com/bitflags/bitflags.git" bitflags |
| check_repo "https://github.com/rust-lang/log.git" log |
| check_repo "https://github.com/rust-lang/mdBook.git" mdBook |
| check_repo "https://github.com/rust-lang/packed_simd.git" packed_simd |
| check_repo "https://github.com/rust-lang/rust-semverver.git" check_repo |
| check_repo "https://github.com/Stebalien/tempfile.git" tempfile |
| check_repo "https://github.com/rust-lang/futures-rs.git" futures-rs |
| check_repo "https://github.com/dtolnay/anyhow.git" anyhow |
| check_repo "https://github.com/dtolnay/thiserror.git" thiserror |
| check_repo "https://github.com/dtolnay/syn.git" syn |
| check_repo "https://github.com/serde-rs/serde.git" serde |
| check_repo "https://github.com/rust-lang/rustlings.git" rustlings |
| check_repo "https://github.com/rust-lang/rustup.git" rustup |
| check_repo "https://github.com/SergioBenitez/Rocket.git" Rocket |
| check_repo "https://github.com/rustls/rustls.git" rustls |
| check_repo "https://github.com/rust-lang/rust-bindgen.git" rust-bindgen |
| check_repo "https://github.com/hyperium/hyper.git" hyper |
| check_repo "https://github.com/actix/actix.git" actix |
| check_repo "https://github.com/denoland/deno.git" denoland_deno |
| |
| # cleanup temp dir |
| echo removing tmp_dir $tmp_dir |
| rm -rf $tmp_dir |
| |
| # figure out the exit code |
| for status in ${STATUSES[@]} |
| do |
| if [ $status -eq 1 ]; then |
| echo "formatting diff found 💔" |
| return 1 |
| fi |
| done |
| |
| echo "no diff found 😊" |
| } |
| |
| main |