summaryrefslogtreecommitdiffstats
path: root/src/tools/rustfmt/ci/check_diff.sh
blob: 062c2dd8673abcfb3a9f37721ae56fbfb617f482 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
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