-
Notifications
You must be signed in to change notification settings - Fork 455
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
Make FileSignature
machine-independent.
#566
Comments
One possible fix, change this: spotless/lib/src/main/java/com/diffplug/spotless/FileSignature.java Lines 83 to 94 in eb783cd
into filenames[i] = file.getName()
filesizes[i] = file.length();
hash[i] = someFastHash(file) This performs a good bit worse, because it requires reading every single config file, and we have to do it for every single step. It could be improved by only doing the hashing on serialization, and continuing to rely on filesystem timestamps for non-serialized in-memory A faster, but perhaps harder-to-implement, alternative would be to pass around a
Could start off with the easy low-performance one, and then do the harder one later... |
@lutovich implemented the content-hashing approach in #571. I implemented a content-hash-when-appropriate mode in #573. I have a lot of confidence that 571 will work. I think 573 can probably work, and is faster, but it's definitely more treacherous. It's possible that the speedup of 573 is immeasurably small, in which case 571 is the slam-dunk answer. Even if 573 is measurably faster, it needs to be a lot faster to justify the testing effort and complexity. I'm gonna stew on this for a while. Just wanted to get both ideas out there in case it sparks any ideas from other stakeholders. |
@nedtwigg I'm wondering if it's worth reworking how and when This runs somewhat counter to idiomatic Gradle, where we generally expect the inputs to a task to be value objects that can be easily tracked for changes, with the task itself responsible for translating these configuration values into executable logic. For example, instead of the task input being a complete I understand this would be a big change, and I'm sure I'm glossing over some major difficulties in the migration. But I believe it's worth considering, and would have the following benefits:
|
I definitely agree that it is no longer necessary, in the gradle plugin, for The fundamental value proposition of Spotless is that you can compose formatters, rather than use just one specific formatter. If someone makes a good license header gizmo, you can use it with every formatter, not just foo. Correct me if I'm wrong, but: public class SpotlessTask {
@Nested
public List<FormatterStep> steps;
...
}
public class FooStep implements FormatterStep {
@Input
String someProp
@InputFile
@PathSensitive(PathSensitivity.RELATIVE)
File configFile
...
}
If Gradle provides the ability to inspect a generic The sticking point, as I see it.If we merge #571, I think we would be most of the way there already. It would be ever-so-slightly less performant than if we made our inputs available to Gradle in the canonical way, but there's still a possibility to do that someday by making FileSignature into a service, which in Gradle could be injected with a Gradle-specific implementation. So I think we already have a good and easy path to make the build cache machine independent, except...: The big sticking point, is GitAttributesLineEndings. The problem is, people have weird git setups that they don't understand. And that means any autoformatter is going to end up fighting git and seem "broken", unless your autoformatter understands git, and silently does whatever whackadoodle thing git is configured to do. We put a lot of work into making that as efficient as possible, by lazily finding the It's tempting to replace A way forwardIf we fix |
I'm happy that we're close to having cacheability working for Spotless, which was my primary goal setting out. So I don't see any great pressure to refactor things. However, the In this example the task input is a list of beans; each implementation has it's own input file property and one of the implementations delegates to another The |
Awesome, thanks for the info! |
Released in |
This is a prerequisite to making the gradle build cache useful across machines (#280). Here is why:
spotless formats by applying a series of steps - every step is capable of serializing its entire state, including config files, for the purpose of up-to-date checks
spotless/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessTask.java
Lines 143 to 146 in eb783cd
spotless/lib/src/main/java/com/diffplug/spotless/FormatterStep.java
Lines 58 to 72 in eb783cd
spotless/lib/src/main/java/com/diffplug/spotless/LazyForwardingEquality.java
Lines 41 to 75 in eb783cd
so far so good, this means that most steps will work with the gradle build cache. The problem is for some formatters that have config files.
LicenseHeaderStep
spotless/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java
Lines 142 to 145 in eb783cd
FileSignature
, which will not relocate.ScalaFmtStep
spotless/lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java
Lines 64 to 81 in eb783cd
FileSignature
uses filesystem absolute paths and lastModified timestamptsspotless/lib/src/main/java/com/diffplug/spotless/FileSignature.java
Lines 43 to 45 in eb783cd
Worst of all,
JarState
is used by almost every single FormatterStep, and it has aFileSignature
inside itspotless/lib/src/main/java/com/diffplug/spotless/JarState.java
Lines 42 to 47 in eb783cd
The text was updated successfully, but these errors were encountered: