Skip to content

Commit 12c8d92

Browse files
committed
Copy published data files prior to publishing.
1 parent 4bd8be7 commit 12c8d92

File tree

3 files changed

+148
-2
lines changed

3 files changed

+148
-2
lines changed

src/main/java/net/neoforged/moddevgradle/internal/DataFileCollections.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import java.util.function.Consumer;
55
import net.neoforged.moddevgradle.dsl.DataFileCollection;
66
import net.neoforged.moddevgradle.internal.utils.ExtensionUtils;
7+
import net.neoforged.moddevgradle.internal.utils.StringUtils;
8+
import net.neoforged.moddevgradle.tasks.CopyDataFile;
79
import org.gradle.api.Project;
810
import org.gradle.api.artifacts.ConfigurablePublishArtifact;
911
import org.gradle.api.artifacts.Configuration;
@@ -93,15 +95,36 @@ private static CollectionWrapper createCollection(Project project, String name,
9395
}
9496
});
9597

98+
var copyTaskName = "copy" + StringUtils.capitalize(name) + "DataPublications";
99+
var copyTask = project.getTasks().register(copyTaskName, CopyDataFile.class);
100+
96101
var depFactory = project.getDependencyFactory();
97102
Consumer<Object> publishCallback = new Consumer<>() {
98103
ConfigurablePublishArtifact firstArtifact;
99104
int artifactCount;
100105

101106
@Override
102107
public void accept(Object artifactNotation) {
103-
elementsConfiguration.getDependencies().add(depFactory.create(project.files(artifactNotation)));
104-
project.getArtifacts().add(elementsConfiguration.getName(), artifactNotation, artifact -> {
108+
// We copy the provided artifact somewhere in the build directory in order to avoid
109+
// plugins which generate companion files (gpg 'signing'), from generating these inside the user's source directories.
110+
111+
// We have to resolve this as a collection because `project.files` doesn't support resolving the outputs of a task.
112+
var inputFiles = project.files(artifactNotation);
113+
if (inputFiles.isEmpty()) return; // what?
114+
if (inputFiles.getFiles().size() > 1) {
115+
throw new RuntimeException("More than one file specified. Not supported by the publishing api.");
116+
}
117+
var copyInput = inputFiles.iterator().next();
118+
var copyOutput = project.getLayout().getBuildDirectory().file(copyTaskName + "/" + artifactCount + "/" + copyInput.getName());
119+
copyTask.configure(t -> {
120+
t.getRawInputs().getFrom().add(inputFiles);
121+
t.getInputFiles().add(project.getLayout().file(project.provider(() -> copyInput)));
122+
t.getOutputFiles().add(copyOutput);
123+
});
124+
125+
elementsConfiguration.getDependencies().add(depFactory.create(project.files(copyOutput)));
126+
project.getArtifacts().add(elementsConfiguration.getName(), copyOutput, artifact -> {
127+
artifact.builtBy(copyTask);
105128
if (firstArtifact == null) {
106129
firstArtifact = artifact;
107130
artifact.setClassifier(category);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package net.neoforged.moddevgradle.tasks;
2+
3+
import java.io.IOException;
4+
import java.nio.file.Files;
5+
import java.nio.file.StandardCopyOption;
6+
import org.gradle.api.DefaultTask;
7+
import org.gradle.api.file.ConfigurableFileCollection;
8+
import org.gradle.api.file.RegularFile;
9+
import org.gradle.api.provider.ListProperty;
10+
import org.gradle.api.tasks.InputFiles;
11+
import org.gradle.api.tasks.OutputFiles;
12+
import org.gradle.api.tasks.TaskAction;
13+
14+
public abstract class CopyDataFile extends DefaultTask {
15+
@InputFiles // Exists to implicitly declare task dependencies.
16+
public abstract ConfigurableFileCollection getRawInputs();
17+
18+
@InputFiles
19+
public abstract ListProperty<RegularFile> getInputFiles();
20+
21+
@OutputFiles
22+
public abstract ListProperty<RegularFile> getOutputFiles();
23+
24+
@TaskAction
25+
public void doCopy() throws IOException {
26+
var inputs = getInputFiles().get();
27+
var outputs = getOutputFiles().get();
28+
if (inputs.size() != outputs.size()) throw new RuntimeException("Lists length dont match.");
29+
30+
for (int i = 0; i < inputs.size(); i++) {
31+
var in = inputs.get(i).getAsFile().toPath();
32+
var out = outputs.get(i).getAsFile().toPath();
33+
Files.createDirectories(out.getParent());
34+
Files.copy(in, out, StandardCopyOption.REPLACE_EXISTING);
35+
}
36+
}
37+
}

src/test/java/net/neoforged/moddevgradle/functional/DataFileCollectionFunctionalTest.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,90 @@ public void testPublishAccessTransformerFile() throws IOException {
3737
entry("publish-at-1.0-accesstransformer.cfg", "# hello world"));
3838
}
3939

40+
@Test
41+
public void testPublishSignedAccessTransformerFileDoesntProduceGarbageNextToTheFile() throws IOException {
42+
var atFile = testProjectDir.toPath().resolve("accesstransformer.cfg");
43+
Files.writeString(atFile, "# hello world");
44+
45+
publishDataFiles("test", "publish-at", "1.0", """
46+
neoForge {
47+
accessTransformers {
48+
publish(project.file("accesstransformer.cfg"))
49+
}
50+
}
51+
signing {
52+
useInMemoryPgpKeys(
53+
""\"
54+
-----BEGIN PGP PRIVATE KEY BLOCK-----
55+
Version: Keybase OpenPGP v1.0.0
56+
Comment: https://keybase.io/crypto
57+
58+
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
108+
Zg==
109+
=QLGC
110+
-----END PGP PRIVATE KEY BLOCK-----
111+
""\",
112+
"password"
113+
)
114+
sign publishing.publications.maven
115+
}
116+
""");
117+
118+
assertThat(Files.exists(atFile.resolveSibling(atFile.getFileName() + ".asc")))
119+
.isFalse();
120+
assertThat(consumeDataFilePublication("accessTransformers", "test:publish-at:1.0")).containsOnly(
121+
entry("publish-at-1.0-accesstransformer.cfg", "# hello world"));
122+
}
123+
40124
@Test
41125
public void testPublishInterfaceInjectionFile() throws IOException {
42126
writeProjectFile("interfaces.json", "[]");
@@ -133,10 +217,12 @@ private void publishDataFiles(String groupId,
133217
}
134218
rootProject.name = "{0}"
135219
""", artifactId);
220+
// TODO we should probably not just always apply the signing plugin?
136221
writeGroovyBuildScript("""
137222
plugins {
138223
id "net.neoforged.moddev"
139224
id "maven-publish"
225+
id "signing"
140226
}
141227
group = "{0}"
142228
version = "{1}"

0 commit comments

Comments
 (0)