Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import ca.weblite.jdeploy.JDeploy;
import ca.weblite.jdeploy.app.AppInfo;
import ca.weblite.jdeploy.app.JVMSpecification;
import ca.weblite.jdeploy.models.CommandSpecParser;
import ca.weblite.jdeploy.app.permissions.PermissionRequest;
import ca.weblite.jdeploy.app.permissions.PermissionRequestService;
import ca.weblite.jdeploy.appbundler.*;
Expand Down Expand Up @@ -896,6 +897,10 @@ private void loadAppInfo(PackagingContext context, AppInfo appInfo) throws IOExc
appInfo.setJdeployRegistryUrl(packagingConfig.getJdeployRegistry());
}

// Parse CLI commands from jdeploy config for bundler use (e.g., embedded LaunchAgent plists)
JSONObject jdeployJson = new JSONObject(context.mj());
appInfo.setCommands(CommandSpecParser.parseCommands(jdeployJson));

String jarPath = context.getString("jar", null);
if (jarPath != null) {
JarFile jarFile = new JarFile(new File(context.directory, toNativePath(jarPath)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import ca.weblite.tools.io.IOUtil;
import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.json.JSONObject;

import javax.inject.Inject;
import javax.inject.Singleton;
Expand Down Expand Up @@ -106,6 +107,7 @@ public File generate(ProjectGeneratorRequest request) throws Exception {
}

updateFilesInDirectory(projectDir, request);
updatePackageJsonWithGithubSettings(projectDir, request);

if (mavenWrapperInjector.isMavenProject(projectDir.getPath())) {
mavenWrapperInjector.installIntoProject(projectDir.getPath());
Expand Down Expand Up @@ -316,6 +318,35 @@ private void generateReleasesProject(
setReleasesRepositoryInWorkflow(projectDirectory, releasesRepository);
}

private void updatePackageJsonWithGithubSettings(File projectDir, ProjectGeneratorRequest request) throws IOException {
if (request.getGithubRepository() == null) {
return;
}
File packageJson = new File(projectDir, "package.json");
if (!packageJson.exists()) {
return;
}

String content = FileUtils.readFileToString(packageJson, "UTF-8");
JSONObject json = new JSONObject(content);

json.put("repository", GITHUB_URL + request.getGithubRepository());

JSONObject jdeploy = json.optJSONObject("jdeploy");
if (jdeploy == null) {
jdeploy = new JSONObject();
json.put("jdeploy", jdeploy);
}

JSONObject github = new JSONObject();
github.put("repository", request.getGithubRepository());
github.put("releases_repository", getReleasesRepository(request));
github.put("releases_url", getReleasesUrl(request));
jdeploy.put("github", github);

FileUtils.writeStringToFile(packageJson, json.toString(2), "UTF-8");
}

private String getReleasesRepository(ProjectGeneratorRequest request) {
return request.getGithubRepository() + "-releases";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ private void loadNPMPackageInfo() throws IOException {
appInfo().setDescription("Desktop application");
}

appInfo().setCommands(npmPackageVersion().getCommands());

for (DocumentTypeAssociation documentTypeAssociation : npmPackageVersion().getDocumentTypeAssociations()) {
if (documentTypeAssociation.isDirectory()) {
// Handle directory association - check for default directory icon if none specified
Expand Down
15 changes: 14 additions & 1 deletion shared/src/main/java/ca/weblite/jdeploy/app/AppInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package ca.weblite.jdeploy.app;

import ca.weblite.jdeploy.app.permissions.PermissionRequest;
import ca.weblite.jdeploy.models.CommandSpec;
import ca.weblite.jdeploy.models.DocumentTypeAssociation;

import ca.weblite.tools.platform.Platform;
Expand Down Expand Up @@ -1433,6 +1434,7 @@ public AppInfo copy() {
out.requireRunAsAdmin = requireRunAsAdmin;
out.codeSignSettings = codeSignSettings;
out.macAppBundleId = macAppBundleId;
out.commands = commands;
if (permissions != null) {
//out.permissions = new ArrayList<>();
for (Permission p : permissions) {
Expand Down Expand Up @@ -1585,7 +1587,8 @@ private boolean equalsImpl(AppInfo o) {
windowsJdeployHome, o.windowsJdeployHome,
linuxJdeployHome, o.linuxJdeployHome,
permissionRequests, o.permissionRequests,
directoryAssociation, o.directoryAssociation
directoryAssociation, o.directoryAssociation,
commands, o.commands

});
}
Expand Down Expand Up @@ -1629,6 +1632,16 @@ public static enum CodeSignSettings {

private String macAppBundleId;

private List<CommandSpec> commands = Collections.emptyList();

public List<CommandSpec> getCommands() {
return commands;
}

public void setCommands(List<CommandSpec> commands) {
this.commands = commands != null ? Collections.unmodifiableList(new ArrayList<>(commands)) : Collections.emptyList();
}

public String getLauncherVersion() {
return launcherVersion;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

package ca.weblite.jdeploy.appbundler;

import ca.weblite.jdeploy.models.CommandSpec;

import java.io.File;
import java.security.cert.Certificate;
import java.util.*;
Expand Down Expand Up @@ -68,6 +70,8 @@ public class AppDescription {
*/
private String initialAppVersion;

private List<CommandSpec> commands = Collections.emptyList();

private Map<String,String> macUsageDescriptions = new HashMap<>();

/**
Expand Down Expand Up @@ -512,4 +516,12 @@ public String getInitialAppVersion() {
public void setInitialAppVersion(String initialAppVersion) {
this.initialAppVersion = initialAppVersion;
}

public List<CommandSpec> getCommands() {
return commands;
}

public void setCommands(List<CommandSpec> commands) {
this.commands = commands != null ? Collections.unmodifiableList(new ArrayList<>(commands)) : Collections.emptyList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ private static AppDescription createAppDescription(AppInfo appInfo, String url)
setupFileAssociations(appInfo, app);
setupUrlSchemes(appInfo, app);
setupMacUsageDescriptions(appInfo, app);
app.setCommands(appInfo.getCommands());
return app;
}

Expand Down
28 changes: 24 additions & 4 deletions shared/src/main/java/ca/weblite/jdeploy/models/CommandSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ public class CommandSpec {
private final String description;
private final List<String> args;
private final List<String> implementations;
private final Boolean embedPlist;

public CommandSpec(String name, String description, List<String> args, List<String> implementations) {
public CommandSpec(String name, String description, List<String> args, List<String> implementations, Boolean embedPlist) {
if (name == null) {
throw new IllegalArgumentException("Command name cannot be null");
}
Expand All @@ -30,13 +31,18 @@ public CommandSpec(String name, String description, List<String> args, List<Stri
} else {
this.implementations = Collections.unmodifiableList(new ArrayList<>(implementations));
}
this.embedPlist = embedPlist;
}

public CommandSpec(String name, String description, List<String> args, List<String> implementations) {
this(name, description, args, implementations, null);
}

/**
* Constructor for backward compatibility (no implementations specified).
*/
public CommandSpec(String name, String description, List<String> args) {
this(name, description, args, null);
this(name, description, args, null, null);
}

public String getName() {
Expand Down Expand Up @@ -64,6 +70,18 @@ public boolean implements_(String implementation) {
return implementations.contains(implementation);
}

/**
* Returns whether this command should have an embedded LaunchAgent plist
* generated in the macOS app bundle.
*
* @return {@code Boolean.TRUE} to force embedding, {@code Boolean.FALSE} to force
* the launchctl fallback, or {@code null} to use the default heuristic
* (embed if all args are static).
*/
public Boolean getEmbedPlist() {
return embedPlist;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand All @@ -73,12 +91,13 @@ public boolean equals(Object o) {
return Objects.equals(name, that.name) &&
Objects.equals(description, that.description) &&
Objects.equals(args, that.args) &&
Objects.equals(implementations, that.implementations);
Objects.equals(implementations, that.implementations) &&
Objects.equals(embedPlist, that.embedPlist);
}

@Override
public int hashCode() {
return Objects.hash(name, description, args, implementations);
return Objects.hash(name, description, args, implementations, embedPlist);
}

@Override
Expand All @@ -88,6 +107,7 @@ public String toString() {
", description='" + description + '\'' +
", args=" + args +
", implementations=" + implementations +
", embedPlist=" + embedPlist +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,17 @@ public static List<CommandSpec> parseCommands(JSONObject jdeployConfig) {
}
}

result.add(new CommandSpec(name, description, args, implementations));
Boolean embedPlist = null;
if (specObj.has("embedPlist")) {
Object embedObj = specObj.get("embedPlist");
if (embedObj instanceof Boolean) {
embedPlist = (Boolean) embedObj;
} else if (embedObj != JSONObject.NULL) {
throw new IllegalArgumentException("Command '" + name + "': 'embedPlist' must be a boolean");
}
}

result.add(new CommandSpec(name, description, args, implementations, embedPlist));
}

// sort by name for deterministic order
Expand Down
Loading