1414import net .minecraftforge .mcmaven .impl .util .Artifact ;
1515import net .minecraftforge .mcmaven .impl .util .ComparableVersion ;
1616import net .minecraftforge .mcmaven .impl .util .Constants ;
17+ import net .minecraftforge .mcmaven .impl .util .POMBuilder ;
18+ import net .minecraftforge .mcmaven .impl .util .Util ;
1719import net .minecraftforge .util .data .json .JsonData ;
20+ import net .minecraftforge .util .file .FileUtils ;
1821import net .minecraftforge .util .hash .HashStore ;
1922import net .minecraftforge .util .hash .HashUtils ;
2023import static net .minecraftforge .mcmaven .impl .Mavenizer .LOGGER ;
2124
25+ import java .io .ByteArrayOutputStream ;
2226import java .io .File ;
27+ import java .io .FileOutputStream ;
28+ import java .io .IOException ;
29+ import java .io .StringReader ;
30+ import java .nio .charset .StandardCharsets ;
2331import java .util .ArrayList ;
32+ import java .util .Arrays ;
2433import java .util .HashMap ;
2534import java .util .HashSet ;
2635import java .util .List ;
2736import java .util .Map ;
2837
38+ import javax .xml .parsers .DocumentBuilderFactory ;
39+ import javax .xml .parsers .ParserConfigurationException ;
40+ import javax .xml .transform .OutputKeys ;
41+ import javax .xml .transform .TransformerException ;
42+ import javax .xml .transform .TransformerFactory ;
43+ import javax .xml .transform .dom .DOMSource ;
44+ import javax .xml .transform .stream .StreamResult ;
45+ import javax .xml .transform .stream .StreamSource ;
46+
47+ import org .w3c .dom .Node ;
48+ import org .xml .sax .SAXException ;
49+
2950// TODO [MCMavenizer][Deobf] ADD DEOBF
3051// use single detached configuration to resolve individual configurations
3152// pass in downloaded files to mcmaven (absolute path)
@@ -35,12 +56,14 @@ public record MinecraftMaven(
3556 Cache cache ,
3657 Mappings mappings ,
3758 Map <String , String > foreignRepositories ,
38- boolean globalAuxiliaryVariants
59+ boolean globalAuxiliaryVariants ,
60+ boolean disableGradle
3961) {
4062 private static final ComparableVersion MIN_SUPPORTED_FORGE = new ComparableVersion ("1.14.4" ); // Only 1.14.4+ has official mappings, we can support more when we add more mappings
4163
42- public MinecraftMaven (File output , boolean dependenciesOnly , File cacheRoot , File jdkCacheRoot , Mappings mappings , Map <String , String > foreignRepositories , boolean globalAuxiliaryVariants ) {
43- this (output , dependenciesOnly , new Cache (cacheRoot , jdkCacheRoot , foreignRepositories ), mappings , foreignRepositories , globalAuxiliaryVariants );
64+ public MinecraftMaven (File output , boolean dependenciesOnly , File cacheRoot , File jdkCacheRoot , Mappings mappings ,
65+ Map <String , String > foreignRepositories , boolean globalAuxiliaryVariants , boolean disableGradle ) {
66+ this (output , dependenciesOnly , new Cache (cacheRoot , jdkCacheRoot , foreignRepositories ), mappings , foreignRepositories , globalAuxiliaryVariants , disableGradle );
4467 }
4568
4669 public MinecraftMaven {
@@ -54,6 +77,7 @@ public MinecraftMaven(File output, boolean dependenciesOnly, File cacheRoot, Fil
5477 if (!foreignRepositories .isEmpty ())
5578 LOGGER .info (" Foreign Repos: [" + String .join (", " , foreignRepositories .values ()) + ']' );
5679 LOGGER .info (" GradleVariantHack: " + globalAuxiliaryVariants );
80+ LOGGER .info (" Disable Gradle: " + disableGradle );
5781 LOGGER .info ();
5882 }
5983
@@ -138,7 +162,13 @@ private void finalize(Artifact module, Mappings mappings, List<Repo.PendingArtif
138162 // I haven't added an opt-in for making artifacts that use mappings, so just assume any artifact with variants
139163 var artifact = pending .artifact ();
140164 String suffix = null ;
141- if (pending .variants () != null && !mappings .isPrimary ()) {
165+ if (!disableGradle && pending .variants () != null && !mappings .isPrimary ()) {
166+ // If we are not the primary mapping, but we haven't generated the primary mapping yet, do so.
167+ // This will duplicate the files. But the other option is to require not writing the variants until the primary mapping is requested.
168+ var primaryTarget = new File (this .output , artifact .getLocalPath ());
169+ if (!primaryTarget .exists ())
170+ updateFile (primaryTarget , pending .get (), pending .artifact ());
171+
142172 suffix = mappings .channel () + '-' + mappings .version ();
143173 if (artifact .getClassifier () == null )
144174 artifact = artifact .withClassifier (suffix );
@@ -147,41 +177,18 @@ private void finalize(Artifact module, Mappings mappings, List<Repo.PendingArtif
147177 }
148178
149179 var target = new File (this .output , artifact .getLocalPath ());
150- var varTarget = new File (this .output , artifact .getLocalPath () + ".variants" );
151- {
152- var source = pending .get ();
153- var cache = HashStore .fromFile (target )
154- .add ("source" , source );
155-
156- boolean write ;
157- if ("pom" .equals (pending .artifact ().getExtension ())) {
158- // Write the pom for non-primary mappings if we haven't generated primary mappings yet
159- write = !target .exists () || (mappings .isPrimary () && !cache .isSame ());
160- } else {
161- write = !target .exists () || !cache .isSame ();
162- }
163-
164- if (write ) {
165- // TODO: [MCMavenizer] Add --api argument to turn class artifacts to api-only targets for a public repo
166- try {
167- org .apache .commons .io .FileUtils .copyFile (source , target );
168- HashUtils .updateHash (target );
169- cache .save ();
170- } catch (Throwable t ) {
171- throw new RuntimeException ("Failed to generate artifact: %s" .formatted (artifact ), t );
172- }
173- }
174- }
180+ updateFile (target , pending .get (), pending .artifact ());
175181
176- if (pending .variants () != null ) {
182+ var varTarget = new File (this .output , artifact .getLocalPath () + ".variants" );
183+ if (!disableGradle && pending .variants () != null ) {
177184 var source = pending .variants ().execute ();
178185 var cache = HashStore .fromFile (varTarget )
179186 .add ("source" , source );
180187
181188 if (!varTarget .exists () || !cache .isSame ()) {
182189 variants .add (Artifact .from (artifact .getGroup (), artifact .getName (), artifact .getVersion ()));
183190 try {
184- var data = JsonData .fromJson (source , GradleModule .Variant [].class );
191+ GradleModule . Variant [] data = JsonData .fromJson (source , GradleModule .Variant [].class );
185192 if (!dependenciesOnly ) {
186193 var file = new GradleModule .Variant .File (target );
187194 for (var variant : data ) {
@@ -190,6 +197,8 @@ private void finalize(Artifact module, Mappings mappings, List<Repo.PendingArtif
190197 variant .name = variant .name + '-' + suffix ;
191198 }
192199 }
200+ // Sort them to make it predictable/easy to diff
201+ Arrays .sort (data , (a , b ) -> a .name .compareTo (b .name ));
193202 JsonData .toJson (data , varTarget );
194203 cache .save ();
195204 } catch (Throwable t ) {
@@ -204,6 +213,36 @@ private void finalize(Artifact module, Mappings mappings, List<Repo.PendingArtif
204213 }
205214 }
206215
216+ private void updateFile (File target , File source , Artifact artifact ) {
217+ var cache = HashStore .fromFile (target )
218+ .add ("source" , source );
219+
220+ var isPom = "pom" .equals (artifact .getExtension ());
221+ boolean write ;
222+ if (isPom ) {
223+ cache .addKnown ("disableGradle" , Boolean .toString (disableGradle ));
224+ // Write the pom for non-primary mappings if we haven't generated primary mappings yet
225+ write = !target .exists () || ((disableGradle || mappings .isPrimary ()) && !cache .isSame ());
226+ } else {
227+ write = !target .exists () || !cache .isSame ();
228+ }
229+
230+ if (write ) {
231+ // TODO: [MCMavenizer] Add --api argument to turn class artifacts to api-only targets for a public repo
232+ try {
233+ if (disableGradle && isPom ) {
234+ makeNonGradlePom (source , target );
235+ } else {
236+ org .apache .commons .io .FileUtils .copyFile (source , target );
237+ }
238+ HashUtils .updateHash (target );
239+ cache .save ();
240+ } catch (Throwable t ) {
241+ throw new RuntimeException ("Failed to generate artifact: %s" .formatted (artifact ), t );
242+ }
243+ }
244+ }
245+
207246 private void updateVariants (Artifact artifact ) {
208247 var root = new File (this .output , artifact .getFolder ());
209248 var inputs = new ArrayList <File >();
@@ -241,4 +280,62 @@ private void updateVariants(Artifact artifact) {
241280 throw new RuntimeException ("Failed to write artifact module: %s" .formatted (artifact ), t );
242281 }
243282 }
283+
284+ private void makeNonGradlePom (File source , File target ) throws IOException , SAXException , ParserConfigurationException , TransformerException {
285+ var docFactory = DocumentBuilderFactory .newInstance ();
286+ var docBuilder = docFactory .newDocumentBuilder ();
287+ var doc = docBuilder .parse (source );
288+
289+ var modified = false ;
290+ var projects = doc .getElementsByTagName ("project" );
291+ for (var x = 0 ; x < projects .getLength (); x ++) {
292+ var project = projects .item (x );
293+ var children = project .getChildNodes ();
294+ for (int y = 0 ; y < children .getLength (); y ++) {
295+ var child = children .item (y );
296+ if (child .getNodeType () == Node .COMMENT_NODE ) {
297+ var content = child .getTextContent ();
298+ if (content .equals (POMBuilder .GRADLE_MAGIC_COMMENT )) {
299+ project .removeChild (child );
300+ y --;
301+ modified = true ;
302+ }
303+ }
304+ }
305+ }
306+
307+ if (!modified ) {
308+ org .apache .commons .io .FileUtils .copyFile (source , target );
309+ return ;
310+ }
311+
312+ var transformerFactory = TransformerFactory .newInstance ();
313+ var transformer = transformerFactory .newTransformer (new StreamSource (new StringReader (
314+ // This needs to strip spacing so our output doesn't have extra whitespace
315+ """
316+ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
317+ <xsl:strip-space elements="*"/>
318+ <xsl:output method="xml" encoding="UTF-8"/>
319+
320+ <xsl:template match="@*|node()">
321+ <xsl:copy>
322+ <xsl:apply-templates select="@*|node()"/>
323+ </xsl:copy>
324+ </xsl:template>
325+ </xsl:stylesheet>
326+ """
327+ )));
328+
329+ transformer .setOutputProperty (OutputKeys .INDENT , "yes" ); //Make it pretty
330+ transformer .setOutputProperty ("{http://xml.apache.org/xslt}indent-amount" , "2" );
331+
332+ var output = new ByteArrayOutputStream ();
333+ transformer .transform (new DOMSource (doc ), new StreamResult (output ));
334+ var data = output .toString ().getBytes (StandardCharsets .UTF_8 );
335+
336+ FileUtils .ensureParent (target );
337+ try (var os = new FileOutputStream (target )) {
338+ os .write (data );
339+ }
340+ }
244341}
0 commit comments