Skip to content

Commit 39d4fc5

Browse files
committed
feat: Move p2 provisioning outside EquoBasedStepBuilder, as first citizen
1 parent 8e776ec commit 39d4fc5

25 files changed

Lines changed: 300 additions & 78 deletions

lib-extra/src/main/java/com/diffplug/spotless/extra/EquoBasedStepBuilder.java

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2025 DiffPlug
2+
* Copyright 2016-2026 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@
1818
import static java.util.stream.Collectors.toMap;
1919

2020
import java.io.File;
21-
import java.io.IOException;
2221
import java.io.Serializable;
2322
import java.util.ArrayList;
2423
import java.util.Collection;
@@ -38,19 +37,15 @@
3837
import com.diffplug.spotless.Provisioner;
3938
import com.diffplug.spotless.SerializedFunction;
4039

41-
import dev.equo.solstice.NestedJars;
42-
import dev.equo.solstice.p2.CacheLocations;
43-
import dev.equo.solstice.p2.P2ClientCache;
4440
import dev.equo.solstice.p2.P2Model;
45-
import dev.equo.solstice.p2.P2QueryCache;
46-
import dev.equo.solstice.p2.P2QueryResult;
4741

4842
/**
4943
* Generic Eclipse based formatter step {@link State} builder.
5044
*/
5145
public abstract class EquoBasedStepBuilder {
5246
private final String formatterName;
5347
private final Provisioner mavenProvisioner;
48+
private final P2Provisioner p2Provisioner;
5449
private final SerializedFunction<State, FormatterFunc> stateToFormatter;
5550
private final ImmutableMap.Builder<String, String> stepProperties;
5651
private String formatterVersion;
@@ -64,12 +59,14 @@ public abstract class EquoBasedStepBuilder {
6459
protected EquoBasedStepBuilder(
6560
String formatterName,
6661
Provisioner mavenProvisioner,
62+
P2Provisioner p2Provisioner,
6763
@Nullable String defaultVersion,
6864
SerializedFunction<State, FormatterFunc> stateToFormatter,
6965
ImmutableMap.Builder<String, String> stepProperties) {
7066

7167
this.formatterName = formatterName;
7268
this.mavenProvisioner = mavenProvisioner;
69+
this.p2Provisioner = p2Provisioner;
7370
this.formatterVersion = defaultVersion;
7471
this.stateToFormatter = stateToFormatter;
7572
this.stepProperties = stepProperties;
@@ -125,25 +122,9 @@ protected void addPlatformRepo(P2Model model, String version) {
125122
/** Returns the FormatterStep (whose state will be calculated lazily). */
126123
public FormatterStep build() {
127124
var roundtrippableState = new EquoStep(formatterVersion, settingProperties, settingXml, FileSignature.promise(settingsFiles), JarState.promise(() -> {
128-
P2QueryResult query;
129-
try {
130-
if (cacheDirectory != null) {
131-
CacheLocations.override_p2data = cacheDirectory.toPath().resolve("dev/equo/p2-data").toFile();
132-
}
133-
query = createModelWithMirrors().query(P2ClientCache.PREFER_OFFLINE, P2QueryCache.ALLOW);
134-
} catch (Exception x) {
135-
throw new IOException("Failed to load " + formatterName + ": " + x, x);
136-
}
137-
var classpath = new ArrayList<File>();
138-
var mavenDeps = new ArrayList<String>();
139-
mavenDeps.add("dev.equo.ide:solstice:1.8.1");
140-
mavenDeps.add("com.diffplug.durian:durian-swt.os:4.3.1");
141-
mavenDeps.addAll(query.getJarsOnMavenCentral());
142-
classpath.addAll(mavenProvisioner.provisionWithTransitives(false, mavenDeps));
143-
classpath.addAll(query.getJarsNotOnMavenCentral());
144-
for (var nested : NestedJars.inFiles(query.getJarsNotOnMavenCentral()).extractAllNestedJars()) {
145-
classpath.add(nested.getValue());
146-
}
125+
P2Model model = createModelWithMirrors();
126+
P2ModelWrapper modelWrapper = P2ModelWrapper.wrap(model);
127+
List<File> classpath = p2Provisioner.provisionP2Dependencies(modelWrapper, mavenProvisioner, cacheDirectory);
147128
return JarState.preserveOrder(classpath);
148129
}), stepProperties.build());
149130
return FormatterStep.create(formatterName, roundtrippableState, EquoStep::state, stateToFormatter);
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2016-2026 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.extra;
17+
18+
import java.util.Collection;
19+
import java.util.Set;
20+
21+
import dev.equo.solstice.p2.P2Model;
22+
23+
/**
24+
* Wrapper for P2Model that exposes only the data needed for caching,
25+
* without leaking the P2Model type to consumers.
26+
*/
27+
public final class P2ModelWrapper {
28+
private final P2Model model;
29+
30+
private P2ModelWrapper(P2Model model) {
31+
this.model = model;
32+
}
33+
34+
public static P2ModelWrapper wrap(P2Model model) {
35+
return new P2ModelWrapper(model);
36+
}
37+
38+
public P2Model unwrap() {
39+
return model;
40+
}
41+
42+
public Collection<String> getP2Repos() {
43+
return model.getP2repo();
44+
}
45+
46+
public Collection<String> getInstallList() {
47+
return model.getInstall();
48+
}
49+
50+
public Set<String> getFilterNames() {
51+
return model.getFilters().keySet();
52+
}
53+
54+
public Collection<String> getPureMaven() {
55+
return model.getPureMaven();
56+
}
57+
58+
public boolean isUseMavenCentral() {
59+
return model.useMavenCentral;
60+
}
61+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2016-2026 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.extra;
17+
18+
import java.io.File;
19+
import java.io.IOException;
20+
import java.util.ArrayList;
21+
import java.util.List;
22+
23+
import javax.annotation.Nullable;
24+
25+
import com.diffplug.spotless.Provisioner;
26+
27+
import dev.equo.solstice.NestedJars;
28+
import dev.equo.solstice.p2.CacheLocations;
29+
import dev.equo.solstice.p2.P2ClientCache;
30+
import dev.equo.solstice.p2.P2Model;
31+
import dev.equo.solstice.p2.P2QueryCache;
32+
import dev.equo.solstice.p2.P2QueryResult;
33+
34+
/**
35+
* Provisions dependencies from Eclipse P2 repositories.
36+
* Similar to {@link Provisioner} but for P2/OSGi bundles.
37+
*/
38+
@FunctionalInterface
39+
public interface P2Provisioner {
40+
/**
41+
* Resolves P2 dependencies and returns the classpath.
42+
*
43+
* @param modelWrapper wrapper around P2Model describing repositories and plugins to install
44+
* @param mavenProvisioner provisioner for Maven dependencies (some P2 bundles are on Maven Central)
45+
* @param cacheDirectory optional cache directory override
46+
* @return ordered list of JAR files forming the classpath
47+
*/
48+
List<File> provisionP2Dependencies(
49+
P2ModelWrapper modelWrapper,
50+
Provisioner mavenProvisioner,
51+
@Nullable File cacheDirectory) throws IOException;
52+
53+
/** Creates a non-caching P2Provisioner for simple use cases. */
54+
static P2Provisioner createDefault() {
55+
return (modelWrapper, mavenProvisioner, cacheDirectory) -> {
56+
try {
57+
if (cacheDirectory != null) {
58+
CacheLocations.override_p2data = cacheDirectory.toPath().resolve("dev/equo/p2-data").toFile();
59+
}
60+
P2Model model = modelWrapper.unwrap();
61+
P2QueryResult query = model.query(P2ClientCache.PREFER_OFFLINE, P2QueryCache.ALLOW);
62+
var classpath = new ArrayList<File>();
63+
var mavenDeps = new ArrayList<String>();
64+
mavenDeps.add("dev.equo.ide:solstice:1.8.1");
65+
mavenDeps.add("com.diffplug.durian:durian-swt.os:4.3.1");
66+
mavenDeps.addAll(query.getJarsOnMavenCentral());
67+
classpath.addAll(mavenProvisioner.provisionWithTransitives(false, mavenDeps));
68+
classpath.addAll(query.getJarsNotOnMavenCentral());
69+
for (var nested : NestedJars.inFiles(query.getJarsNotOnMavenCentral()).extractAllNestedJars()) {
70+
classpath.add(nested.getValue());
71+
}
72+
return classpath;
73+
} catch (Exception e) {
74+
throw new IOException("Failed to provision P2 dependencies", e);
75+
}
76+
};
77+
}
78+
}

lib-extra/src/main/java/com/diffplug/spotless/extra/cpp/EclipseCdtFormatterStep.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2025 DiffPlug
2+
* Copyright 2016-2026 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
2323
import com.diffplug.spotless.Jvm;
2424
import com.diffplug.spotless.Provisioner;
2525
import com.diffplug.spotless.extra.EquoBasedStepBuilder;
26+
import com.diffplug.spotless.extra.P2Provisioner;
2627

2728
import dev.equo.solstice.p2.P2Model;
2829

@@ -45,8 +46,8 @@ public static String defaultVersion() {
4546
}
4647

4748
/** Provides default configuration */
48-
public static EquoBasedStepBuilder createBuilder(Provisioner provisioner) {
49-
return new EquoBasedStepBuilder(NAME, provisioner, defaultVersion(), EclipseCdtFormatterStep::apply, ImmutableMap.builder()) {
49+
public static EquoBasedStepBuilder createBuilder(Provisioner provisioner, P2Provisioner p2Provisioner) {
50+
return new EquoBasedStepBuilder(NAME, provisioner, p2Provisioner, defaultVersion(), EclipseCdtFormatterStep::apply, ImmutableMap.builder()) {
5051
@Override
5152
protected P2Model model(String version) {
5253
var model = new P2Model();

lib-extra/src/main/java/com/diffplug/spotless/extra/groovy/GrEclipseFormatterStep.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2025 DiffPlug
2+
* Copyright 2016-2026 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
2424
import com.diffplug.spotless.Jvm;
2525
import com.diffplug.spotless.Provisioner;
2626
import com.diffplug.spotless.extra.EquoBasedStepBuilder;
27+
import com.diffplug.spotless.extra.P2Provisioner;
2728

2829
import dev.equo.solstice.p2.P2Model;
2930

@@ -39,8 +40,8 @@ public static String defaultVersion() {
3940
return JVM_SUPPORT.getRecommendedFormatterVersion();
4041
}
4142

42-
public static EquoBasedStepBuilder createBuilder(Provisioner provisioner) {
43-
return new EquoBasedStepBuilder(NAME, provisioner, defaultVersion(), GrEclipseFormatterStep::apply, ImmutableMap.builder()) {
43+
public static EquoBasedStepBuilder createBuilder(Provisioner provisioner, P2Provisioner p2Provisioner) {
44+
return new EquoBasedStepBuilder(NAME, provisioner, p2Provisioner, defaultVersion(), GrEclipseFormatterStep::apply, ImmutableMap.builder()) {
4445
@Override
4546
protected P2Model model(String version) {
4647
if (!version.startsWith("4.")) {

lib-extra/src/main/java/com/diffplug/spotless/extra/java/EclipseJdtFormatterStep.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2025 DiffPlug
2+
* Copyright 2016-2026 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
2525
import com.diffplug.spotless.Provisioner;
2626
import com.diffplug.spotless.SerializedFunction;
2727
import com.diffplug.spotless.extra.EquoBasedStepBuilder;
28+
import com.diffplug.spotless.extra.P2Provisioner;
2829

2930
import dev.equo.solstice.p2.P2Model;
3031

@@ -40,8 +41,8 @@ public static String defaultVersion() {
4041
return JVM_SUPPORT.getRecommendedFormatterVersion();
4142
}
4243

43-
public static EclipseJdtFormatterStep.Builder createBuilder(Provisioner provisioner) {
44-
return new EclipseJdtFormatterStep.Builder(NAME, provisioner, defaultVersion(), EclipseJdtFormatterStep::apply, ImmutableMap.builder());
44+
public static EclipseJdtFormatterStep.Builder createBuilder(Provisioner provisioner, P2Provisioner p2Provisioner) {
45+
return new EclipseJdtFormatterStep.Builder(NAME, provisioner, p2Provisioner, defaultVersion(), EclipseJdtFormatterStep::apply, ImmutableMap.builder());
4546
}
4647

4748
private static FormatterFunc apply(EquoBasedStepBuilder.State state) throws Exception {
@@ -59,10 +60,11 @@ public static class Builder extends EquoBasedStepBuilder {
5960
Builder(
6061
String formatterName,
6162
Provisioner mavenProvisioner,
63+
P2Provisioner p2Provisioner,
6264
String defaultVersion,
6365
SerializedFunction<State, FormatterFunc> stateToFormatter,
6466
ImmutableMap.Builder<String, String> stepProperties) {
65-
super(formatterName, mavenProvisioner, defaultVersion, stateToFormatter, stepProperties);
67+
super(formatterName, mavenProvisioner, p2Provisioner, defaultVersion, stateToFormatter, stepProperties);
6668
this.stepProperties = stepProperties;
6769
}
6870

lib-extra/src/test/java/com/diffplug/spotless/extra/cpp/EclipseCdtFormatterStepTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2025 DiffPlug
2+
* Copyright 2016-2026 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,11 +21,12 @@
2121
import org.junit.jupiter.params.provider.MethodSource;
2222

2323
import com.diffplug.spotless.TestProvisioner;
24+
import com.diffplug.spotless.extra.P2Provisioner;
2425
import com.diffplug.spotless.extra.eclipse.EquoResourceHarness;
2526

2627
class EclipseCdtFormatterStepTest extends EquoResourceHarness {
2728
public EclipseCdtFormatterStepTest() {
28-
super(EclipseCdtFormatterStep.createBuilder(TestProvisioner.mavenCentral()));
29+
super(EclipseCdtFormatterStep.createBuilder(TestProvisioner.mavenCentral(), P2Provisioner.createDefault()));
2930
}
3031

3132
@ParameterizedTest

lib-extra/src/test/java/com/diffplug/spotless/extra/groovy/GrEclipseFormatterStepSpecialCaseTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2025 DiffPlug
2+
* Copyright 2023-2026 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
2020

2121
import com.diffplug.spotless.StepHarness;
2222
import com.diffplug.spotless.TestProvisioner;
23+
import com.diffplug.spotless.extra.P2Provisioner;
2324

2425
public class GrEclipseFormatterStepSpecialCaseTest {
2526
/**
@@ -30,13 +31,13 @@ public class GrEclipseFormatterStepSpecialCaseTest {
3031
*/
3132
@Test
3233
public void issue_1657() {
33-
Assertions.assertThrows(RuntimeException.class, () -> StepHarness.forStep(GrEclipseFormatterStep.createBuilder(TestProvisioner.mavenCentral()).build())
34+
Assertions.assertThrows(RuntimeException.class, () -> StepHarness.forStep(GrEclipseFormatterStep.createBuilder(TestProvisioner.mavenCentral(), P2Provisioner.createDefault()).build())
3435
.testResourceUnaffected("groovy/greclipse/format/SomeClass.test"));
3536
}
3637

3738
@Test
3839
public void issue_1657_fixed() {
39-
StepHarness.forStep(GrEclipseFormatterStep.createBuilder(TestProvisioner.mavenCentral()).build())
40+
StepHarness.forStep(GrEclipseFormatterStep.createBuilder(TestProvisioner.mavenCentral(), P2Provisioner.createDefault()).build())
4041
.testResourceUnaffected("groovy/greclipse/format/SomeClass.fixed");
4142
}
4243
}

lib-extra/src/test/java/com/diffplug/spotless/extra/groovy/GrEclipseFormatterStepTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2025 DiffPlug
2+
* Copyright 2016-2026 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,14 +21,15 @@
2121
import org.junit.jupiter.params.provider.MethodSource;
2222

2323
import com.diffplug.spotless.TestProvisioner;
24+
import com.diffplug.spotless.extra.P2Provisioner;
2425
import com.diffplug.spotless.extra.eclipse.EquoResourceHarness;
2526

2627
public class GrEclipseFormatterStepTest extends EquoResourceHarness {
2728
private static final String INPUT = "class F{ def m(){} }";
2829
private static final String EXPECTED = "class F{\n\tdef m(){}\n}";
2930

3031
public GrEclipseFormatterStepTest() {
31-
super(GrEclipseFormatterStep.createBuilder(TestProvisioner.mavenCentral()));
32+
super(GrEclipseFormatterStep.createBuilder(TestProvisioner.mavenCentral(), P2Provisioner.createDefault()));
3233
}
3334

3435
@ParameterizedTest

0 commit comments

Comments
 (0)