Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]

## [4.4.2] - 2025-11-06
### Fixed
- Changed CleanedAssert assertion to pass when attributes aren't in the correct order by normalizing XML content before comparison. Fixes test failures when running tests in P2ModelTest with Nondex due to non-deterministic attribute ordering in tags resulting from mirrorApp. ([#222](https://github.com/diffplug/goomph/pull/222))

## [4.4.1] - 2025-10-15
### Fixed
- Fixed build failure when querying APT options for compile tasks before `project.afterEvaluate`.
Expand Down
4 changes: 2 additions & 2 deletions HOW_TO_AUTOMATE_IDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ So you want to automate your IDE configuration. The first thing to do is look a
- [Spotless](https://github.com/diffplug/spotless/blob/gradle/5.17.1/ide/build.gradle) (single-project Gradle plugin)
- (your example here)

The next thing is to look at the [javadoc](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/oomph/OomphIdePlugin.html) for `OomphIdePlugin`, which inclues a pretty in-depth look at how it works.
The next thing is to look at the [javadoc](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/oomph/OomphIdePlugin.html) for `OomphIdePlugin`, which inclues a pretty in-depth look at how it works.

## How do I automate ${MY_THING} which isn't in the examples or docs?

Expand All @@ -27,7 +27,7 @@ Depending on what you're trying to automate, you might need to touch all three.

Manipulating project files is a [core part of gradle](https://docs.gradle.org/current/userguide/eclipse_plugin.html), so we won't cover that here.

Manipulating plugin and feature jars has lots of coverage in the examples above. The entire `oomphIdeBlock` extends [P2Declarative](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/p2/P2Declarative.html).
Manipulating plugin and feature jars has lots of coverage in the examples above. The entire `oomphIdeBlock` extends [P2Declarative](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/p2/P2Declarative.html).
So if you want to add any features, you just add the required p2 repositories, and then specify the features or installable units that you need.

Manipulating the workspace is where it gets tricky. We'll dig in below:
Expand Down
48 changes: 24 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ output = [
[![Maven artifact](https://img.shields.io/badge/mavenCentral-com.diffplug.gradle%3Agoomph-blue.svg)](https://search.maven.org/artifact/com.diffplug.gradle/goomph)
[![License Apache](https://img.shields.io/badge/license-Apache-blue.svg)](https://tldrlegal.com/license/apache-license-2.0-(apache-2.0))

[![Changelog](https://img.shields.io/badge/changelog-4.4.1-brightgreen.svg)](CHANGES.md)
[![Javadoc](https://img.shields.io/badge/javadoc-yes-brightgreen.svg)](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/index.html)
[![Changelog](https://img.shields.io/badge/changelog-4.4.2-brightgreen.svg)](CHANGES.md)
[![Javadoc](https://img.shields.io/badge/javadoc-yes-brightgreen.svg)](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/index.html)
[![Live chat](https://img.shields.io/badge/gitter-live_chat-brightgreen.svg)](https://gitter.im/diffplug/goomph)
[![CircleCI](https://circleci.com/gh/diffplug/goomph.svg?style=shield)](https://circleci.com/gh/diffplug/goomph)
<!---freshmark /shields -->
Expand Down Expand Up @@ -48,46 +48,46 @@ Below is an index of Goomph's capabilities, along with links to the javadoc wher

#### `com.diffplug.eclipse` Eclipse project files and eclipse version-mapping maven central artifacts.

* [`apt`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/eclipse/apt/AptEclipsePlugin.html) fixes eclipse project to work with Gradle annotation processing.
* [`mavencentral`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/eclipse/MavenCentralPlugin.html) makes it easy to add dependency jars from an eclipse release.
* [`buildproperties`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/eclipse/BuildPropertiesPlugin.html) uses [`build.properties`](https://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.pde.doc.user%2Fguide%2Ftools%2Feditors%2Fmanifest_editor%2Fbuild.htm) to control a gradle build, and fixes eclipse project classpath to include binary assets specified in `build.properties`.
* [`excludebuildfolder`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/eclipse/ExcludeBuildFolderPlugin.html) excludes the gradle `build` folder from Eclipse's resource indexing.
* [`projectdeps`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/eclipse/ProjectDepsPlugin.html) fixes an intermittent problem where dependencies on other projects within the workspace aren't always resolved correctly within Eclipse.
* [`resourcefilters`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/eclipse/ResourceFiltersPlugin.html) adds resource filters to the eclipse project.
* [`apt`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/eclipse/apt/AptEclipsePlugin.html) fixes eclipse project to work with Gradle annotation processing.
* [`mavencentral`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/eclipse/MavenCentralPlugin.html) makes it easy to add dependency jars from an eclipse release.
* [`buildproperties`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/eclipse/BuildPropertiesPlugin.html) uses [`build.properties`](https://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.pde.doc.user%2Fguide%2Ftools%2Feditors%2Fmanifest_editor%2Fbuild.htm) to control a gradle build, and fixes eclipse project classpath to include binary assets specified in `build.properties`.
* [`excludebuildfolder`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/eclipse/ExcludeBuildFolderPlugin.html) excludes the gradle `build` folder from Eclipse's resource indexing.
* [`projectdeps`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/eclipse/ProjectDepsPlugin.html) fixes an intermittent problem where dependencies on other projects within the workspace aren't always resolved correctly within Eclipse.
* [`resourcefilters`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/eclipse/ResourceFiltersPlugin.html) adds resource filters to the eclipse project.

#### `com.diffplug.osgi` Plugins for working with OSGi.

* [`bndmanifest`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/osgi/BndManifestPlugin.html) generates a manifest using purely bnd, and outputs it for IDE consumption.
* [`equinoxlaunch`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/eclipserunner/EquinoxLaunchPlugin.html) can configure and run equinox applications as part of the build, such as a code generator.
* [`OsgiExecable`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/osgi/OsgiExecable.html) makes it easy to run a chunk of code within an OSGi container, and get the result from outside the container.
* [`bndmanifest`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/osgi/BndManifestPlugin.html) generates a manifest using purely bnd, and outputs it for IDE consumption.
* [`equinoxlaunch`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/eclipserunner/EquinoxLaunchPlugin.html) can configure and run equinox applications as part of the build, such as a code generator.
* [`OsgiExecable`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/osgi/OsgiExecable.html) makes it easy to run a chunk of code within an OSGi container, and get the result from outside the container.

#### `com.diffplug.p2` A and plugins for manipulating p2 data. (*mostly [abandoned](https://github.com/diffplug/goomph/issues/166#issuecomment-945188596) now*)

* [`asmaven`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/p2/AsMavenPlugin.html) downloads dependencies from a p2 repository and makes them available in a local maven repository.
* [`P2Model`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/p2/P2Model.html) models a set of p2 repositories and IUs, and provides convenience methods for running p2-director or the p2.mirror ant task against these.
* [`P2AntRunner`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/p2/P2AntRunner.html) runs eclipse ant tasks.
* [`CategoryPublisher`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/p2/CategoryPublisher.html) models the CategoryPublisher eclipse application.
* [`FeaturesAndBundlesPublisher`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/p2/FeaturesAndBundlesPublisher.html) models the FeaturesAndBundlesPublisher eclipse application.
* [`Repo2Runnable`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/p2/Repo2Runnable.html) models the Repo2Runnable eclipse application.
* [`asmaven`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/p2/AsMavenPlugin.html) downloads dependencies from a p2 repository and makes them available in a local maven repository.
* [`P2Model`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/p2/P2Model.html) models a set of p2 repositories and IUs, and provides convenience methods for running p2-director or the p2.mirror ant task against these.
* [`P2AntRunner`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/p2/P2AntRunner.html) runs eclipse ant tasks.
* [`CategoryPublisher`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/p2/CategoryPublisher.html) models the CategoryPublisher eclipse application.
* [`FeaturesAndBundlesPublisher`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/p2/FeaturesAndBundlesPublisher.html) models the FeaturesAndBundlesPublisher eclipse application.
* [`Repo2Runnable`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/p2/Repo2Runnable.html) models the Repo2Runnable eclipse application.

#### `com.diffplug.gradle.pde` Tasks for running Eclipse PDE using a downloaded eclipse instance. (*this part is mostly [abandoned](https://github.com/diffplug/goomph/issues/166#issuecomment-945188596) now*)

* [`PdeBuildTask`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/pde/PdeBuildTask.html) runs PDE build to build an RCP product.
* [`PdeAntBuildTask`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/pde/PdeAntBuildTask.html) runs PDE on an ant file.
* [`PdeBuildTask`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/pde/PdeBuildTask.html) runs PDE build to build an RCP product.
* [`PdeAntBuildTask`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/pde/PdeAntBuildTask.html) runs PDE on an ant file.

#### `com.diffplug.gradle` Miscellaneous infrastructure.

* [`CmdLineTask`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/CmdLineTask.html) runs a series of shell commands, possibly copying or moving files in the meantime.
* [`JavaExecable`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/JavaExecable.html) makes it easy to run a chunk of code in a separate JVM, and get the result back in this one.
* [`JavaExecWinFriendly`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/JavaExecWinFriendly.html) overcomes limitations in Windows' commandline length and long classpaths.
* [`CmdLineTask`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/CmdLineTask.html) runs a series of shell commands, possibly copying or moving files in the meantime.
* [`JavaExecable`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/JavaExecable.html) makes it easy to run a chunk of code in a separate JVM, and get the result back in this one.
* [`JavaExecWinFriendly`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/JavaExecWinFriendly.html) overcomes limitations in Windows' commandline length and long classpaths.

#### `com.diffplug.gradle.eclipserunner` Infrastructure for running headless eclipse applications.

* Used to power the infrastructure above.

#### Other

* [`com.diffplug.configuration-cache-for-platform-specific-build`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/swt/PlatformSpecificBuildPlugin.html) allows you to use `OS.getNative()` and `OS.getRunning()` in your gradle build without breaking the configuration cache.
* [`com.diffplug.configuration-cache-for-platform-specific-build`](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/swt/PlatformSpecificBuildPlugin.html) allows you to use `OS.getNative()` and `OS.getRunning()` in your gradle build without breaking the configuration cache.

## IDE-as-build-artifact. (*this part is mostly [abandoned](https://github.com/diffplug/goomph/issues/189)*)

Expand All @@ -110,7 +110,7 @@ oomphIde {
}
```

See the [plugin's javadoc](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.1/com/diffplug/gradle/oomph/OomphIdePlugin.html) for a quickstart, and [HOW_TO_AUTOMATE_IDE.md](HOW_TO_AUTOMATE_IDE.md) for examples and more in-depth details.
See the [plugin's javadoc](https://javadoc.io/doc/com.diffplug.gradle/goomph/4.4.2/com/diffplug/gradle/oomph/OomphIdePlugin.html) for a quickstart, and [HOW_TO_AUTOMATE_IDE.md](HOW_TO_AUTOMATE_IDE.md) for examples and more in-depth details.

<!---freshmark /javadoc -->

Expand Down
3 changes: 1 addition & 2 deletions src/main/java/com/diffplug/gradle/p2/P2Model.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2019 DiffPlug
* Copyright (C) 2015-2025 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,7 +15,6 @@
*/
package com.diffplug.gradle.p2;


import com.diffplug.common.base.Consumers;
import com.diffplug.common.base.Errors;
import com.diffplug.common.base.StringPrinter;
Expand Down
28 changes: 25 additions & 3 deletions src/test/java/com/diffplug/gradle/CleanedAssert.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 DiffPlug
* Copyright (C) 2021-2025 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,8 +15,9 @@
*/
package com.diffplug.gradle;


import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.junit.Assert;

Expand All @@ -26,7 +27,28 @@ public static void assumeJre8() {
}

public static void xml(String expected, String actual) {
Assert.assertEquals(trim(expected), trim(actual));
Assert.assertEquals(normalizeXml(trim(expected)), normalizeXml(trim(actual)));
}

private static String normalizeXml(String xml) {
Pattern tagPattern = Pattern.compile("<([^\\s/>]+)([^>]*)>");
Matcher matcher = tagPattern.matcher(xml);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String tagName = matcher.group(1);
String remainder = matcher.group(2).trim();
boolean selfClosing = remainder.endsWith("/");
if (selfClosing) {
remainder = remainder.substring(0, remainder.length() - 1).trim();
}
String[] attrArray = remainder.isEmpty() ? new String[0] : remainder.split("\\s+");
Arrays.sort(attrArray);
String attrs = (attrArray.length > 0 ? " " + String.join(" ", attrArray) : "");
String replacement = "<" + tagName + attrs + (selfClosing ? "/>" : ">");
matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(sb);
return sb.toString();
}

private static String trim(String input) {
Expand Down