]> err.no Git - sope/blob - maintenance/make-osxpkg.sh
added Changes file for 4.5.4=>4.5.5
[sope] / maintenance / make-osxpkg.sh
1 #!/bin/sh
2 #
3 # make-osxpkg.sh
4 #
5 # Create a MacOSX Installer package for a given GNUstep directory. It does so
6 # by installing the results in a certain directory and then running the
7 # necessary packaging commands.
8 #
9
10 PKG_NAME="$1"
11
12 oldpwd="$PWD"
13 PKG_BUILD_DIR="$PWD/osxpkgbuild"
14 PKG_DIR="$PKG_BUILD_DIR/${PKG_NAME}.pkg"
15 PKG_RSRC_DIR="$PKG_BUILD_DIR/${PKG_NAME}.pkg/Contents/Resources"
16 PKG_VERSION="4.5"
17 ROOT_DIR="$PKG_BUILD_DIR/root"
18
19 CHECK_XML="yes"
20 PLIST_DT_ID="-//Apple Computer//DTD PLIST 1.0//EN"
21 PLIST_DT_LOC="http://www.apple.com/DTDs/PropertyList-1.0.dtd"
22 INSTALLER_FORMAT_KEY="0.10000000149011612"
23
24 BACKGROUND_TIFF="../maintenance/package-background.tiff"
25 LICENSE_FILE="../maintenance/License.rtf"
26 WELCOME_FILE="../maintenance/Welcome.rtf"
27
28 MKDIRS="mkdirhier"
29 CHMOD="chmod"
30 CHOWN="chown"
31 CHGRP="chgrp"
32 SUDO="sudo"
33 RM_R="rm -r"
34
35
36 # ****************************** options ******************************
37
38 # if we set this to 'yes', we get no 'upgrade' button on "reinstalls"
39 PKG_IS_RELOCATABLE=no
40
41 PKG_INSTALLFAT=yes
42
43 # RootAuthorization / AdminAuthorization
44 PKG_AUTHORIZATION=RootAuthorization
45
46
47 # ****************************** usage ********************************
48
49 function usage() {
50   cat <<_ACEOF
51 make-osxpkg.sh <pkgname>
52 _ACEOF
53 }
54
55
56 # ****************************** validate cmdline args ****************
57
58 function validateArgs() {
59   if test "x$PKG_NAME" = "x"; then
60     usage;
61     exit 1
62   fi
63 }
64
65
66 # ****************************** prepare/cleanup tmpfiles *************
67
68 function prepareTmpDirs() {
69   if test -d $PKG_BUILD_DIR; then
70     echo -n "  deleting old builddir: $PKG_BUILD_DIR .."
71     ${SUDO} ${RM_R} $PKG_BUILD_DIR
72     echo ".. done."
73   fi
74
75   echo -n "  preparing temporary builddir .."
76   ${MKDIRS} "${PKG_BUILD_DIR}"
77   ${MKDIRS} "${PKG_DIR}"
78   ${MKDIRS} "${PKG_RSRC_DIR}"
79   ${MKDIRS} "${PKG_RSRC_DIR}/English.lproj"
80   ${MKDIRS} "${ROOT_DIR}"
81   ${MKDIRS} "${ROOT_DIR}/Library/Frameworks"
82   echo ".. done: $PKG_BUILD_DIR."
83 }
84
85 function fixUpPermissions() {
86   echo -n "  fixing permissions in builddir (requires sudo) .."
87   ${SUDO} ${CHOWN} -R root  "${ROOT_DIR}"
88   ${SUDO} ${CHGRP} -R admin "${ROOT_DIR}"
89   ${SUDO} ${CHMOD} -R 755   "${ROOT_DIR}"
90   ${SUDO} ${CHMOD} u+t   "${ROOT_DIR}"
91   ${SUDO} ${CHMOD} u+t   "${ROOT_DIR}/Library"
92   echo ".. done."
93 }
94
95 function cleanupTmpDirs() {
96   if test -d $PKG_BUILD_DIR; then
97     echo -n "  deleting builddir: $PKG_BUILD_DIR .."
98     rm -r $PKG_BUILD_DIR
99     echo ".. done."
100   fi
101 }
102
103
104 # ****************************** install ******************************
105
106 function installIntoTmpDirs() {
107   echo -n "  install sources (log in ${PKG_BUILD_DIR}/install.log) .."
108   make -s FRAMEWORK_INSTALL_DIR="${ROOT_DIR}/Library/Frameworks" \
109     shared=yes frameworks=yes install \
110     >${PKG_BUILD_DIR}/install.log 2>&1
111   echo ".. done."
112 }
113
114
115 # ****************************** pax archive **************************
116
117 function makePaxArchive() {
118   echo -n "  gen archive .."
119   cd "${ROOT_DIR}"
120   pax -w . | gzip -c >${PKG_DIR}/Contents/Archive.pax.gz
121
122   cd ${PKG_DIR}/Contents/Resources
123   ln -s ../Archive.pax.gz "${PKG_NAME}.pax.gz"
124   cd "$oldpwd"
125   echo ".. done: ${PKG_DIR}/Contents/Archive.pax.gz"
126 }
127
128
129 # ****************************** bom/sizes ****************************
130
131 function generateBoM() {
132   echo -n "  gen BoM file .."
133   cd "${ROOT_DIR}"
134   mkbom . "${PKG_DIR}/Contents/Archive.bom"
135   
136   cd ${PKG_DIR}/Contents/Resources
137   ln -s ../Archive.bom "${PKG_NAME}.bom"
138   cd "$oldpwd"
139   echo ".. done."
140 }
141
142 function calcSizes() {
143   echo -n "  calculate sizes .."
144   size_uncompressed="`du -sk $ROOT_DIR | cut -f 1`"
145   size_compressed="`du -sk $PKG_DIR | cut -f 1`"
146   numfiles="`find $ROOT_DIR | wc -l`"
147   numfiles="`echo $numfiles - 1 | bc`"
148   echo ".. done (size=${size_compressed}K/${size_uncompressed}K, #$numfiles)."
149 }
150
151 function generateSizes() {
152   echo -n "  gen sizes file .."
153   cd "${ROOT_DIR}"
154   echo "NumFiles       $numfiles"          >${PKG_DIR}/Contents/Archive.sizes
155   echo "InstalledSize  $size_uncompressed" >>${PKG_DIR}/Contents/Archive.sizes
156   echo "CompressedSize $size_compressed"   >>${PKG_DIR}/Contents/Archive.sizes
157   
158   cd ${PKG_DIR}/Contents/Resources
159   ln -s ../Archive.sizes "${PKG_NAME}.sizes"
160   cd "$oldpwd"
161   echo ".. done."
162 }
163
164
165 # ****************************** info files ***************************
166
167 function plistWriteString() {
168   echo "    <key>$1</key>"
169   echo "    <string>$2</string>"
170 }
171 function plistWriteInt() {
172   echo "    <key>$1</key>"
173   echo "    <integer>`echo $2`</integer>"
174 }
175 function plistWriteReal() {
176   echo "    <key>$1</key>"
177   echo "    <real>`echo $2`</real>"
178 }
179 function plistWriteDate() {
180   echo "    <key>$1</key>"
181   echo "    <date>$2</date>"
182 }
183 function plistWriteBool() {
184   echo "    <key>$1</key>"
185   echo "    <$2/>"
186 }
187
188
189 function genInfoPList() {
190   # http://developer.apple.com/documentation/DeveloperTools/Conceptual/
191   #   SoftwareDistribution/Concepts/sd_pkg_flags.html
192   F="${PKG_DIR}/Contents/Info.plist"
193   echo -n "  gen Info.plist: $F .."
194   
195   echo >$F  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
196   echo >>$F "<!DOCTYPE plist PUBLIC \"${PLIST_DT_ID}\" \"${PLIST_DT_LOC}\">"
197   echo >>$F "<plist version=\"1.0\">"
198   echo >>$F "  <dict>"
199   
200   plistWriteString >>$F CFBundleGetInfoString "${PKG_NAME} ${PKG_VERSION}"
201   plistWriteString >>$F CFBundleIdentifier "org.opengroupware.pkg.${PKG_NAME}"
202   plistWriteString >>$F CFBundleName       "${PKG_NAME}"
203   plistWriteString >>$F CFBundleShortVersionString "${PKG_VERSION}"
204   
205   plistWriteString >>$F IFMajorVersion 4
206   plistWriteString >>$F IFMinorVersion 5
207   
208   plistWriteDate   >>$F IFPkgBuildDate "`date -u +%Y-%m-%dT%H:%M:%SZ`"
209   plistWriteString >>$F IFPkgBuildVersion                 "${PKG_VERSION}"
210   plistWriteBool   >>$F IFPkgFlagAllowBackRev             true
211
212   # allowed: AdminAuthorization, RootAuthorization, ??
213   plistWriteString >>$F IFPkgFlagAuthorizationAction      ${PKG_AUTHORIZATION}
214
215   plistWriteString >>$F IFPkgFlagBackgroundAlignment      topright
216   plistWriteString >>$F IFPkgFlagBackgroundScaling        none
217   plistWriteString >>$F IFPkgFlagDefaultLocation          /
218   plistWriteBool   >>$F IFPkgFlagFollowLinks              true
219   
220   if test "x${PKG_INSTALLFAT}" = "xyes"; then
221     plistWriteBool   >>$F IFPkgFlagInstallFat             true
222   else
223     plistWriteBool   >>$F IFPkgFlagInstallFat             false
224   fi
225
226   plistWriteInt    >>$F IFPkgFlagInstalledSize            $size_uncompressed
227   plistWriteBool   >>$F IFPkgFlagIsRequired               false
228   plistWriteBool   >>$F IFPkgFlagOverwritePermissions     false
229
230   if test "x${PKG_IS_RELOCATABLE}" = "xyes"; then
231     plistWriteBool   >>$F IFPkgFlagRelocatable            true
232   else
233     plistWriteBool   >>$F IFPkgFlagRelocatable            false
234   fi
235
236   plistWriteString >>$F IFPkgFlagRestartAction            NoRestart
237   plistWriteBool   >>$F IFPkgFlagRootVolumeOnly           false
238   plistWriteBool   >>$F IFPkgFlagUpdateInstalledLanguages false
239   plistWriteBool   >>$F IFPkgFlagUseUserMask              false
240   plistWriteReal   >>$F IFPkgFormatVersion "${INSTALLER_FORMAT_KEY}"
241   plistWriteInt    >>$F IFPkgPayloadFileCount             $numfiles
242   
243   echo >>$F "  </dict>"
244   echo >>$F "</plist>"
245   if test "x$CHECK_XML" = "xyes"; then
246     xmllint --noout $F
247   fi
248   
249   echo ".. done."
250 }
251
252
253 function genBundleVersions() {
254   F="${PKG_RSRC_DIR}/BundleVersions.plist"
255   echo "  gen bundle versions: $F .."
256   
257   echo >$F  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
258   echo >>$F "<!DOCTYPE plist PUBLIC \"${PLIST_DT_ID}\" \"${PLIST_DT_LOC}\">"
259   echo >>$F "<plist version=\"1.0\">"
260   echo >>$F "  <dict>"
261   
262
263   frameworks=`find "${ROOT_DIR}" -type d -name "*.framework"`
264   for frameworkpath in $frameworks; do
265     frameworkvfile="`find $frameworkpath -type f -name Version | head -n 1`"
266     if test "x$frameworkvfile" != "x"; then
267       relfwpath="`echo $frameworkpath | sed sX${ROOT_DIR}/XXg`"
268       
269       echo >>$F "    <key>${relfwpath}</key>"
270       echo >>$F "    <dict>"
271       echo >>$F "      <key>BuildVersion</key>"
272       echo >>$F "      <string>1</string>" # TODO
273       echo >>$F "      <key>CFBundleShortVersionString</key>"
274       echo >>$F "      <string>${PKG_VERSION}</string>"
275       echo >>$F "      <key>ProjectName</key>"
276       echo >>$F "      <string>`basename -s .framework $relfwpath`</string>"
277       echo >>$F "      <key>SourceVersion</key>"
278       echo >>$F "      <string>${PKG_VERSION}</string>" # TODO
279       echo >>$F "    </dict>"
280     else
281       echo "    Note: no Version file in framework `basename $frameworkpath`"
282     fi
283   done
284   
285   echo >>$F "  </dict>"
286   echo >>$F "</plist>"
287   if test "x$CHECK_XML" = "xyes"; then
288     xmllint --noout $F
289   fi
290   echo "  generated: $F."
291 }
292
293 function genEnDescription() {
294   F="${PKG_RSRC_DIR}/English.lproj/Description.plist"
295   echo -n "  gen description plist: $F .."
296   
297   echo >$F  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
298   echo >>$F "<!DOCTYPE plist PUBLIC \"${PLIST_DT_ID}\" \"${PLIST_DT_LOC}\">"
299   echo >>$F "<plist version=\"1.0\">"
300   echo >>$F "  <dict>"
301   
302   plistWriteString >>$F IFPkgDescriptionDescription "${PKG_NAME}"
303   plistWriteString >>$F IFPkgDescriptionTitle       "${PKG_NAME}"
304   plistWriteString >>$F IFPkgDescriptionVersion     "${PKG_VERSION}"
305   
306   echo >>$F "  </dict>"
307   echo >>$F "</plist>"
308   if test "x$CHECK_XML" = "xyes"; then
309     xmllint --noout $F
310   fi
311   echo ".. done."
312 }
313
314 function genInfoFile() {
315   F="${PKG_RSRC_DIR}/English.lproj/${PKG_NAME}.info"
316   echo -n "  gen info file: $F .."
317   
318   echo >$F  "Title                 ${PKG_NAME}"
319   echo >>$F "Version               ${PKG_VERSION}"
320   echo >>$F "Description           ${PKG_VERSION}"
321   
322   echo >>$F "Require Reboot        NO"  # TODO: consolidate
323   echo >>$F "OverwritePermissions  NO"  # TODO: consolidate
324   echo >>$F "UseUserMask           NO"  # TODO: consolidate
325   echo >>$F "RootVolumeOnly        NO"  # TODO: consolidate
326
327   if test "x${PKG_AUTHORIZATION}" = "x"; then
328     echo >>$F "NeedsAuthorization    NO"
329   else
330     # need to check Admin/Root?
331     echo >>$F "NeedsAuthorization    YES"
332   fi
333
334   echo >>$F "DefaultLocation       /"   # TODO: consolidate
335   
336   if test "x${PKG_IS_RELOCATABLE}" = "xyes"; then
337     echo >>$F "Relocatable           YES"
338   else
339     echo >>$F "Relocatable           NO"
340   fi
341   
342   if test "x${PKG_INSTALLFAT}" = "xyes"; then
343     echo >>$F "Install Fat           YES"
344   else
345     echo >>$F "Install Fat           NO"
346   fi
347   
348   echo >>$F "LibrarySubdirectory   Standard"
349   
350   echo ".. done."
351 }
352
353 function genPkgInfoFile() {
354   F="${PKG_DIR}/Contents/PkgInfo"
355   echo -n "  gen PkgInfo: $F .."
356   echo >$F "pmkrpkg1"
357   echo ".. done."
358 }
359
360 function genPkgVersionFile() {
361   F="${PKG_RSRC_DIR}/package_version"
362   echo -n "  gen package_version: $F .."
363   echo >$F  "major: 4"
364   echo >>$F "minor: 5"
365   echo ".. done."
366 }
367
368
369 # ****************************** resources ****************************
370
371 function copyBackgroundImage() {
372   if test -f "${BACKGROUND_TIFF}"; then
373     cp "${BACKGROUND_TIFF}" "${PKG_RSRC_DIR}/background.tiff"
374   else
375     echo "ERROR: did not find background image: ${BACKGROUND_TIFF}"
376   fi
377 }
378
379 function copyLicenseFile() {
380   if test -f "${LICENSE_FILE}"; then
381     cp "${LICENSE_FILE}" "${PKG_RSRC_DIR}/English.lproj/License.rtf"
382   else
383     echo "ERROR: did not find file: ${LICENSE_FILE}"
384   fi
385 }
386 function copyWelcomeFile() {
387   if test -f "${WELCOME_FILE}"; then
388     cp "${WELCOME_FILE}" "${PKG_RSRC_DIR}/English.lproj/Welcome.rtf"
389   else
390     echo "ERROR: did not find file: ${WELCOME_FILE}"
391   fi
392 }
393
394
395 # ****************************** debugging ****************************
396
397 function debugShowResults() {
398   echo ""
399   echo "prepared contents:"
400   find -s $PKG_BUILD_DIR \
401   | sed "sX${PKG_BUILD_DIR}/X  Xg"
402 }
403
404
405 # ****************************** sudo *********************************
406
407 function ensureSudo() {
408   # this will bring up the 'sudo' authentication
409   if test "x$USER" != "xroot"; then
410     echo "We need to run some commands using 'sudo', so please enter your "
411     echo "credentials when being asked for them (unless you already did so)"
412     sudo touch /tmp/osx-pkg-sudo-tmp
413     sudo rm    /tmp/osx-pkg-sudo-tmp
414   fi
415 }
416
417
418 # ****************************** running ******************************
419
420 echo "Building MacOSX Installer.app package $PKG_NAME.pkg .."
421 validateArgs;
422
423 ensureSudo;
424
425 prepareTmpDirs;
426 installIntoTmpDirs;
427 fixUpPermissions;
428
429 makePaxArchive;
430 generateBoM;
431
432 calcSizes;
433 generateSizes;
434
435 genInfoPList;
436 genInfoFile;
437 genBundleVersions;
438 genEnDescription;
439 genPkgInfoFile;
440 genPkgVersionFile;
441
442 copyBackgroundImage;
443 copyLicenseFile;
444 copyWelcomeFile;
445
446
447 # debugging, print results
448 #debugShowResults;
449
450
451 # move results
452 if test -d "$PKG_DIR"; then
453   if test -d "${oldpwd}/${PKG_NAME}.pkg"; then
454     rm -rf "${oldpwd}/${PKG_NAME}.pkg"
455   fi
456   mv "$PKG_DIR" "${oldpwd}/${PKG_NAME}.pkg"
457 else
458   echo "ERROR: did not find package: $PKG_DIR"
459 fi
460
461 #cleanupTmpDirs;