about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/check_diff.yml33
-rwxr-xr-xci/check_diff.sh199
2 files changed, 232 insertions, 0 deletions
diff --git a/.github/workflows/check_diff.yml b/.github/workflows/check_diff.yml
new file mode 100644
index 00000000000..8bfb5834519
--- /dev/null
+++ b/.github/workflows/check_diff.yml
@@ -0,0 +1,33 @@
+name: Diff Check
+on:
+  workflow_dispatch:
+    inputs:
+      clone_url:
+        description: 'Git url of a rustfmt fork to compare against the latest master rustfmt'
+        required: true
+      branch_name:
+        description: 'Name of the feature branch on the forked repo'
+        required: true
+      commit_hash:
+        description: 'Optional commit hash from the feature branch'
+        required: false
+      rustfmt_configs:
+        description: 'Optional comma separated list of rustfmt config options to pass when running the feature branch'
+        required: false
+
+jobs:
+  diff_check:
+    runs-on: ubuntu-latest
+
+    steps:
+    - name: checkout
+      uses: actions/checkout@v3
+
+    - name: install rustup
+      run: |
+        curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh
+        sh rustup-init.sh -y --default-toolchain none
+        rustup target add x86_64-unknown-linux-gnu
+
+    - name: check diff
+      run: bash ${GITHUB_WORKSPACE}/ci/check_diff.sh ${{ github.event.inputs.clone_url }} ${{ github.event.inputs.branch_name }} ${{ github.event.inputs.commit_hash }} ${{ github.event.inputs.rustfmt_configs }}
diff --git a/ci/check_diff.sh b/ci/check_diff.sh
new file mode 100755
index 00000000000..062c2dd8673
--- /dev/null
+++ b/ci/check_diff.sh
@@ -0,0 +1,199 @@
+#!/bin/bash
+
+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 build --release --bin rustfmt && cp target/release/rustfmt $1/rustfmt
+    if [ -z "$OPTIONAL_COMMIT_HASH" ]; then
+        git switch $FEATURE_BRANCH
+    else
+        git switch $OPTIONAL_COMMIT_HASH --detach
+    fi
+    cargo build --release --bin rustfmt && cp target/release/rustfmt $1/feature_rustfmt
+    RUSFMT_BIN=$1/rustfmt
+    FEATURE_BIN=$1/feature_rustfmt
+}
+
+# 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
+
+    check_diff $REPO_NAME
+    # append the status of running `check_diff` to the STATUSES array
+    STATUSES+=($?)
+
+    echo "removing tmp_dir $tmp_dir"
+    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