Skip to content

Commit 730221c

Browse files
Fix DMG packaging: it didn't display destination directory when a dialog with copying DMG contents popped up.
1 parent 32103d4 commit 730221c

File tree

2 files changed

+49
-46
lines changed

2 files changed

+49
-46
lines changed

src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacDmgPackager.java

Lines changed: 45 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
package jdk.jpackage.internal;
2727

28+
import static jdk.jpackage.internal.util.PathUtils.normalizedAbsolutePathString;
29+
2830
import java.io.File;
2931
import java.io.IOException;
3032
import java.nio.file.Files;
@@ -153,17 +155,18 @@ enum DmgPackageTaskID implements TaskID {
153155
}
154156

155157
Path volumePath() {
156-
return dmgWorkdir();
158+
return dmgWorkdir().resolve(volumeName());
157159
}
158160

159161
String volumeName() {
160162
return pkg.app().name();
161163
}
162164

163165
String createVolumeUrlLocation() throws IOException {
164-
Files.createDirectories(volumePath());
166+
final var volumeParentDir = volumePath().getParent();
167+
Files.createDirectories(volumeParentDir);
165168
// Url should end with '/' and it should be real path (no symbolic links).
166-
return volumePath().toRealPath().resolve(volumeName()).toUri().toString() + File.separator;
169+
return volumeParentDir.toRealPath().resolve(volumePath().getFileName()).toUri().toString() + File.separator;
167170
}
168171

