Skip to content

Commit 4aa562a

Browse files
committed
refactor: extracted build state from Project
The `Project` class now does not contain any build-related code anymore, this has all been moved to `BuildContext`. So a `Builder` can be given a `Project` and a `BuildContext` where the former represents all the inputs that go into the build and the latter represents all the outputs (and any temporary/intermediate state).
1 parent cec649c commit 4aa562a

33 files changed

Lines changed: 576 additions & 388 deletions

src/main/java/dev/jbang/cli/App.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import dev.jbang.dependencies.DependencyUtil;
2727
import dev.jbang.net.JdkManager;
2828
import dev.jbang.net.JdkProvider;
29+
import dev.jbang.source.BuildContext;
2930
import dev.jbang.source.Project;
3031
import dev.jbang.source.ProjectBuilder;
3132
import dev.jbang.util.CommandBuffer;
@@ -117,7 +118,7 @@ public static boolean install(String name, String scriptRef, boolean force, bool
117118
&& !prj.getResourceRef().isURL()) {
118119
scriptRef = prj.getResourceRef().getFile().toAbsolutePath().toString();
119120
}
120-
prj.builder().build();
121+
prj.builder(BuildContext.forProject(prj)).build();
121122
installScripts(name, scriptRef, benative);
122123
Util.infoMsg("Command installed: " + name);
123124
return true;

src/main/java/dev/jbang/cli/BaseBuildCommand.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ ProjectBuilder createProjectBuilder() {
4747
.mainClass(buildMixin.main)
4848
.compileOptions(buildMixin.compileOptions)
4949
.nativeImage(nativeMixin.nativeImage)
50-
.nativeOptions(nativeMixin.nativeOptions)
51-
.buildDir(buildDir);
50+
.nativeOptions(nativeMixin.nativeOptions);
5251
}
5352
}

src/main/java/dev/jbang/cli/Build.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import java.io.IOException;
44

5+
import dev.jbang.source.BuildContext;
6+
import dev.jbang.source.Project;
57
import dev.jbang.source.ProjectBuilder;
68

79
import picocli.CommandLine.Command;
@@ -15,7 +17,8 @@ public Integer doCall() throws IOException {
1517
jdkProvidersMixin.initJdkProviders();
1618

1719
ProjectBuilder pb = createProjectBuilder();
18-
pb.build(scriptMixin.scriptOrFile).builder().build();
20+
Project prj = pb.build(scriptMixin.scriptOrFile);
21+
prj.builder(BuildContext.forProject(prj, buildDir)).build();
1922

2023
return EXIT_OK;
2124
}

