-
Notifications
You must be signed in to change notification settings - Fork 459
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
spotlessApply --staged #623
Comments
The relevant parts are a combination of Because the total number of files staged is typically so few, there is potentially a meaningful speedup to be had from not configuring every project, and limiting yourself to only those projects which are parents of the files in question. So the right command is probably not |
This is quite interesting, and something I've been thinking about how to leverage properly. Before I knew about the ratchet feature, I was building a Git hooks plugin to copy the functionality of husky and lint-staged for Gradle projects at work. It follows the same strategy as those projects, except it tries to expose the list of staged files to tasks and plugins by setting a Gradle property. You can see the idea expressed on the project page, and you can see some of the logic that handles dealing with the staging area in this file. There are some caveats I've observed (some related only to how I've implemented it, and some that other implementations would need to deal with).
With that said, I'm wondering whether you think some of this logic can be extracted and reused in Spotless, or if Spotless should delegate this behavior to other solutions while maintaining an integration API (which might exist already). |
I left feedback on your
Yes and yes. We maintain a stable API, both at the
We do use JGit, but we also shell out to Git in some places, so that's not a showstopper. The showstopper, in terms of getting merged, is about whether the docs are simple. user@machine repo % ./gradlew build
:spotlessJavaCheck FAILED
The following files had format violations:
src\main\java\com\diffplug\gradle\spotless\FormatExtension.java
-\t\t····if·(targets.length·==·0)·{
+\t\tif·(targets.length·==·0)·{
Run './gradlew spotlessApply' to fix these violations.
user@machine repo % ./gradlew spotlessApply
:spotlessApply
BUILD SUCCESSFUL
user@machine repo % ./gradlew build
BUILD SUCCESSFUL The problem with the staging area is that it makes things more complicated. I like
So normally, if you run That paragraph above is pretty complicated. I think you could leave it out of the feature docs, because you're never losing user data, and it mostly just "does the right thing". But if you add even a little bit more complexity to the intended behavior, it gets really hard for users to understand what they're getting, and what the intended behavior even is. I don't have plans to implement this feature anytime soon, so PR's are absolutely encouraged. But I would start with the docs first, and feel free to open a PR with just the documentation change. If you get buy-in on the docs, then you are guaranteed to get merged eventually. That goes both for implementing |
@nedtwigg Is this supposed to be available soon? I'm looking for a solution to spotlessApply before every commit. |
@ShivamGoyal1899 PR's welcome, no work is scheduled. There's a workaround linked above, search "git hook script". |
@nedtwigg I actually tried creating a simple pre-commit hook in combination with #!/bin/sh
set -e
./gradlew -PdisableSpotlessCheck spotlessApply
git update-index --again :/: |
I don't think you need |
A good idea from git-code-format-maven-plugin is for the plugin to setup the git commit hooks itself. Worth looking into. |
We created the hook manually, as I suggested above, but it also seemed to run on every back merge we do from upstream branches, making the change so big that it's very hard to review. Also, as this was on a production codebase with almost 10-15 PRs a day with 100+ files each, the number of conflicts we were getting was intolerable. We ended up removing the hook, making the process back to normal till our entire codebase is formatted. |
I think |
Agreed with the format everything once idea. Right now, we are trying to pick chunks and reformat, once it reaches around half of the entire project, the plan is to find a sweet spot where we have least PRs and format remaining in one go. |
Just in case it helps anyone who wants to work on this issue, or has the same need of "all files in my staging area must be this way", here's my git pre-commit hook to do that. I think the only way I've seen this fail in six or so months of using it now is when you stage just a few lines in a file that Spotless then reformats in a way so the remaining unstaged changes can't be reapplied on top of the latest formatted state. I stage and commit single lines/range of lines/hunks all the time, and have only run into that once or twice, though. #!/bin/bash
set -euo pipefail
pop_stash() {
if [ "$previous_stash" != "$new_stash" ]; then
echo "Popping stash and restoring unstaged changes..."
git stash pop --quiet
git restore --quiet --staged .
fi
}
echo "Temporarily comitting staged changes..."
git commit --quiet --no-verify --message 'Staged changes'
echo "Temporarily stashing unstaged changes including new files..."
git add --all
previous_stash=$(git rev-parse -q --verify refs/stash)
git stash push --quiet --staged --message 'Unstaged changes'
new_stash=$(git rev-parse -q --verify refs/stash)
echo "Reverting temporary commit to bring back staged changes..."
git reset --soft HEAD^
echo "Running Gradle ':format' task on staged changes..."
if ! ./gradlew :format; then
echo "Gradle execution failed"
echo "Temporarily comitting staged changes..."
git commit --quiet --no-verify --message 'Staged changes'
pop_stash
echo "Reverting temporary commit to bring back staged changes..."
git reset --soft HEAD^
exit 1
fi
echo "Staging formatting changes (if any) and temporarily comitting staged and formatted changes..."
git add --all
git commit --quiet --no-verify --message 'Staged and formatted changes'
pop_stash
echo "Reverting temporary commit to bring back staged and formatted changes..."
git reset --soft HEAD^ |
this reverts commit 5d1518c. pre-commit introduces unnecessary complications in managing formatting for staged files only. furthermore, spotless lacks support for this issue (see diffplug/spotless#623). additionally, pre-commit's downsides are worsened by slow initial gradle build times.
Hello Do you see a way of using spotless within the build and apply it to only changed files ? (Without using a git hook ) |
Spotless applies itself to the files on disk. However, when git makes a commit, it does not use the files on disk, it uses the staging area. If you do this:
Then your commit will definitely pass a
spotlessCheck
. But if you do this, it might not:aside: this three-files-per-file model, with an independent index, is confusing to beginners, and imo of limited utility even to experts, which is why DiffPlug doesn't have a staging area.
@lowwor made an excellent git hook script which uses the stash to run
spotlessCheck
on staged files.With our new git integration, it would now be relatively easy for Spotless to have a mode which operates on the staging area directly. This is especially useful for pre-commit hooks, which could either fail on badly formatted content
spotlessCheck --staged
, or silently fix the commit right before it is createdspotlessApply --staged
.Due to merge conflicts that this is likely to generate, implementing this is blocked on #603 and #600.PR's welcome!The text was updated successfully, but these errors were encountered: