Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add scripts/nixfmt-mergetool #277

Closed
wants to merge 1 commit into from
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 <[email protected]>
#
# This file can be redistributed under the terms of Unlicense
# <https://unlicense.org> license.
Comment on lines +2 to +5
Copy link
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 <[email protected]>
2019-2024 Nixfmt Contributors
License: MPL-2.0
?

Suggested change
# Copyright (c) 2025 Jan Malakhovski <[email protected]>
#
# 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"
Loading