|
1 #! /bin/bash |
|
2 |
|
3 # Create a read-only disk image of the contents of a folder |
|
4 |
|
5 set -e; |
|
6 |
|
7 function pure_version() { |
|
8 echo '1.0.0.2' |
|
9 } |
|
10 |
|
11 function version() { |
|
12 echo "create-dmg $(pure_version)" |
|
13 } |
|
14 |
|
15 function usage() { |
|
16 version |
|
17 echo "Creates a fancy DMG file." |
|
18 echo "Usage: $(basename $0) options... image.dmg source_folder" |
|
19 echo "All contents of source_folder will be copied into the disk image." |
|
20 echo "Options:" |
|
21 echo " --volname name" |
|
22 echo " set volume name (displayed in the Finder sidebar and window title)" |
|
23 echo " --volicon icon.icns" |
|
24 echo " set volume icon" |
|
25 echo " --background pic.png" |
|
26 echo " set folder background image (provide png, gif, jpg)" |
|
27 echo " --window-pos x y" |
|
28 echo " set position the folder window" |
|
29 echo " --window-size width height" |
|
30 echo " set size of the folder window" |
|
31 echo " --icon-size icon_size" |
|
32 echo " set window icons size (up to 128)" |
|
33 echo " --icon file_name x y" |
|
34 echo " set position of the file's icon" |
|
35 echo " --hide-extension file_name" |
|
36 echo " hide the extension of file" |
|
37 echo " --custom-icon file_name custom_icon_or_sample_file x y" |
|
38 echo " set position and custom icon" |
|
39 echo " --app-drop-link x y" |
|
40 echo " make a drop link to Applications, at location x,y" |
|
41 echo " --eula eula_file" |
|
42 echo " attach a license file to the dmg" |
|
43 echo " --no-internet-enable" |
|
44 echo " disable automatic mount©" |
|
45 echo " --version show tool version number" |
|
46 echo " -h, --help display this help" |
|
47 exit 0 |
|
48 } |
|
49 |
|
50 WINX=10 |
|
51 WINY=60 |
|
52 WINW=500 |
|
53 WINH=350 |
|
54 ICON_SIZE=128 |
|
55 |
|
56 while test "${1:0:1}" = "-"; do |
|
57 case $1 in |
|
58 --volname) |
|
59 VOLUME_NAME="$2" |
|
60 shift; shift;; |
|
61 --volicon) |
|
62 VOLUME_ICON_FILE="$2" |
|
63 shift; shift;; |
|
64 --background) |
|
65 BACKGROUND_FILE="$2" |
|
66 BACKGROUND_FILE_NAME="$(basename $BACKGROUND_FILE)" |
|
67 BACKGROUND_CLAUSE="set background picture of opts to file \".background:$BACKGROUND_FILE_NAME\"" |
|
68 shift; shift;; |
|
69 --icon-size) |
|
70 ICON_SIZE="$2" |
|
71 shift; shift;; |
|
72 --window-pos) |
|
73 WINX=$2; WINY=$3 |
|
74 shift; shift; shift;; |
|
75 --window-size) |
|
76 WINW=$2; WINH=$3 |
|
77 shift; shift; shift;; |
|
78 --icon) |
|
79 POSITION_CLAUSE="${POSITION_CLAUSE}set position of item \"$2\" to {$3, $4} |
|
80 " |
|
81 shift; shift; shift; shift;; |
|
82 --hide-extension) |
|
83 HIDING_CLAUSE="${HIDING_CLAUSE}set the extension hidden of item \"$2\" to true" |
|
84 shift; shift;; |
|
85 --custom-icon) |
|
86 shift; shift; shift; shift; shift;; |
|
87 -h | --help) |
|
88 usage;; |
|
89 --version) |
|
90 version; exit 0;; |
|
91 --pure-version) |
|
92 pure_version; exit 0;; |
|
93 --app-drop-link) |
|
94 APPLICATION_LINK=$2 |
|
95 APPLICATION_CLAUSE="set position of item \"Applications\" to {$2, $3} |
|
96 " |
|
97 shift; shift; shift;; |
|
98 --eula) |
|
99 EULA_RSRC=$2 |
|
100 shift; shift;; |
|
101 --no-internet-enable) |
|
102 NOINTERNET=1 |
|
103 shift;; |
|
104 -*) |
|
105 echo "Unknown option $1. Run with --help for help." |
|
106 exit 1;; |
|
107 esac |
|
108 done |
|
109 |
|
110 test -z "$2" && { |
|
111 echo "Not enough arguments. Invoke with --help for help." |
|
112 exit 1 |
|
113 } |
|
114 |
|
115 DMG_PATH="$1" |
|
116 DMG_DIRNAME="$(dirname "$DMG_PATH")" |
|
117 DMG_DIR="$(cd $DMG_DIRNAME > /dev/null; pwd)" |
|
118 DMG_NAME="$(basename "$DMG_PATH")" |
|
119 DMG_TEMP_NAME="$DMG_DIR/rw.${DMG_NAME}" |
|
120 SRC_FOLDER="$(cd "$2" > /dev/null; pwd)" |
|
121 test -z "$VOLUME_NAME" && VOLUME_NAME="$(basename "$DMG_PATH" .dmg)" |
|
122 |
|
123 AUX_PATH="$(dirname $0)/support" |
|
124 |
|
125 test -d "$AUX_PATH" || { |
|
126 echo "Cannot find support directory: $AUX_PATH" |
|
127 exit 1 |
|
128 } |
|
129 |
|
130 if [ -f "$SRC_FOLDER/.DS_Store" ]; then |
|
131 echo "Deleting any .DS_Store in source folder" |
|
132 rm "$SRC_FOLDER/.DS_Store" |
|
133 fi |
|
134 |
|
135 # Create the image |
|
136 echo "Creating disk image..." |
|
137 test -f "${DMG_TEMP_NAME}" && rm -f "${DMG_TEMP_NAME}" |
|
138 ACTUAL_SIZE=`du -sm "$SRC_FOLDER" | sed -e 's/ .*//g'` |
|
139 DISK_IMAGE_SIZE=$(expr $ACTUAL_SIZE + 20) |
|
140 hdiutil create -srcfolder "$SRC_FOLDER" -volname "${VOLUME_NAME}" -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format UDRW -size ${DISK_IMAGE_SIZE}m "${DMG_TEMP_NAME}" |
|
141 |
|
142 # mount it |
|
143 echo "Mounting disk image..." |
|
144 MOUNT_DIR="/Volumes/${VOLUME_NAME}" |
|
145 |
|
146 # try unmount dmg if it was mounted previously (e.g. developer mounted dmg, installed app and forgot to unmount it) |
|
147 echo "Unmounting disk image..." |
|
148 DEV_NAME=$(hdiutil info | egrep '^/dev/' | sed 1q | awk '{print $1}') |
|
149 test -d "${MOUNT_DIR}" && hdiutil detach "${DEV_NAME}" |
|
150 |
|
151 echo "Mount directory: $MOUNT_DIR" |
|
152 DEV_NAME=$(hdiutil attach -readwrite -noverify -noautoopen "${DMG_TEMP_NAME}" | egrep '^/dev/' | sed 1q | awk '{print $1}') |
|
153 echo "Device name: $DEV_NAME" |
|
154 |
|
155 if ! test -z "$BACKGROUND_FILE"; then |
|
156 echo "Copying background file..." |
|
157 test -d "$MOUNT_DIR/.background" || mkdir "$MOUNT_DIR/.background" |
|
158 cp "$BACKGROUND_FILE" "$MOUNT_DIR/.background/$BACKGROUND_FILE_NAME" |
|
159 fi |
|
160 |
|
161 if ! test -z "$APPLICATION_LINK"; then |
|
162 echo "making link to Applications dir" |
|
163 echo $MOUNT_DIR |
|
164 ln -s /Applications "$MOUNT_DIR/Applications" |
|
165 fi |
|
166 |
|
167 if ! test -z "$VOLUME_ICON_FILE"; then |
|
168 echo "Copying volume icon file '$VOLUME_ICON_FILE'..." |
|
169 cp "$VOLUME_ICON_FILE" "$MOUNT_DIR/.VolumeIcon.icns" |
|
170 SetFile -c icnC "$MOUNT_DIR/.VolumeIcon.icns" |
|
171 fi |
|
172 |
|
173 # run applescript |
|
174 APPLESCRIPT=$(mktemp -t createdmg) |
|
175 cat "$AUX_PATH/template.applescript" | sed -e "s/WINX/$WINX/g" -e "s/WINY/$WINY/g" -e "s/WINW/$WINW/g" -e "s/WINH/$WINH/g" -e "s/BACKGROUND_CLAUSE/$BACKGROUND_CLAUSE/g" -e "s/ICON_SIZE/$ICON_SIZE/g" | perl -pe "s/POSITION_CLAUSE/$POSITION_CLAUSE/g" | perl -pe "s/APPLICATION_CLAUSE/$APPLICATION_CLAUSE/g" | perl -pe "s/HIDING_CLAUSE/$HIDING_CLAUSE/" >"$APPLESCRIPT" |
|
176 |
|
177 echo "Running Applescript: /usr/bin/osascript \"${APPLESCRIPT}\" \"${VOLUME_NAME}\"" |
|
178 "/usr/bin/osascript" "${APPLESCRIPT}" "${VOLUME_NAME}" || true |
|
179 echo "Done running the applescript..." |
|
180 sleep 4 |
|
181 |
|
182 rm "$APPLESCRIPT" |
|
183 |
|
184 # make sure it's not world writeable |
|
185 echo "Fixing permissions..." |
|
186 chmod -Rf go-w "${MOUNT_DIR}" &> /dev/null || true |
|
187 echo "Done fixing permissions." |
|
188 |
|
189 # make the top window open itself on mount: |
|
190 echo "Blessing started" |
|
191 bless --folder "${MOUNT_DIR}" --openfolder "${MOUNT_DIR}" |
|
192 echo "Blessing finished" |
|
193 |
|
194 if ! test -z "$VOLUME_ICON_FILE"; then |
|
195 # tell the volume that it has a special file attribute |
|
196 SetFile -a C "$MOUNT_DIR" |
|
197 fi |
|
198 |
|
199 # unmount |
|
200 echo "Unmounting disk image..." |
|
201 hdiutil detach "${DEV_NAME}" |
|
202 |
|
203 # compress image |
|
204 echo "Compressing disk image..." |
|
205 hdiutil convert "${DMG_TEMP_NAME}" -format UDZO -imagekey zlib-level=9 -o "${DMG_DIR}/${DMG_NAME}" |
|
206 rm -f "${DMG_TEMP_NAME}" |
|
207 |
|
208 # adding EULA resources |
|
209 if [ ! -z "${EULA_RSRC}" -a "${EULA_RSRC}" != "-null-" ]; then |
|
210 echo "adding EULA resources" |
|
211 "${AUX_PATH}/dmg-license.py" "${DMG_DIR}/${DMG_NAME}" "${EULA_RSRC}" |
|
212 fi |
|
213 |
|
214 if [ ! -z "${NOINTERNET}" -a "${NOINTERNET}" == 1 ]; then |
|
215 echo "not setting 'internet-enable' on the dmg" |
|
216 else |
|
217 hdiutil internet-enable -yes "${DMG_DIR}/${DMG_NAME}" |
|
218 fi |
|
219 |
|
220 echo "Disk image done" |
|
221 exit 0 |