Skip to content

Commit d96433c

Browse files
committed
Rewrite the optimizePng task to try and take advantage of gradle's incremental change detection
1 parent d3c8f74 commit d96433c

File tree

2 files changed

+80
-48
lines changed

2 files changed

+80
-48
lines changed

build.gradle

Lines changed: 32 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.modrinth.minotaur.dependencies.VersionDependency
44
import groovy.json.JsonOutput
55
import groovy.json.JsonSlurper
66
import mekanism.MergeJars
7+
import mekanism.OptimizePng
78
import net.darkhax.curseforgegradle.TaskPublishCurseForge
89
import net.darkhax.curseforgegradle.UploadArtifact
910
import net.neoforged.gradle.dsl.common.runs.run.Run
@@ -32,7 +33,7 @@ defaultTasks('build')
3233
idea {
3334
module {
3435
//Exclude directories from being managed
35-
for (String excludeDirName in ["runs", "out", "logs", "gradle"]) {
36+
for (String excludeDirName : ["runs", "out", "logs", "gradle"]) {
3637
excludeDirs.add(new File(projectDir, excludeDirName))
3738
}
3839
//Tell IDEA to always download sources/javadoc artifacts from maven.
@@ -71,9 +72,7 @@ sourceSets {
7172
compileClasspath += api.output
7273
}
7374
gameTest {
74-
runs {
75-
modIdentifier = 'mekanismtests'
76-
}
75+
runs.modIdentifier = 'mekanismtests'
7776
compileClasspath += api.output
7877
}
7978
}
@@ -98,9 +97,7 @@ setupExtraSourceSets(sourceSets.gameTest, false)
9897
// based on the primary added source set
9998
for (String name : secondaryModules) {
10099
def sourceSet = sourceSets.create(name)
101-
sourceSet.runs {
102-
modIdentifier = name
103-
}
100+
sourceSet.runs.modIdentifier = name
104101
sourceSet.resources {
105102
//Add the generated module resources
106103
srcDirs += ["src/datagen/generated/mekanism${name}"]
@@ -127,10 +124,10 @@ def setupExtraSourceSets(SourceSet base, boolean includeExtra = true) {
127124
def baseLocalRuntime = project.configurations.maybeCreate(base.getTaskName(null, 'localRuntime'))
128125
if (base != project.sourceSets.main) {
129126
// If this is a secondary module then make the base tasks extend the builtin ones
130-
baseImplementation.extendsFrom(project.configurations.getByName('implementation'))
131-
baseCompileOnly.extendsFrom(project.configurations.getByName('compileOnly'))
132-
baseRuntimeOnly.extendsFrom(project.configurations.getByName('runtimeOnly'))
133-
baseLocalRuntime.extendsFrom(project.configurations.getByName('localRuntime'))
127+
baseImplementation.extendsFrom(project.configurations.named('implementation').get())
128+
baseCompileOnly.extendsFrom(project.configurations.named('compileOnly').get())
129+
baseRuntimeOnly.extendsFrom(project.configurations.named('runtimeOnly').get())
130+
baseLocalRuntime.extendsFrom(project.configurations.named('localRuntime').get())
134131
}
135132
if (includeExtra) {
136133
//And then setup and have all the extra sourceSets have their configurations extend the ones for the base module so that they can
@@ -141,7 +138,7 @@ def setupExtraSourceSets(SourceSet base, boolean includeExtra = true) {
141138
//And then setup the configurations for it
142139
def implExtends = [baseImplementation]
143140
if (extraType == 'datagen') {
144-
implExtends.add(project.configurations.getByName('datagenNonMod'))
141+
implExtends.add(project.configurations.named('datagenNonMod').get())
145142
}
146143
project.configurations.maybeCreate(extraSourceSet.getTaskName(null, 'implementation')).extendsFrom(*implExtends)
147144
project.configurations.maybeCreate(extraSourceSet.getTaskName(null, 'compileOnly')).extendsFrom(baseCompileOnly)
@@ -163,9 +160,7 @@ SourceSet setupExtraSourceSet(SourceSet baseSourceSet, String extra) {
163160
//If the base sourceSet is main it already is the extra source set and has a reference to the base one from before this if statement
164161
extraSourceSet.compileClasspath += getExtraSourceSet(project.sourceSets.main, extra).output
165162
extraSourceSet.compileClasspath += baseSourceSet.output
166-
extraSourceSet.runs {
167-
modIdentifier = name
168-
}
163+
extraSourceSet.runs.modIdentifier = name
169164
}
170165
return extraSourceSet
171166
}
@@ -177,16 +172,16 @@ static void extendConfigurations(Configuration base, Configuration... configurat
177172
}
178173

179174
SourceSet getExtraSourceSet(String base, String name) {
180-
return getExtraSourceSet(project.sourceSets.getByName(base), name)
175+
return getExtraSourceSet(project.sourceSets.named(base).get(), name)
181176
}
182177

183178
SourceSet getExtraSourceSet(SourceSet base, String name) {
184-
return project.sourceSets.getByName(base.getTaskName(name, null))
179+
return project.sourceSets.named(base.getTaskName(name, null)).get()
185180
}
186181

187182
setupTasks(sourceSets.main)
188183
for (String name : secondaryModules) {
189-
setupTasks(sourceSets.getByName(name))
184+
setupTasks(sourceSets.named(name).get())
190185
}
191186

192187
def setupTasks(SourceSet sourceSet) {
@@ -230,8 +225,8 @@ def setupTasks(SourceSet sourceSet) {
230225
dependsOn(compileTask)
231226
finalizedBy(replaceResourceTask)
232227
doLast {
233-
fileTree(dir: getOutputs().getFiles().getAsPath(), includes: jsonPatterns).each {
234-
File file -> file.setText(JsonOutput.toJson(new JsonSlurper().parse(file)))
228+
for (def file : fileTree(dir: getOutputs().getFiles().getAsPath(), includes: jsonPatterns)) {
229+
file.setText(JsonOutput.toJson(new JsonSlurper().parse(file)))
235230
}
236231
}
237232
}
@@ -547,7 +542,7 @@ def allJar = tasks.register('allJar', Jar, {
547542
from(sourceSets.main.output, MergeJars.createExcludeClosure(baseExcludeData, 'crafttweaker_parameter_names.json'))
548543
Closure<CopySpec> excludeFromAll = MergeJars.createExcludeClosure(baseExcludeData, 'logo.png', 'pack.mcmeta')
549544
for (String name : secondaryModules) {
550-
from(sourceSets.getByName(name).output, excludeFromAll)
545+
from(sourceSets.named(name).map(s -> s.output), excludeFromAll)
551546
}
552547
//And finally copy over the generated files
553548
MergeJars.getGeneratedClosures(versionProperties).each { closure -> from(layout.buildDirectory.dir('generated'), closure) }
@@ -577,34 +572,23 @@ artifacts {
577572
archives sourcesJar
578573
}
579574

580-
//Minimize/optimize all png files, requires optipng on the PATH
581-
// Credits: BrainStone
582-
void minimizePNGFile(File file) {
583-
long size = file.length()
584-
exec {
585-
executable('optipng')
586-
args('-q', '-o7', '-zm1-9', '-strip', 'all', file)
587-
}
588-
long newSize = file.length()
589-
if (newSize < size) {
590-
System.out.format('Reduced File size of %s from %d bytes to %d bytes (reduced by %.2f%%)\n',
591-
file, size, newSize, ((double) (size - newSize)) / ((double) size) * 100.0)
592-
}
593-
}
594-
595-
tasks.register('optimizePng').configure {
596-
doLast {
597-
def pngPatterns = ['**/*.png']
598-
//Ensure the logo is minimized (we add this file to each jar)
599-
minimizePNGFile(file("${projectDir}/logo.png"))
600-
//Minimize any PNGs in the source sets
601-
def sourceSets = [sourceSets.main, sourceSets.additions, sourceSets.generators, sourceSets.defense, sourceSets.tools]
602-
for (def sourceSet : sourceSets) {
603-
for (dir in sourceSet.resources.srcDirs) {
604-
fileTree(dir: dir, includes: pngPatterns).each { minimizePNGFile(it) }
605-
}
575+
tasks.register('optimizePng', OptimizePng) {
576+
def pngPatterns = ['**/*.png']
577+
//Ensure the logo is minimized (we add this file to each jar)
578+
inputFiles.from(file("${projectDir}/logo.png"))
579+
//Minimize any PNGs in the source sets
580+
def sourceSets = [sourceSets.main, sourceSets.additions, sourceSets.defense, sourceSets.generators, sourceSets.tools]
581+
for (def sourceSet : sourceSets) {
582+
for (def dir : sourceSet.resources.srcDirs) {
583+
inputFiles.from(fileTree(dir: dir, includes: pngPatterns))
606584
}
607585
}
586+
outputs.upToDateWhen {
587+
//Validate that none of the files has changed size, as the odds that a file has the exact same size and has changed is very low for an image file
588+
//Note: This is from Chat-GPT, I don't understand why the any check isn't just always true (and thus this being different from returning always false)
589+
// but it seems to function properly(?), whereas just always returning false does not
590+
!inputFiles.files.any { file -> file.length() != file.size() }
591+
}
608592
}
609593

610594
//properties to put in $HOME/.gradle/gradle.properties
@@ -714,7 +698,7 @@ tasks.register('outputChangelog') {
714698
}
715699
}
716700

717-
def mainCfUpload, additionsCfUpload, generatorsCfUpload, toolsCfUpload;
701+
def mainCfUpload, additionsCfUpload, generatorsCfUpload, toolsCfUpload
718702

719703
if (System.getenv('CURSEFORGE_KEY') != null || project.hasProperty('curseforgeKey')) {
720704
println('Enabling Curseforge config')
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package mekanism
2+
3+
import org.gradle.api.DefaultTask
4+
import org.gradle.api.file.ConfigurableFileCollection
5+
import org.gradle.api.file.FileType
6+
import org.gradle.api.model.ObjectFactory
7+
import org.gradle.api.tasks.InputFiles
8+
import org.gradle.api.tasks.TaskAction
9+
import org.gradle.work.ChangeType
10+
import org.gradle.work.Incremental
11+
import org.gradle.work.InputChanges
12+
13+
import javax.inject.Inject
14+
15+
class OptimizePng extends DefaultTask {
16+
17+
@InputFiles
18+
@Incremental
19+
final ConfigurableFileCollection inputFiles
20+
21+
@Inject
22+
OptimizePng(ObjectFactory objects) {
23+
this.inputFiles = objects.fileCollection()
24+
}
25+
26+
@TaskAction
27+
void execute(InputChanges inputChanges) {
28+
for (def fileChange : inputChanges.getFileChanges(inputFiles)) {
29+
if (fileChange.changeType == ChangeType.REMOVED || fileChange.fileType != FileType.FILE) {
30+
//Don't care about files that were removed
31+
continue
32+
}
33+
def file = fileChange.file
34+
//Minimize/optimize all png files, requires optipng on the PATH
35+
// Credits: BrainStone
36+
long size = file.length()
37+
project.exec {
38+
executable('optipng')
39+
args('-q', '-o7', '-zm1-9', '-strip', 'all', file)
40+
}
41+
long newSize = file.length()
42+
if (newSize < size) {
43+
System.out.format('Reduced File size of %s from %d bytes to %d bytes (reduced by %.2f%%)\n',
44+
file, size, newSize, ((double) (size - newSize)) / ((double) size) * 100.0)
45+
}
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)