|
1 | 1 | using System; |
2 | 2 | using System.Collections.Generic; |
3 | 3 | using System.IO; |
| 4 | +using System.Linq; |
4 | 5 | using System.Runtime.Versioning; |
5 | 6 | using System.Threading; |
6 | 7 | using Newtonsoft.Json; |
@@ -52,22 +53,54 @@ public static void CreateInstallerPkg(string appBundlePath, string pkgOutputPath |
52 | 53 | { |
53 | 54 | Log.Info($"Creating installer '.pkg' for app at '{appBundlePath}'"); |
54 | 55 |
|
55 | | - var args = new List<string> { |
56 | | - "--install-location", "~/Applications", |
57 | | - "--component", appBundlePath, |
| 56 | + using var _1 = Utility.GetTempDirectory(out var tmp); |
| 57 | + using var _2 = Utility.GetTempDirectory(out var tmpPayload1); |
| 58 | + using var _3 = Utility.GetTempDirectory(out var tmpPayload2); |
| 59 | + |
| 60 | + // copy .app to tmp folder |
| 61 | + var bundleName = Path.GetFileName(appBundlePath); |
| 62 | + var tmpBundlePath = Path.Combine(tmpPayload1, bundleName); |
| 63 | + Utility.CopyFiles(new DirectoryInfo(appBundlePath), new DirectoryInfo(tmpBundlePath)); |
| 64 | + |
| 65 | + // generate non-relocatable pkg |
| 66 | + var pkgPlistPath = Path.Combine(tmp, "tmp.plist"); |
| 67 | + InvokeAndThrowIfNonZero("pkgbuild", new[] { "--analyze", "--root", tmpPayload1, pkgPlistPath }, null); |
| 68 | + InvokeAndThrowIfNonZero("plutil", new[] { "-replace", "BundleIsRelocatable", "-bool", "NO", pkgPlistPath }, null); |
| 69 | + |
| 70 | + var pkg1Path = Path.Combine(tmpPayload2, "1.pkg"); |
| 71 | + string[] args1 = { |
| 72 | + "--root", tmpPayload1, |
| 73 | + "--component-plist", pkgPlistPath, |
| 74 | + "--install-location", "/Applications", |
| 75 | + pkg1Path, |
58 | 76 | }; |
| 77 | + |
| 78 | + InvokeAndThrowIfNonZero("pkgbuild", args1, null); |
59 | 79 |
|
| 80 | + // create product package that installs to home dir |
| 81 | + var distributionPath = Path.Combine(tmp, "distribution.xml"); |
| 82 | + InvokeAndThrowIfNonZero("productbuild", new[] { "--synthesize", "--package", pkg1Path, distributionPath }, null); |
| 83 | + |
| 84 | + // disable local system installation and build final package |
| 85 | + var distXml = File.ReadAllLines(distributionPath).ToList(); |
| 86 | + distXml.Insert(2, "<domains enable_anywhere=\"false\" enable_currentUserHome=\"true\" enable_localSystem=\"false\" />"); |
| 87 | + File.WriteAllLines(distributionPath, distXml); |
| 88 | + |
| 89 | + List<string> args2 = new () { |
| 90 | + "--distribution", distributionPath, |
| 91 | + "--package-path", tmpPayload2, |
| 92 | + pkgOutputPath |
| 93 | + }; |
| 94 | + |
60 | 95 | if (!String.IsNullOrEmpty(signIdentity)) { |
61 | | - args.Add("--sign"); |
62 | | - args.Add(signIdentity); |
| 96 | + args2.Add("--sign"); |
| 97 | + args2.Add(signIdentity); |
63 | 98 | } else { |
64 | 99 | Log.Warn("No Installer signing identity provided. The '.pkg' will not be signed."); |
65 | 100 | } |
66 | | - |
67 | | - args.Add(pkgOutputPath); |
68 | | - |
69 | | - InvokeAndThrowIfNonZero("pkgbuild", args, null); |
70 | | - |
| 101 | + |
| 102 | + InvokeAndThrowIfNonZero("productbuild", args2, null); |
| 103 | + |
71 | 104 | Log.Info("Installer created successfully"); |
72 | 105 | } |
73 | 106 |
|
|
0 commit comments