37489e43b6
rustfmt currently has a runtime dependency on the sysroot. So when we build a standalone rustfmt binary we need to set `LD_LIBRARY_PATH` so each rustfmt binary knows where to find it's dependencies. When running our Diff-Check job to test PRs for breaking changes it's often the case that both the master rustfmt binary and the feature branch binary have the same runtime dependencies so we only need to set `LD_LIBRARY_PATH` once. However, when running the diff-check job against a subtree sync PR that assumption doesn't hold. The subtree sync PR bumps the required toolchain used to build rustfmt and therefore the binary that gets built for the subtree sync PR has a different runtime dependency than the master rustfmt binary. Now we set `LD_LIBRARY_PATH` twice to account for this potential difference.
235 lines
7.9 KiB
Bash
Executable File
235 lines
7.9 KiB
Bash
Executable File
#!/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 submoduels 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
|
|
#
|
|
# Globlas:
|
|
# $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)
|
|
#
|
|
# Globlas:
|
|
# $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 feture 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
|
|
#
|
|
# Globlas:
|
|
# $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_VERSON=$(cargo --version)
|
|
echo -e "\ncompiling with $CARGO_VERSON\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
|