diff --git a/README.md b/README.md
index 5f69f65..5c03a8d 100644
--- a/README.md
+++ b/README.md
@@ -13,12 +13,12 @@ Create a macOS Application from an executable (like a Go binary)
To install `appify`:
```bash
-go get github.com/machinebox/appify
+go get git.yetaga.in/alazyreader/appify
```
## Usage
-```
+```bash
appify -name "My Go Application" -icon ./icon.png /path/to/bin
```
diff --git a/main.go b/main.go
index 76a8ffe..a7d8dd5 100644
--- a/main.go
+++ b/main.go
@@ -29,6 +29,7 @@ func run() error {
version = flag.String("version", "1.0", "app version")
identifier = flag.String("id", "", "bundle identifier")
icon = flag.String("icon", "", "icon image file (.icns|.png|.jpg|.jpeg)")
+ extraPlist = flag.String("plist", "", "path to file with additional plist dict key/value items")
)
flag.Parse()
args := flag.Args()
@@ -70,6 +71,13 @@ func run() error {
if id == "" {
id = *author + "." + *name
}
+ if *extraPlist != "" {
+ b, err := os.ReadFile(*extraPlist)
+ if err != nil {
+ return errors.Wrap(err, "error reading plist location: "+*extraPlist)
+ }
+ *extraPlist = string(b)
+ }
info := infoListData{
Name: *name,
Executable: filepath.Join("MacOS", appname),
@@ -77,6 +85,7 @@ func run() error {
Version: *version,
InfoString: *name + " by " + *author,
ShortVersionString: *version,
+ AdditionalPList: *extraPlist,
}
if *icon != "" {
iconPath, err := prepareIcons(*icon, resouresPath)
@@ -150,6 +159,7 @@ type infoListData struct {
InfoString string
ShortVersionString string
IconFile string
+ AdditionalPList string
}
const infoPlistTemplate = `
@@ -176,6 +186,9 @@ const infoPlistTemplate = `
CFBundleIconFile
{{ .IconFile }}
{{- end }}
+{{- if .AdditionalPList -}}
+{{ .AdditionalPList -}}
+{{- end }}
`
diff --git a/main_test.go b/main_test.go
index 656eb23..abf4991 100644
--- a/main_test.go
+++ b/main_test.go
@@ -51,6 +51,45 @@ func Test(t *testing.T) {
}
}
+func TestWithPListInjection(t *testing.T) {
+ is := is.New(t)
+ out, err := exec.Command("./appify",
+ "-name", "Test",
+ "-icon", "testdata/machina-square.png",
+ "-plist", "testdata/additionalplist.xml",
+ "testdata/app").CombinedOutput()
+ t.Logf("%q", string(out))
+ is.NoErr(err)
+ defer os.RemoveAll("Test.app")
+ actualAppHash := filehash(t, "testdata/app")
+ type file struct {
+ path string
+ perm string
+ hash string
+ }
+ for _, f := range []file{
+ {path: "Test.app", perm: "drwxr-xr-x"},
+ {path: "Test.app/Contents", perm: "drwxr-xr-x"},
+ {path: "Test.app/Contents/MacOS", perm: "drwxr-xr-x"},
+ {path: "Test.app/Contents/MacOS/Test.app", perm: "-rwxr-xr-x", hash: actualAppHash},
+ {path: "Test.app/Contents/Info.plist", perm: "-rw-r--r--", hash: "dd977257c7e77dc7739bb4ae70e5f697"},
+ {path: "Test.app/Contents/README", perm: "-rw-r--r--", hash: "afeb10df47c7f189b848ae44a54e7e06"},
+ {path: "Test.app/Contents/Resources", perm: "drwxr-xr-x"},
+ {path: "Test.app/Contents/Resources/icon.icns", perm: "-rw-r--r--", hash: "23bdc36475094ed8886f319811d3a182"},
+ } {
+ t.Run(f.path, func(t *testing.T) {
+ is := is.New(t)
+ info, err := os.Stat(f.path)
+ is.NoErr(err)
+ is.Equal(info.Mode().String(), f.perm) // perm
+ if f.hash != "" {
+ actual := filehash(t, f.path)
+ is.Equal(actual, f.hash) // hash
+ }
+ })
+ }
+}
+
// filehash gets an md5 hash of the file at path.
func filehash(t *testing.T, path string) string {
is := is.New(t)
diff --git a/testdata/additionalplist.xml b/testdata/additionalplist.xml
new file mode 100644
index 0000000..556fb8d
--- /dev/null
+++ b/testdata/additionalplist.xml
@@ -0,0 +1,33 @@
+CFBundleDocumentTypes
+
+
+ CFBundleTypeExtensions
+
+ jpg
+ JPG
+ jpeg
+ JPEG
+
+ CFBundleTypeIconFile
+ jpeg.icns
+ CFBundleTypeMIMETypes
+
+ image/jpeg
+
+ CFBundleTypeName
+ JPEG Image
+ CFBundleTypeOSTypes
+
+ JPEG
+ ????
+
+ CFBundleTypeRole
+ Viewer
+ LSItemContentTypes
+
+ public.jpeg
+
+ LSTypeIsPackage
+
+
+
\ No newline at end of file