@@ -4,6 +4,7 @@ import argparse
44import string
55import os
66import subprocess
7+ import plistlib
78
89
910quickpkg_version = '0.0'
@@ -34,49 +35,75 @@ def cmdexec(command):
3435 return {"return_code" : proc .returncode , "stderr" : stderr .rstrip (), "stdout" : stdout .rstrip ()}
3536
3637
38+ # stolen from munkicommons.py
39+ def getFirstPlist (textString ):
40+ """Gets the next plist from a text string that may contain one or
41+ more text-style plists.
42+ Returns a tuple - the first plist (if any) and the remaining
43+ string after the plist"""
44+ plist_header = '<?xml version'
45+ plist_footer = '</plist>'
46+ plist_start_index = textString .find (plist_header )
47+ if plist_start_index == - 1 :
48+ # not found
49+ return ("" , textString )
50+ plist_end_index = textString .find (
51+ plist_footer , plist_start_index + len (plist_header ))
52+ if plist_end_index == - 1 :
53+ # not found
54+ return ("" , textString )
55+ # adjust end value
56+ plist_end_index = plist_end_index + len (plist_footer )
57+ return (textString [plist_start_index :plist_end_index ],
58+ textString [plist_end_index :])
59+
60+
3761def attachdmg (dmgpath ):
38- return
39-
40-
41- # command to run
42- # hdiutil attach ~/Downloads/BBEdit_11.1.4.dmg -mountrandom /tmp -plist -nobrowse
43- #
44- # returns
45- # <?xml version="1.0" encoding="UTF-8"?>
46- # <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
47- # <plist version="1.0">
48- # <dict>
49- # <key>system-entities</key>
50- # <array>
51- # <dict>
52- # <key>content-hint</key>
53- # <string>Apple_HFS</string>
54- # <key>dev-entry</key>
55- # <string>/dev/disk4s1</string>
56- # <key>mount-point</key>
57- # <string>/private/tmp/dmg.6fzBvH</string>
58- # <key>potentially-mountable</key>
59- # <true/>
60- # <key>unmapped-content-hint</key>
61- # <string>48465300-0000-11AA-AA11-00306543ECAC</string>
62- # <key>volume-kind</key>
63- # <string>hfs</string>
64- # </dict>
65- # <dict>
66- # <key>content-hint</key>
67- # <string>GUID_partition_scheme</string>
68- # <key>dev-entry</key>
69- # <string>/dev/disk4</string>
70- # <key>potentially-mountable</key>
71- # <false/>
72- # <key>unmapped-content-hint</key>
73- # <string>GUID_partition_scheme</string>
74- # </dict>
75- # </array>
76- # </dict>
77- # </plist>
62+ attachcmd = ["/usr/bin/hdiutil" ,
63+ "attach" ,
64+ dmgpath ,
65+ "-mountrandom" ,
66+ "/private/tmp" ,
67+ "-plist" ,
68+ "-nobrowse" ]
69+ result = cmdexec (attachcmd )
70+ if result ["return_code" ] == 0 :
71+ # parse the plist output
72+ (theplist , alltext ) = getFirstPlist (result ["stdout" ])
73+ resultdict = plistlib .readPlistFromString (theplist )
74+ volpaths = []
75+ for x in resultdict ["system-entities" ]:
76+ if x ["potentially-mountable" ]:
77+ if x ["volume-kind" ] == 'hfs' :
78+ volpaths .append (x ["mount-point" ])
79+ # return the paths to mounted volume
80+ return volpaths
81+ else :
82+ print "error mounting disk image"
83+ print "(%d, %s)" % (result ["returncode" ], result ["stderr" ])
84+ exit (1 )
7885
7986
87+ def detachpaths (volpaths ):
88+ for x in volpaths :
89+ if os .path .exists (x ):
90+ if os .path .ismount (x ):
91+ detachcmd = ["/usr/bin/hdiutil" , "detach" , x ]
92+ cmdexec (detachcmd )
93+
94+ def finditemswithextension (dirpath , item_extension ):
95+ foundapps = []
96+ if os .path .exists (dirpath ):
97+ for x in os .listdir (dirpath ):
98+ (item_basename , item_extension ) = os .path .splitext (x )
99+ item_extension = string .lstrip (item_extension , '.' )
100+ if item_extension == 'app' :
101+ foundapps .append (os .path .join (dirpath , x ))
102+ else :
103+ print "path %s does not exist" % dirpath
104+ exit (1 )
105+ return foundapps
106+
80107if __name__ == "__main__" :
81108 # for convenience link to argparse tutorial:
82109 # https://docs.python.org/2/howto/argparse.html#id1
@@ -107,8 +134,38 @@ if __name__ == "__main__":
107134 print ".%s is not a supported extension!" % item_extension
108135 exit (1 )
109136
137+ # if item is an app, just pass it on
138+ if item_extension == 'app' :
139+ if not os .path .exists (item_path ):
140+ print "This does not seem to be an Application!"
141+ exit (1 )
142+
143+ app_path = item_path
144+
145+ dmgvolumepaths = []
146+
110147 # if item is a dmg, mount it and find useful contents
148+ if item_extension == 'dmg' :
149+ dmgvolumepaths = attachdmg (item_path )
150+ foundapps = []
151+ for x in dmgvolumepaths :
152+ moreapps = finditemswithextension (x , 'app' )
153+ foundapps .extend (moreapps )
154+ if len (foundapps ) == 0 :
155+ print "Could not find an application!"
156+ detachpaths (dmgvolumepaths )
157+ exit (1 )
158+ elif len (foundapps ) > 1 :
159+ print "Found too many Applications! Can't decide!"
160+ print foundapps
161+ detachpaths (dmgvolumepaths )
162+ exit (1 )
163+
164+ app_path = foundapps [0 ]
111165
112166 # extract version and other metadata
113-
167+ print app_path
168+
114169 # run pkgutil to build result
170+ detachpaths (dmgvolumepaths )
171+
0 commit comments