src/main/java/dev/jbang/cli/Export.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import dev.jbang.Settings;
2222
import dev.jbang.dependencies.ArtifactInfo;
2323
import dev.jbang.dependencies.MavenCoordinate;
24+
import dev.jbang.source.BuildContext;
2425
import dev.jbang.source.Project;
2526
import dev.jbang.source.ProjectBuilder;
2627
import dev.jbang.util.JarUtil;
@@ -82,11 +83,13 @@ protected Path createManifest(String newPath) throws IOException {
8283
public Integer doCall() throws IOException {
8384
exportMixin.validate();
8485
ProjectBuilder pb = createProjectBuilder(exportMixin);
85-
Project prj = pb.build(exportMixin.scriptMixin.scriptOrFile).builder().build();
86-
return apply(prj, pb);
86+
Project prj = pb.build(exportMixin.scriptMixin.scriptOrFile);
87+
BuildContext ctx = BuildContext.forProject(prj);
88+
prj.builder(ctx).build();
89+
return apply(prj, ctx);
8790
}
8891

89-
abstract int apply(Project prj, ProjectBuilder pb) throws IOException;
92+
abstract int apply(Project prj, BuildContext ctx) throws IOException;
9093

9194
protected ProjectBuilder createProjectBuilder(ExportMixin exportMixin) {
9295
return ProjectBuilder
@@ -118,9 +121,9 @@ Path getJarOutputPath() {
118121
class ExportLocal extends BaseExportCommand {
119122

120123
@Override
121-
int apply(Project prj, ProjectBuilder pb) throws IOException {
124+
int apply(Project prj, BuildContext ctx) throws IOException {
122125
// Copy the JAR
123-
Path source = prj.getJarFile();
126+
Path source = ctx.getJarFile();
124127
Path outputPath = getJarOutputPath();
125128
if (outputPath.toFile().exists()) {
126129
if (exportMixin.force) {
@@ -155,9 +158,9 @@ class ExportPortable extends BaseExportCommand {
155158
public static final String LIB = "lib";
156159

157160
@Override
158-
int apply(Project prj, ProjectBuilder pb) throws IOException {
161+
int apply(Project prj, BuildContext ctx) throws IOException {
159162
// Copy the JAR
160-
Path source = prj.getJarFile();
163+
Path source = ctx.getJarFile();
161164
Path outputPath = getJarOutputPath();
162165
if (outputPath.toFile().exists()) {
163166
if (exportMixin.force) {
@@ -205,14 +208,14 @@ class ExportMavenPublish extends BaseExportCommand {
205208
String version;
206209

207210
@Override
208-
int apply(Project prj, ProjectBuilder pb) throws IOException {
211+
int apply(Project prj, BuildContext ctx) throws IOException {
209212
Path outputPath = exportMixin.outputFile;
210213

211214
if (outputPath == null) {
212215
outputPath = Settings.getLocalMavenRepo();
213216
}
214217
// Copy the JAR
215-
Path source = prj.getJarFile();
218+
Path source = ctx.getJarFile();
216219

217220
if (!outputPath.toFile().isDirectory()) {
218221
if (outputPath.toFile().exists()) {
@@ -306,9 +309,9 @@ int apply(Project prj, ProjectBuilder pb) throws IOException {
306309
class ExportNative extends BaseExportCommand {
307310

308311
@Override
309-
int apply(Project prj, ProjectBuilder pb) throws IOException {
312+
int apply(Project prj, BuildContext ctx) throws IOException {
310313
// Copy the native binary
311-
Path source = prj.getNativeImageFile();
314+
Path source = ctx.getNativeImageFile();
312315
Path outputPath = getNativeOutputPath();
313316
if (outputPath.toFile().exists()) {
314317
if (exportMixin.force) {
@@ -345,9 +348,9 @@ Path getNativeOutputPath() {
345348
class ExportFatjar extends BaseExportCommand {
346349

347350
@Override
348-
int apply(Project prj, ProjectBuilder pb) throws IOException {
351+
int apply(Project prj, BuildContext ctx) throws IOException {
349352
// Copy the native binary
350-
Path source = prj.getJarFile();
353+
Path source = ctx.getJarFile();
351354
Path outputPath = getFatjarOutputPath();
352355
if (outputPath.toFile().exists()) {
353356
if (exportMixin.force) {

src/main/java/dev/jbang/cli/Info.java

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -87,51 +87,51 @@ static class ScriptInfo {
8787
String description;
8888
String gav;
8989

90-
public ScriptInfo(Project prj, ProjectBuilder pb) {
90+
public ScriptInfo(Project prj, BuildContext ctx) {
9191
originalResource = prj.getResourceRef().getOriginalResource();
9292

9393
if (scripts.add(originalResource)) {
9494
backingResource = prj.getResourceRef().getFile().toString();
9595

9696
init(prj);
9797

98-
if (pb != null) {
99-
applicationJar = prj.getJarFile() == null ? null : prj.getJarFile().toAbsolutePath().toString();
100-
nativeImage = prj.getNativeImageFile() == null || !Files.exists(prj.getNativeImageFile()) ? null
101-
: prj.getNativeImageFile().toAbsolutePath().toString();
102-
mainClass = prj.getMainClass();
103-
requestedJavaVersion = prj.getJavaVersion();
104-
105-
try {
106-
JdkProvider.Jdk jdk = JdkManager.getJdk(requestedJavaVersion, false);
107-
if (jdk != null && jdk.isInstalled()) {
108-
availableJdkPath = jdk.getHome().toString();
109-
}
110-
} catch (ExitException e) {
111-
// Ignore
98+
applicationJar = ctx.getJarFile() == null ? null
99+
: ctx.getJarFile().toAbsolutePath().toString();
100+
nativeImage = ctx.getNativeImageFile() == null
101+
|| !Files.exists(ctx.getNativeImageFile()) ? null
102+
: ctx.getNativeImageFile().toAbsolutePath().toString();
103+
mainClass = prj.getMainClass();
104+
requestedJavaVersion = prj.getJavaVersion();
105+
106+
try {
107+
JdkProvider.Jdk jdk = JdkManager.getJdk(requestedJavaVersion, false);
108+
if (jdk != null && jdk.isInstalled()) {
109+
availableJdkPath = jdk.getHome().toString();
112110
}
111+
} catch (ExitException e) {
112+
// Ignore
113+
}
113114

114-
String cp = prj.resolveClassPath().getClassPath();
115-
if (cp.isEmpty()) {
116-
resolvedDependencies = Collections.emptyList();
117-
} else {
118-
resolvedDependencies = Arrays.asList(cp.split(CP_SEPARATOR));
119-
}
115+
String cp = prj.resolveClassPath().getClassPath();
116+
if (cp.isEmpty()) {
117+
resolvedDependencies = Collections.emptyList();
118+
} else {
119+
resolvedDependencies = Arrays.asList(cp.split(CP_SEPARATOR));
120+
}
120121

121-
if (prj.getJavaVersion() != null) {
122-
javaVersion = Integer.toString(JavaUtil.parseJavaVersion(prj.getJavaVersion()));
123-
}
122+
if (prj.getJavaVersion() != null) {
123+
javaVersion = Integer.toString(JavaUtil.parseJavaVersion(prj.getJavaVersion()));
124+
}
124125

125-
List<String> opts = prj.getRuntimeOptions();
126-
if (!opts.isEmpty()) {
127-
runtimeOptions = opts;
128-
}
126+
List<String> opts = prj.getRuntimeOptions();
127+
if (!opts.isEmpty()) {
128+
runtimeOptions = opts;
129+
}
129130

130-
if (prj.getJarFile() != null && Files.exists(prj.getJarFile())) {
131-
Project jarProject = ProjectBuilder.create().build(prj.getJarFile());
132-
mainClass = jarProject.getMainClass();
133-
gav = jarProject.getGav().orElse(gav);
134-
}
131+
if (ctx.getJarFile() != null && Files.exists(ctx.getJarFile())) {
132+
Project jarProject = ProjectBuilder.create().build(ctx.getJarFile());
133+
mainClass = jarProject.getMainClass();
134+
gav = jarProject.getGav().orElse(gav);
135135
}
136136
}
137137
}
@@ -195,7 +195,7 @@ ScriptInfo getInfo() {
195195

196196
scripts = new HashSet<>();
197197

198-
return new ScriptInfo(prj, pb);
198+
return new ScriptInfo(prj, BuildContext.forProject(prj, buildDir));
199199
}
200200

201201
ProjectBuilder createProjectBuilder() {
@@ -207,8 +207,7 @@ ProjectBuilder createProjectBuilder() {
207207
.additionalSources(scriptMixin.sources)
208208
.additionalResources(scriptMixin.resources)
209209
.forceType(scriptMixin.forceType)
210-
.catalog(scriptMixin.catalog)
211-
.buildDir(buildDir);
210+
.catalog(scriptMixin.catalog);
212211
}
213212

214213
}

src/main/java/dev/jbang/cli/Run.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.regex.Matcher;
1010
import java.util.regex.Pattern;
1111

12+
import dev.jbang.source.BuildContext;
1213
import dev.jbang.source.Project;
1314
import dev.jbang.source.ProjectBuilder;
1415
import dev.jbang.source.Source;
@@ -102,15 +103,16 @@ public Integer doCall() throws IOException {
102103
}
103104
}
104105

105-
prj.builder().build();
106+
BuildContext ctx = BuildContext.forProject(prj, buildDir);
107+
prj.builder(ctx).build();
106108

107109
if (Boolean.TRUE.equals(nativeMixin.nativeImage)
108110
&& (scriptMixin.forceType == Source.Type.jshell || prj.isJShell())) {
109111
warn(".jsh cannot be used with --native thus ignoring --native.");
110112
pb.nativeImage(false);
111113
}
112114

113-
String cmdline = prj.cmdGenerator().generate();
115+
String cmdline = prj.cmdGenerator(ctx).generate();
114116
debug("run: " + cmdline);
115117
out.println(cmdline);
116118

@@ -133,8 +135,7 @@ ProjectBuilder createProjectBuilder() {
133135
String javaAgentOptions = agentOption.getValue();
134136
ProjectBuilder apb = super.createProjectBuilder();
135137
Project aprj = apb.build(javaAgent);
136-
aprj.addRuntimeOption("-javaagent:" + aprj.getJarFile()
137-
+ (javaAgentOptions != null ? "=" + javaAgentOptions : ""));
138+
aprj.addRuntimeOption("-javaagent:$JAR$" + (javaAgentOptions != null ? "=" + javaAgentOptions : ""));
138139
pb.addJavaAgent(aprj);
139140
}
140141
}

src/main/java/dev/jbang/source/AppBuilder.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@
2020
*/
2121
public abstract class AppBuilder implements Builder<Project> {
2222
protected final Project project;
23+
protected final BuildContext ctx;
2324

2425
protected boolean fresh = Util.isFresh();
2526
protected Util.Shell shell = Util.getShell();
2627

27-
public AppBuilder(Project project) {
28+
public AppBuilder(Project project, BuildContext ctx) {
2829
this.project = project;
30+
this.ctx = ctx;
2931
}
3032

3133
public AppBuilder setFresh(boolean fresh) {
@@ -40,8 +42,8 @@ public AppBuilder setShell(Util.Shell shell) {
4042

4143
@Override
4244
public Project build() throws IOException {
43-
Path outjar = project.getJarFile();
44-
boolean nativeBuildRequired = project.isNativeImage() && !Files.exists(project.getNativeImageFile());
45+
Path outjar = ctx.getJarFile();
46+
boolean nativeBuildRequired = project.isNativeImage() && !Files.exists(ctx.getNativeImageFile());
4547
IntegrationResult integrationResult = new IntegrationResult(null, null, null);
4648
String requestedJavaVersion = project.getJavaVersion();
4749
// always build the jar for native mode
@@ -57,7 +59,7 @@ public Project build() throws IOException {
5759
} else if (Files.isReadable(outjar)) {
5860
Project jarProject = ProjectBuilder.create().build(outjar);
5961
// We already have a Jar, check if we can still use it
60-
if (!project.isUpToDate()) {
62+
if (!ctx.isUpToDate()) {
6163
Util.verboseMsg("Building as previous build jar found but it or its dependencies not up-to-date.");
6264
} else if (JavaUtil.javaVersion(requestedJavaVersion) < JavaUtil.minRequestedVersion(
6365
jarProject.getJavaVersion())) {
@@ -69,7 +71,7 @@ public Project build() throws IOException {
6971
if (project.getMainClass() == null) {
7072
project.setMainClass(jarProject.getMainClass());
7173
}
72-
Util.verboseMsg("No build required. Reusing jar from " + project.getJarFile());
74+
Util.verboseMsg("No build required. Reusing jar from " + ctx.getJarFile());
7375
buildRequired = false;
7476
}
7577
} else {
@@ -78,7 +80,7 @@ public Project build() throws IOException {
7880

7981
if (buildRequired) {
8082
// set up temporary folder for compilation
81-
Path compileDir = project.getBuildDir();
83+
Path compileDir = ctx.getCompileDir();
8284
Util.deletePath(compileDir, true);
8385
compileDir.toFile().mkdirs();
8486
// do the actual building
@@ -96,14 +98,15 @@ public Project build() throws IOException {
9698

9799
if (nativeBuildRequired) {
98100
if (integrationResult.nativeImagePath != null) {
99-
Files.move(integrationResult.nativeImagePath, project.getNativeImageFile());
101+
Files.move(integrationResult.nativeImagePath, ctx.getNativeImageFile());
100102
} else {
101103
getNativeBuildStep().build();
102104
}
103105
}
104106

105107
for (Project aprj : project.getJavaAgents()) {
106-
aprj.builder().build();
108+
BuildContext actx = ctx.forSubProject(aprj, "agents");
109+
aprj.builder(actx).build();
107110
}
108111

109112
return project;
@@ -118,10 +121,10 @@ public static boolean keepClasses() {
118121
protected abstract Builder<IntegrationResult> getIntegrationBuildStep();
119122

120123
protected Builder<Project> getJarBuildStep() {
121-
return new JarBuildStep(project);
124+
return new JarBuildStep(project, ctx);
122125
}
123126

124127
protected Builder<Project> getNativeBuildStep() {
125-
return new NativeBuildStep(project);
128+
return new NativeBuildStep(project, ctx);
126129
}
127130
}

0 commit comments

Comments
 (0)