4
4
# - It only minimally depends on GitHub: All operations are done using Git directly
5
5
# - Reuse of previous work: Formatting all of Nixpkgs takes some time, we don't want to recompute it if not necessary
6
6
# - Handles force pushes gracefully and linearises merge commits
7
- #
7
+ # - Runs all external code in Nix derivations, so this is safe to use for PRs from forks too
8
8
9
9
set -euo pipefail
10
10
@@ -24,6 +24,8 @@ nixpkgsUrl=$3
24
24
nixpkgsUpstreamUrl=https://github.com/NixOS/nixpkgs
25
25
nixpkgsMirrorBranch=nixfmt-$nixfmtPrNumber
26
26
27
+ SCRIPT_DIR=$( cd -- " $( dirname -- " ${BASH_SOURCE[0]} " ) " & > /dev/null && pwd )
28
+
27
29
tmp=$( mktemp -d)
28
30
cd " $tmp "
29
31
trap ' rm -rf "$tmp"' exit
@@ -47,7 +49,7 @@ isLinear() {
47
49
}
48
50
49
51
step " Fetching nixfmt pull request and creating a branch for the head commit"
50
- git init nixfmt
52
+ git init nixfmt -b unused
51
53
git -C nixfmt fetch " $nixfmtUrl " " refs/pull/$nixfmtPrNumber /merge"
52
54
nixfmtBaseCommit=$( git -C nixfmt rev-parse FETCH_HEAD^1)
53
55
nixfmtHeadCommit=$( git -C nixfmt rev-parse FETCH_HEAD^2)
@@ -95,7 +97,7 @@ bodyForCommitIndex() {
95
97
}
96
98
97
99
step " Fetching upstream Nixpkgs commit history"
98
- git init --bare nixpkgs.git
100
+ git init --bare nixpkgs.git -b unused
99
101
100
102
git -C nixpkgs.git remote add upstream " $nixpkgsUpstreamUrl "
101
103
# This makes sure that we don't actually have to fetch any contents, otherwise we'd wait forever!
@@ -179,9 +181,12 @@ else
179
181
echo " Checking whether commit with index $(( nixpkgsCommitCount + 1 )) ($nixpkgsCommit ) in nixpkgs corresponds to commit with index $nixpkgsCommitCount ($nixfmtCommit ) in nixfmt"
180
182
181
183
# We generate the bodies of the commits to contain the nixfmt commit so we can check against it here to verify it's the same
182
- body=$( git -C nixpkgs.git log -1 " $nixpkgsCommit " --pretty=%B)
183
- expectedBody=$( bodyForCommitIndex " $nixpkgsCommitCount " )
184
- if [[ " $body " == " $expectedBody " ]]; then
184
+ # Note that `--format=format:` makes it so that there's no extra newline
185
+ git -C nixpkgs.git log -1 " $nixpkgsCommit " --format=format:%B > " $tmp /body"
186
+ bodyForCommitIndex " $nixpkgsCommitCount " > " $tmp /expected-body"
187
+
188
+ # Ignore case so that we don't need to be worried about things like NixOS vs nixos in the URL
189
+ if diff --ignore-case " $tmp /body" " $tmp /expected-body" ; then
185
190
echo " It does!"
186
191
else
187
192
echo " It does not, this indicates a force push was done"
@@ -199,13 +204,23 @@ else
199
204
fi
200
205
201
206
202
- git init nixpkgs
207
+ git init nixpkgs -b unused
203
208
git -C nixpkgs config user.name " GitHub Actions"
204
209
git -C nixpkgs config user.email
" [email protected] "
205
210
206
211
step " Fetching contents of Nixpkgs base commit $nixpkgsBaseCommit "
207
212
# This is needed because for every commit we reset Nixpkgs to the base branch before formatting
208
- git -C nixpkgs fetch --no-tags --depth 1 " $nixpkgsUpstreamUrl " " $nixpkgsBaseCommit "
213
+ git -C nixpkgs fetch --no-tags --depth 1 " $nixpkgsUpstreamUrl " " $nixpkgsBaseCommit " :base
214
+
215
+ step " Checking out Nixpkgs at the base commit"
216
+ git -C nixpkgs checkout base
217
+
218
+ # Because we run the formatter in a Nix derivation, we need to get its input files into the Nix store.
219
+ # Since they never change, it would be wasteful to import them multiple times for each nixfmt run.
220
+ # So instead we just import them once and reuse that result throughout
221
+ step " Importing Nix files from base commit into the Nix store"
222
+ baseStorePath=$( nix-instantiate --eval --read-write-mode " $SCRIPT_DIR /sync-pr-support.nix" -A repoNixFiles.outPath --arg repo " $PWD /nixpkgs" | tr -d ' "' )
223
+ echo " $baseStorePath "
209
224
210
225
step " Fetching contents of the starting commit and updating the mirror branch"
211
226
# This is only needed so we can push the resulting diff after formatting
@@ -234,9 +249,6 @@ update() {
234
249
235
250
step " Checking out nixfmt at $nixfmtCommit "
236
251
git -C nixfmt checkout -q " $nixfmtCommit "
237
-
238
- step " Building nixfmt"
239
- nix-build nixfmt
240
252
}
241
253
242
254
# Format Nixpkgs with a specific nixfmt version and push the result.
@@ -247,21 +259,21 @@ next() {
247
259
248
260
update " $index "
249
261
250
- if [[ -n " $appliedNixfmtPath " && " $appliedNixfmtPath " == " $( realpath result) " ]]; then
251
- echo " The nixfmt store path didn't change, saving ourselves a formatting"
252
- else
253
- step " Checking out Nixpkgs at the base commit"
254
- git -C nixpkgs checkout " $nixpkgsBaseCommit " -- .
262
+ step " Checking out Nixpkgs at the base commit"
263
+ git -C nixpkgs checkout base -- .
255
264
256
- step " Running nixfmt on nixpkgs"
257
- if ! time xargs -r -0 -P" $( nproc) " -n1 -a <( find nixpkgs -type f -name ' *.nix' -print0) result/bin/nixfmt; then
258
- echo -e " \e[31mFailed to run nixfmt on some files\e[0m"
259
- exit 1
260
- fi
261
- git -C nixpkgs add -A
265
+ step " Running nixfmt on nixpkgs in a derivation"
262
266
263
- appliedNixfmtPath=$( realpath result)
267
+ # This uses always the same sync-pr-support.nix file from the same nixfmt branch that this script is in,
268
+ # but doesn't use anything else from that nixfmt branch. Instead the nixfmtPath is used for the formatting.
269
+ if ! nix-build " $SCRIPT_DIR /sync-pr-support.nix" -A formattedGitRepo --arg storePath " $baseStorePath " --arg nixfmtPath " $PWD /nixfmt" ; then
270
+ echo -e " \e[31mFailed to run nixfmt on some files\e[0m"
271
+ exit 1
264
272
fi
273
+ step " Syncing changes into the Nixpkgs tree"
274
+ # We need to move the changed files in result/ back into the tree (without messing up the permissions and other files)
275
+ rsync --archive --no-perms result/ nixpkgs
276
+ git -C nixpkgs add -A
265
277
266
278
step " Committing the formatted result"
267
279
git -C nixpkgs commit --allow-empty -m " $( bodyForCommitIndex " $index " ) "
@@ -271,14 +283,12 @@ next() {
271
283
nixpkgsCommitCount=$(( nixpkgsCommitCount + 1 ))
272
284
}
273
285
274
- appliedNixfmtPath=
275
286
if (( nixpkgsCommitCount == 0 )) ; then
276
287
# If we don't have a base-formatted Nixpkgs commit yet, create it
277
288
next 0
278
289
else
279
290
# Otherwise, just build the nixfmt that was used for the current commit, such that we know the store path
280
291
update " $(( nixpkgsCommitCount - 1 )) "
281
- appliedNixfmtPath=$( realpath result)
282
292
fi
283
293
284
294
while (( nixpkgsCommitCount - 1 < nixfmtCommitCount )) ; do
0 commit comments