169172
Path volumeScript() {
@@ -183,19 +186,15 @@ Path licenseFile() {
183186
}
184187

185188
Path protoDmg() {
186-
return dmgWorkdir().resolve("proto.dmg").toAbsolutePath();
189+
return dmgWorkdir().resolve("proto.dmg");
187190
}
188191

189192
Path protoCopyDmg() {
190-
return dmgWorkdir().resolve("proto-copy.dmg").toAbsolutePath();
191-
}
192-
193-
Path mountedProtoDmgPath() {
194-
return dmgWorkdir().resolve(volumeName());
193+
return dmgWorkdir().resolve("proto-copy.dmg");
195194
}
196195

197196
Path bgImageFileInMountedDmg() {
198-
return mountedProtoDmgPath().resolve(".background/background.tiff");
197+
return volumePath().resolve(".background/background.tiff");
199198
}
200199

201200
private Path dmgWorkdir() {
@@ -227,26 +226,23 @@ private void prepareDMGSetupScript() throws IOException {
227226

228227
data.put("DEPLOY_VOLUME_PATH", volumePath().toString());
229228
data.put("DEPLOY_APPLICATION_NAME", pkg.app().name());
229+
230230
String targetItem = pkg.relativeInstallDir().getFileName().toString();
231231
data.put("DEPLOY_TARGET", targetItem);
232-
data.put("DEPLOY_INSTALL_LOCATION", installRoot(pkg).toString());
233-
data.put("DEPLOY_INSTALL_LOCATION_DISPLAY_NAME",
234-
getInstallDirDisplayName());
232+
233+
data.put("DEPLOY_INSTALL_LOCATION", pkg.installDir().getParent().toString());
234+
235+
// "DEPLOY_INSTALL_LOCATION_DISPLAY_NAME" is the label for the default destination directory
236+
// for DMG bundle on the right side from the "copy" arrow in the dialog
237+
// that pops up when user clicks on a .dmg file.
238+
data.put("DEPLOY_INSTALL_LOCATION_DISPLAY_NAME", getInstallDirDisplayName());
235239

236240
env.createResource(DEFAULT_DMG_SETUP_SCRIPT)
237241
.setCategory(I18N.getString("resource.dmg-setup-script"))
238242
.setSubstitutionData(data)
239243
.saveToFile(dmgSetup);
240244
}
241245

242-
private static Path installRoot(MacDmgPackage pkg) {
243-
if (pkg.isRuntimeInstaller()) {
244-
return Path.of("/Library/Java/JavaVirtualMachines");
245-
} else {
246-
return Path.of("/Applications");
247-
}
248-
}
249-
250246
private void prepareLicense() throws IOException {
251247
final var licFile = pkg.licenseFile();
252248
if (licFile.isEmpty()) {
@@ -283,11 +279,14 @@ private void prepareConfigFiles() throws IOException {
283279
prepareDMGSetupScript();
284280
}
285281

286-
// Returns display name of installation directory. Display name is used to
287-
// show user installation location and for well known (default only) we will
288-
// use "Applications" or "JavaVirtualMachines".
289282
private String getInstallDirDisplayName() {
290-
return installRoot(pkg).getFileName().toString();
283+
final var defaultInstallDir = new PackageBuilder(pkg.app(), pkg.type()).defaultInstallDir().orElseThrow();
284+
if (defaultInstallDir.equals(pkg.installDir())) {
285+
// Return "Applications" for "/Applications/foo.app"
286+
return defaultInstallDir.getParent().getFileName().toString();
287+
} else {
288+
return pkg.installDir().getParent().toString();
289+
}
291290
}
292291

293292
private void buildDMG() throws IOException {
@@ -320,9 +319,9 @@ private void buildDMG() throws IOException {
320319
hdiutil.toString(),
321320
"create",
322321
hdiUtilVerbosityFlag,
323-
"-srcfolder", srcFolder.toAbsolutePath().toString(),
322+
"-srcfolder", normalizedAbsolutePathString(srcFolder),
324323
"-volname", volumeName(),
325-
"-ov", protoDMG.toString(),
324+
"-ov", normalizedAbsolutePathString(protoDMG),
326325
"-fs", "HFS+",
327326
"-format", "UDRW");
328327
try {
@@ -345,7 +344,7 @@ private void buildDMG() throws IOException {
345344
hdiUtilVerbosityFlag,
346345
"-size", String.valueOf(size),
347346
"-volname", volumeName(),
348-
"-ov", protoDMG.toString(),
347+
"-ov", normalizedAbsolutePathString(protoDMG),
349348
"-fs", "HFS+");
350349
new RetryExecutor()
351350
.setMaxAttemptsCount(10)
@@ -358,17 +357,17 @@ private void buildDMG() throws IOException {
358357
pb = new ProcessBuilder(
359358
hdiutil.toString(),
360359
"attach",
361-
protoDMG.toString(),
360+
normalizedAbsolutePathString(protoDMG),
362361
hdiUtilVerbosityFlag,
363362
"-mountroot", protoDMG.getParent().toString());
364363
IOUtils.exec(pb, false, null, true, Executor.INFINITE_TIMEOUT);
365364

366-
final Path mountedRoot = mountedProtoDmgPath();
365+
final Path mountedVolume = volumePath();
367366

368367
// Copy app image, since we did not create DMG with it, but instead we created
369368
// empty one.
370369
if (copyAppImage) {
371-
FileUtils.copyRecursive(srcFolder, mountedRoot);
370+
FileUtils.copyRecursive(srcFolder, mountedVolume);
372371
}
373372

374373
try {
@@ -382,14 +381,14 @@ private void buildDMG() throws IOException {
382381
// headless environment.
383382
try {
384383
pb = new ProcessBuilder("/usr/bin/osascript",
385-
volumeScript().toAbsolutePath().toString());
384+
normalizedAbsolutePathString(volumeScript()));
386385
IOUtils.exec(pb, 180); // Wait 3 minutes. See JDK-8248248.
387386
} catch (IOException ex) {
388387
Log.verbose(ex);
389388
}
390389

391390
// volume icon
392-
Path volumeIconFile = mountedRoot.resolve(".VolumeIcon.icns");
391+
Path volumeIconFile = mountedVolume.resolve(".VolumeIcon.icns");
393392
IOUtils.copyFile(volumeIcon(), volumeIconFile);
394393

395394
// Indicate that we want a custom icon
@@ -407,14 +406,14 @@ private void buildDMG() throws IOException {
407406
pb = new ProcessBuilder(
408407
setFileUtility.orElseThrow().toString(),
409408
"-c", "icnC",
410-
volumeIconFile.toAbsolutePath().toString());
409+
normalizedAbsolutePathString(volumeIconFile));
411410
IOUtils.exec(pb);
412411
volumeIconFile.toFile().setReadOnly();
413412

414413
pb = new ProcessBuilder(
415414
setFileUtility.orElseThrow().toString(),
416415
"-a", "C",
417-
mountedRoot.toAbsolutePath().toString());
416+
normalizedAbsolutePathString(mountedVolume));
418417
IOUtils.exec(pb);
419418
} catch (IOException ex) {
420419
Log.error(ex.getMessage());
@@ -430,14 +429,14 @@ private void buildDMG() throws IOException {
430429
hdiutil.toString(),
431430
"detach",
432431
hdiUtilVerbosityFlag,
433-
mountedRoot.toAbsolutePath().toString());
432+
normalizedAbsolutePathString(mountedVolume));
434433
// "hdiutil detach" might not work right away due to resource busy error, so
435434
// repeat detach several times.
436435
RetryExecutor retryExecutor = new RetryExecutor();
437436
// Image can get detach even if we got resource busy error, so stop
438437
// trying to detach it if it is no longer attached.
439438
retryExecutor.setExecutorInitializer(exec -> {
440-
if (!Files.exists(mountedRoot)) {
439+
if (!Files.exists(mountedVolume)) {
441440
retryExecutor.abort();
442441
}
443442
});
@@ -448,13 +447,13 @@ private void buildDMG() throws IOException {
448447
} catch (IOException ex) {
449448
if (!retryExecutor.isAborted()) {
450449
// Now force to detach if it still attached
451-
if (Files.exists(mountedRoot)) {
450+
if (Files.exists(mountedVolume)) {
452451
pb = new ProcessBuilder(
453452
hdiutil.toString(),
454453
"detach",
455454
"-force",
456455
hdiUtilVerbosityFlag,
457-
mountedRoot.toAbsolutePath().toString());
456+
normalizedAbsolutePathString(mountedVolume));
458457
IOUtils.exec(pb, false, null, true, Executor.INFINITE_TIMEOUT);
459458
}
460459
}
@@ -465,10 +464,10 @@ private void buildDMG() throws IOException {
465464
pb = new ProcessBuilder(
466465
hdiutil.toString(),
467466
"convert",
468-
protoDMG.toAbsolutePath().toString(),
467+
normalizedAbsolutePathString(protoDMG),
469468
hdiUtilVerbosityFlag,
470469
"-format", "UDZO",
471-
"-o", finalDMG.toAbsolutePath().toString());
470+
"-o", normalizedAbsolutePathString(finalDMG));
472471
try {
473472
new RetryExecutor()
474473
.setMaxAttemptsCount(10)
@@ -482,10 +481,10 @@ private void buildDMG() throws IOException {
482481
pb = new ProcessBuilder(
483482
hdiutil.toString(),
484483
"convert",
485-
protoCopyDMG.toString(),
484+
normalizedAbsolutePathString(protoCopyDMG),
486485
hdiUtilVerbosityFlag,
487486
"-format", "UDZO",
488-
"-o", finalDMG.toAbsolutePath().toString());
487+
"-o", normalizedAbsolutePathString(finalDMG));
489488
IOUtils.exec(pb, false, null, true, Executor.INFINITE_TIMEOUT);
490489
} finally {
491490
Files.deleteIfExists(protoCopyDMG);
@@ -497,9 +496,9 @@ private void buildDMG() throws IOException {
497496
pb = new ProcessBuilder(
498497
hdiutil.toString(),
499498
"udifrez",
500-
finalDMG.toAbsolutePath().toString(),
499+
normalizedAbsolutePathString(finalDMG),
501500
"-xml",
502-
licenseFile().toAbsolutePath().toString()
501+
normalizedAbsolutePathString(licenseFile())
503502
);
504503
new RetryExecutor()
505504
.setMaxAttemptsCount(10)
@@ -516,7 +515,7 @@ private void buildDMG() throws IOException {
516515

517516
Log.verbose(MessageFormat.format(I18N.getString(
518517
"message.output-to-location"),
519-
pkg.app().name(), finalDMG.toAbsolutePath().toString()));
518+
pkg.app().name(), normalizedAbsolutePathString(finalDMG)));
520519

521520
}
522521

src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/model/MacPackage.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ default AppImageLayout appImageLayout() {
3838
}
3939
}
4040

41+
default Path installDir() {
42+
return Path.of("/").resolve(relativeInstallDir());
43+
}
44+
4145
public static MacPackage create(Package pkg) {
4246
return CompositeProxy.create(MacPackage.class, pkg);
4347
}

0 commit comments

Comments
 (0)