diff --git a/build.gradle.kts b/build.gradle.kts index 4e1d44e..7290b26 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,8 +7,11 @@ import org.jetbrains.kotlin.org.apache.commons.io.FileUtils import org.jetbrains.kotlin.org.apache.commons.io.filefilter.FileFilterUtils import org.jetbrains.kotlin.org.apache.commons.lang3.StringUtils import org.jetbrains.kotlin.org.apache.commons.lang3.time.DateFormatUtils +import java.io.FileNotFoundException import java.nio.file.Files import java.util.* +import java.util.concurrent.Executors +import java.util.concurrent.Future plugins { java @@ -35,7 +38,6 @@ val isBeta = project.version.toString().contains("beta", ignoreCase = true) val macOSSignUsername = System.getenv("TERMORA_MAC_SIGN_USER_NAME") ?: StringUtils.EMPTY val macOSSign = os.isMacOsX && macOSSignUsername.isNotBlank() && System.getenv("TERMORA_MAC_SIGN").toBoolean() -val macOSInstallSignUsername = System.getenv("TERMORA_MAC_INSTALL_SIGN_USER_NAME") ?: StringUtils.EMPTY // macOS 公证信息 val macOSNotaryKeychainProfile = System.getenv("TERMORA_MAC_NOTARY_KEYCHAIN_PROFILE") ?: StringUtils.EMPTY @@ -430,7 +432,7 @@ tasks.register("jpackage") { arguments.add("--type") if (os.isMacOsX) { - arguments.add("app-image") + arguments.add("dmg") } else if (os.isWindows) { arguments.add("app-image") } else if (os.isLinux) { @@ -573,30 +575,65 @@ fun packOnWindows(distributionDir: Directory, finalFilenameWithoutExtension: Str */ fun packOnMac(distributionDir: Directory, finalFilenameWithoutExtension: String, projectName: String) { val dmgFile = distributionDir.file("${finalFilenameWithoutExtension}.dmg").asFile - val appFile = distributionDir.file("${projectName}.app").asFile + val zipFile = distributionDir.file("${finalFilenameWithoutExtension}.zip").asFile - // dmg - exec { - commandLine( - "create-dmg", - "--volname", "$projectName Installer", - "--window-pos", "300", "100", - "--window-size", "500", "300", - "--icon-size", "80", - "--icon", appFile.name, "130", "110", - "--hide-extension", appFile.name, - "--app-drop-link", "370", "110", - dmgFile.absolutePath, appFile.absolutePath, - ) - workingDir = distributionDir.asFile + // rename + // @formatter:off + exec { commandLine("mv", distributionDir.file("${projectName}-${appVersion}.dmg").asFile.absolutePath, dmgFile.absolutePath,) } + // @formatter:on + + // sign dmg + signMacOSLocalFile(dmgFile) + + // 找到 .app + val imageFile = layout.buildDirectory.dir("jpackage/images/").get().asFile + val appFile = imageFile.listFiles()?.firstOrNull()?.listFiles()?.firstOrNull() + ?: throw FileNotFoundException("${projectName}.app") + + // zip + // @formatter:off + exec { commandLine("ditto", "-c", "-k", "--sequesterRsrc", "--keepParent", appFile.absolutePath, zipFile.absolutePath) } + // @formatter:on + + // sign zip + signMacOSLocalFile(zipFile) + + // 公证 + if (macOSNotary) { + val pool = Executors.newCachedThreadPool() + val jobs = mutableListOf>() + + // zip + pool.submit { + // 对 zip 公证 + notaryMacOSLocalFile(zipFile) + // 对 .app 盖章 + stapleMacOSLocalFile(appFile) + // 删除旧的 zip ,旧的 zip 仅仅是为了公证 + FileUtils.deleteQuietly(zipFile) + // 再对盖完章的 app 打成 zip 包 + // @formatter:off + exec { commandLine("ditto", "-c", "-k", "--sequesterRsrc", "--keepParent", appFile.absolutePath, zipFile.absolutePath) } + // @formatter:on + // 再对 zip 签名 + signMacOSLocalFile(zipFile) + }.apply { jobs.add(this) } + + // dmg + pool.submit { + // 公证 + notaryMacOSLocalFile(dmgFile) + // 盖章 + stapleMacOSLocalFile(dmgFile) + }.apply { jobs.add(this) } + + // join ... + jobs.forEach { it.get() } + + // shutdown + pool.shutdown() } - // 签名 - signMacOSLocalFile(dmgFile) - // 公证 - notaryMacOSLocalFile(dmgFile) - // 盖章 - stapleMacOSLocalFile(dmgFile) } /**