|
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 " --version show tool version number" |
|
44 echo " -h, --help display this help" |
|
45 exit 0 |
|
46 } |
|
47 |
|
48 WINX=10 |
|
49 WINY=60 |
|
50 WINW=500 |
|
51 WINH=350 |
|
52 ICON_SIZE=128 |
|
53 |
|
54 while test "${1:0:1}" = "-"; do |
|
55 case $1 in |
|
56 --volname) |
|
57 VOLUME_NAME="$2" |
|
58 shift; shift;; |
|
59 --volicon) |
|
60 VOLUME_ICON_FILE="$2" |
|
61 shift; shift;; |
|
62 --background) |
|
63 BACKGROUND_FILE="$2" |
|
64 BACKGROUND_FILE_NAME="$(basename $BACKGROUND_FILE)" |
|
65 BACKGROUND_CLAUSE="set background picture of opts to file \".background:$BACKGROUND_FILE_NAME\"" |
|
66 shift; shift;; |
|
67 --icon-size) |
|
68 ICON_SIZE="$2" |
|
69 shift; shift;; |
|
70 --window-pos) |
|
71 WINX=$2; WINY=$3 |
|
72 shift; shift; shift;; |
|
73 --window-size) |
|
74 WINW=$2; WINH=$3 |
|
75 shift; shift; shift;; |
|
76 --icon) |
|
77 POSITION_CLAUSE="${POSITION_CLAUSE}set position of item \"$2\" to {$3, $4} |
|
78 " |
|
79 shift; shift; shift; shift;; |
|
80 --hide-extension) |
|
81 HIDING_CLAUSE="${HIDING_CLAUSE}set the extension hidden of item \"$2\" to true" |
|
82 shift; shift;; |
|
83 --custom-icon) |
|
84 shift; shift; shift; shift; shift;; |
|
85 -h | --help) |
|
86 usage;; |
|
87 --version) |
|
88 version; exit 0;; |
|
89 --pure-version) |
|
90 pure_version; exit 0;; |
|
91 --app-drop-link) |
|
92 APPLICATION_LINK=$2 |
|
93 APPLICATION_CLAUSE="set position of item \"Applications\" to {$2, $3} |
|
94 " |
|
95 shift; shift; shift;; |
|
96 --eula) |
|
97 EULA_RSRC=$2 |
|
98 shift; shift;; |
|
99 -*) |
|
100 echo "Unknown option $1. Run with --help for help." |
|
101 exit 1;; |
|
102 esac |
|
103 done |
|
104 |
|
105 test -z "$2" && { |
|
106 echo "Not enough arguments. Invoke with --help for help." |
|
107 exit 1 |
|
108 } |
|
109 |
|
110 DMG_PATH="$1" |
|
111 DMG_DIRNAME="$(dirname "$DMG_PATH")" |
|
112 DMG_DIR="$(cd $DMG_DIRNAME > /dev/null; pwd)" |
|
113 DMG_NAME="$(basename "$DMG_PATH")" |
|
114 DMG_TEMP_NAME="$DMG_DIR/rw.${DMG_NAME}" |
|
115 SRC_FOLDER="$(cd "$2" > /dev/null; pwd)" |
|
116 test -z "$VOLUME_NAME" && VOLUME_NAME="$(basename "$DMG_PATH" .dmg)" |
|
117 |
|
118 AUX_PATH="$(dirname $0)/support" |
|
119 |
|
120 test -d "$AUX_PATH" || { |
|
121 echo "Cannot find support directory: $AUX_PATH" |
|
122 exit 1 |
|
123 } |
|
124 |
|
125 if [ -f "$SRC_FOLDER/.DS_Store" ]; then |
|
126 echo "Deleting any .DS_Store in source folder" |
|
127 rm "$SRC_FOLDER/.DS_Store" |
|
128 fi |
|
129 |
|
130 # Create the image |
|
131 echo "Creating disk image..." |
|
132 test -f "${DMG_TEMP_NAME}" && rm -f "${DMG_TEMP_NAME}" |
|
133 ACTUAL_SIZE=`du -sm "$SRC_FOLDER" | sed -e 's/ .*//g'` |
|
134 DISK_IMAGE_SIZE=$(expr $ACTUAL_SIZE + 20) |
|
135 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}" |
|
136 |
|
137 # mount it |
|
138 echo "Mounting disk image..." |
|
139 MOUNT_DIR="/Volumes/${VOLUME_NAME}" |
|
140 |
|
141 # try unmount dmg if it was mounted previously (e.g. developer mounted dmg, installed app and forgot to unmount it) |
|
142 echo "Unmounting disk image..." |
|
143 DEV_NAME=$(hdiutil info | egrep '^/dev/' | sed 1q | awk '{print $1}') |
|
144 test -d "${MOUNT_DIR}" && hdiutil detach "${DEV_NAME}" |
|
145 |
|
146 echo "Mount directory: $MOUNT_DIR" |
|
147 DEV_NAME=$(hdiutil attach -readwrite -noverify -noautoopen "${DMG_TEMP_NAME}" | egrep '^/dev/' | sed 1q | awk '{print $1}') |
|
148 echo "Device name: $DEV_NAME" |
|
149 |
|
150 if ! test -z "$BACKGROUND_FILE"; then |
|
151 echo "Copying background file..." |
|
152 test -d "$MOUNT_DIR/.background" || mkdir "$MOUNT_DIR/.background" |
|
153 cp "$BACKGROUND_FILE" "$MOUNT_DIR/.background/$BACKGROUND_FILE_NAME" |
|
154 fi |
|
155 |
|
156 if ! test -z "$APPLICATION_LINK"; then |
|
157 echo "making link to Applications dir" |
|
158 echo $MOUNT_DIR |
|
159 ln -s /Applications "$MOUNT_DIR/Applications" |
|
160 fi |
|
161 |
|
162 if ! test -z "$VOLUME_ICON_FILE"; then |
|
163 echo "Copying volume icon file '$VOLUME_ICON_FILE'..." |
|
164 cp "$VOLUME_ICON_FILE" "$MOUNT_DIR/.VolumeIcon.icns" |
|
165 SetFile -c icnC "$MOUNT_DIR/.VolumeIcon.icns" |
|
166 fi |
|
167 |
|
168 # run applescript |
|
169 APPLESCRIPT=$(mktemp -t createdmg) |
|
170 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" |
|
171 |
|
172 echo "Running Applescript: /usr/bin/osascript \"${APPLESCRIPT}\" \"${VOLUME_NAME}\"" |
|
173 "/usr/bin/osascript" "${APPLESCRIPT}" "${VOLUME_NAME}" || true |
|
174 echo "Done running the applescript..." |
|
175 sleep 4 |
|
176 |
|
177 rm "$APPLESCRIPT" |
|
178 |
|
179 # make sure it's not world writeable |
|
180 echo "Fixing permissions..." |
|
181 chmod -Rf go-w "${MOUNT_DIR}" &> /dev/null || true |
|
182 echo "Done fixing permissions." |
|
183 |
|
184 # make the top window open itself on mount: |
|
185 echo "Blessing started" |
|
186 bless --folder "${MOUNT_DIR}" --openfolder "${MOUNT_DIR}" |
|
187 echo "Blessing finished" |
|
188 |
|
189 if ! test -z "$VOLUME_ICON_FILE"; then |
|
190 # tell the volume that it has a special file attribute |
|
191 SetFile -a C "$MOUNT_DIR" |
|
192 fi |
|
193 |
|
194 # unmount |
|
195 echo "Unmounting disk image..." |
|
196 hdiutil detach "${DEV_NAME}" |
|
197 |
|
198 # compress image |
|
199 echo "Compressing disk image..." |
|
200 hdiutil convert "${DMG_TEMP_NAME}" -format UDZO -imagekey zlib-level=9 -o "${DMG_DIR}/${DMG_NAME}" |
|
201 rm -f "${DMG_TEMP_NAME}" |
|
202 |
|
203 # adding EULA resources |
|
204 if [ ! -z "${EULA_RSRC}" -a "${EULA_RSRC}" != "-null-" ]; then |
|
205 echo "adding EULA resources" |
|
206 "${AUX_PATH}/dmg-license.py" "${DMG_DIR}/${DMG_NAME}" "${EULA_RSRC}" |
|
207 fi |
|
208 |
|
209 echo "Disk image done" |
|
210 exit 0 |