Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions scripts/nixfmt-mergetool
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env bash
# Copyright (c) 2025 Jan Malakhovski <oxij@oxij.org>
#
# This file can be redistributed under the terms of Unlicense
# <https://unlicense.org> license.
Comment on lines +2 to +5

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only worry I have is the re-introduction of separately licensed files, which we moved away from in the past: #171. Would you be okay with you to re-license it under the MPL-2.0 license and assign copyright to the generic "Nixfmt contributors" as defined in

nixfmt/.reuse/dep5

Lines 3 to 6 in e825e95

Files: *
Copyright: 2019-2022 Serokell <hi@serokell.io>
2019-2024 Nixfmt Contributors
License: MPL-2.0
?

Suggested change
# Copyright (c) 2025 Jan Malakhovski <oxij@oxij.org>
#
# This file can be redistributed under the terms of Unlicense
# <https://unlicense.org> license.


usage() {
cat - << EOF
usage: $0 LOCAL BASE REMOTE MERGED

A \`git-mergetool\`-compatible merge tool that uses \`nixfmt\` to merge more
stuff.

This tool rejects all non-\`.nix\` files, for \`.nix\` files it simply

- calls \`nixfmt\` on its first three inputs, followed by
- running \`git merge-file\` on the same inputs, followed by
- running \`nixfmt\` on the result.

Put the following to your \`~/.gitconfig\`:

\`\`\`
[mergetool "nixfmt"]
cmd = nixfmt-mergetool "\$LOCAL" "\$BASE" "\$REMOTE" "\$MERGED"
trustExitCode = true
\`\`\`

Then, when \`git merge\` or \`git rebase\` fails, run

\`\`\`
git mergetool -t nixfmt .
# or, only for some specific files
git mergetool -t nixfmt FILE1 FILE2 FILE3
\`\`\`

and some \`.nix\` files will probably get merged automagically.

Note that files that \`git\` merges successfully even before \`git mergetool\`
will be ignored by \`git mergetool\`.

If you don't like the result, run

\`\`\`
git restore --merge .
# or, only for some specific files
git restore --merge FILE1 FILE2 FILE3
\`\`\`

to return back to the unmerged state.
EOF
exit 1
}

[[ $# == 0 ]] && usage
case "$1" in
--h|--help|--usage) usage ;;
esac

[[ "${4##*.}" != "nix" ]] && echo "skipping $4" && exit 1

echo "merging $4"

nixfmt "$1" "$2" "$3"
ret=$?
[[ $ret != 0 ]] && echo "pre-formatting \`nixfmt\` failed" && exit $ret

trap 'rm -f "$4.merge.nix"' 0

git merge-file --stdout "$1" "$2" "$3" > "$4.merge.nix"
ret=$?
[[ $ret != 0 ]] && echo "\`git merge-file\` failed" && exit $ret

nixfmt "$4.merge.nix"
ret=$?
[[ $ret != 0 ]] && echo "post-formatting \`nixfmt\` failed" && exit $ret

mv "$4.merge.nix" "$4"