]> err.no Git - sope/blob - maintenance/make-osxmpkg.sh
improved versioning support
[sope] / maintenance / make-osxmpkg.sh
1 #!/bin/sh
2 #
3 # make-osxmpkg.sh
4 #
5 # Create a MacOSX Installer *multi* package for SOPE.
6 #
7
8 PKG_NAME="$1"
9
10 oldpwd="$PWD"
11 PKG_BUILD_DIR="$PWD/osxpkgbuild"
12 PKG_DIR="$PKG_BUILD_DIR/${PKG_NAME}.mpkg"
13 PKG_RSRC_DIR="$PKG_BUILD_DIR/${PKG_NAME}.mpkg/Contents/Resources"
14
15 # TODO: make that arguments
16 PKG_MAJOR_VERSION=4
17 PKG_MINOR_VERSION=5
18 PKG_SUBMINOR_VERSION=trunk
19
20 PKG_VERSION="${PKG_MAJOR_VERSION}.${PKG_MINOR_VERSION}.${PKG_SUBMINOR_VERSION}"
21 ROOT_DIR="$PKG_BUILD_DIR/Packages"
22
23 CHECK_XML="yes"
24 PLIST_DT_ID="-//Apple Computer//DTD PLIST 1.0//EN"
25 PLIST_DT_LOC="http://www.apple.com/DTDs/PropertyList-1.0.dtd"
26 INSTALLER_FORMAT_KEY="0.10000000149011612"
27
28 BACKGROUND_TIFF="maintenance/package-background.tiff"
29 LICENSE_FILE="maintenance/License.rtf"
30 WELCOME_FILE="maintenance/Welcome.rtf"
31
32 MKDIRS="mkdirhier"
33 CHMOD="chmod"
34 CHOWN="chown"
35 CHGRP="chgrp"
36 SUDO="sudo"
37 RM_R="rm -r"
38
39
40 # ****************************** options ******************************
41
42 # if we set this to 'yes', we get no 'upgrade' button on "reinstalls"
43 PKG_IS_RELOCATABLE=no
44
45 # RootAuthorization / AdminAuthorization
46 PKG_AUTHORIZATION=RootAuthorization
47
48
49 # ****************************** usage ********************************
50
51 function usage() {
52   cat <<_ACEOF
53 make-osxmpkg.sh <pkgname>
54 _ACEOF
55 }
56
57
58 # ****************************** validate cmdline args ****************
59
60 function validateArgs() {
61   if test "x$PKG_NAME" = "x"; then
62     usage;
63     exit 1
64   fi
65 }
66
67
68 # ****************************** prepare/cleanup tmpfiles *************
69
70 function prepareTmpDirs() {
71   if test -d $PKG_BUILD_DIR; then
72     echo -n "  deleting old builddir: $PKG_BUILD_DIR .."
73     ${SUDO} ${RM_R} $PKG_BUILD_DIR
74     echo ".. done."
75   fi
76
77   echo -n "  preparing temporary builddir .."
78   ${MKDIRS} "${PKG_BUILD_DIR}"
79   ${MKDIRS} "${PKG_DIR}"
80   ${MKDIRS} "${PKG_RSRC_DIR}"
81   ${MKDIRS} "${PKG_RSRC_DIR}/English.lproj"
82   ${MKDIRS} "${ROOT_DIR}"
83   echo ".. done: $PKG_BUILD_DIR."
84 }
85
86 function fixUpPermissions() {
87   echo -n "  fixing permissions in builddir (requires sudo) .."
88   ${SUDO} ${CHOWN} -R root  "${ROOT_DIR}"
89   ${SUDO} ${CHGRP} -R admin "${ROOT_DIR}"
90   ${SUDO} ${CHMOD} -R 755   "${ROOT_DIR}"
91   ${SUDO} ${CHMOD} u+t   "${ROOT_DIR}"
92   ${SUDO} ${CHMOD} u+t   "${ROOT_DIR}/Library"
93   echo ".. done."
94 }
95
96 function cleanupTmpDirs() {
97   if test -d $PKG_BUILD_DIR; then
98     echo -n "  deleting builddir: $PKG_BUILD_DIR .."
99     rm -r $PKG_BUILD_DIR
100     echo ".. done."
101   fi
102 }
103
104
105 # ****************************** info files ***************************
106
107 function plistWriteString() {
108   echo "    <key>$1</key>"
109   echo "    <string>$2</string>"
110 }
111 function plistWriteInt() {
112   echo "    <key>$1</key>"
113   echo "    <integer>`echo $2`</integer>"
114 }
115 function plistWriteReal() {
116   echo "    <key>$1</key>"
117   echo "    <real>`echo $2`</real>"
118 }
119 function plistWriteDate() {
120   echo "    <key>$1</key>"
121   echo "    <date>$2</date>"
122 }
123 function plistWriteBool() {
124   echo "    <key>$1</key>"
125   echo "    <$2/>"
126 }
127
128 function genSubPkgEntry {
129   echo "      <dict>"
130   echo "        <key>IFPkgFlagPackageLocation</key>"
131   echo "        <string>$1</string>"
132   echo "        <key>IFPkgFlagPackageSelection</key>"
133   echo "        <string>$2</string>"
134   echo "      </dict>"
135 }
136
137 function genInfoPList() {
138   # http://developer.apple.com/documentation/DeveloperTools/Conceptual/
139   #   SoftwareDistribution/Concepts/sd_pkg_flags.html
140   F="${PKG_DIR}/Contents/Info.plist"
141   echo -n "  gen Info.plist: $F .."
142   
143   echo >$F  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
144   echo >>$F "<!DOCTYPE plist PUBLIC \"${PLIST_DT_ID}\" \"${PLIST_DT_LOC}\">"
145   echo >>$F "<plist version=\"1.0\">"
146   echo >>$F "  <dict>"
147
148   plistWriteString >>$F IFMajorVersion ${PKG_MAJOR_VERSION}
149   plistWriteString >>$F IFMinorVersion ${PKG_MINOR_VERSION}
150
151   plistWriteDate   >>$F IFPkgBuildDate "`date -u +%Y-%m-%dT%H:%M:%SZ`"
152   plistWriteString >>$F IFPkgBuildVersion                 "${PKG_VERSION}"
153   #plistWriteBool   >>$F IFPkgFlagAllowBackRev             true
154
155   # allowed: AdminAuthorization, RootAuthorization, ??
156   plistWriteString >>$F IFPkgFlagAuthorizationAction      ${PKG_AUTHORIZATION}
157   
158   plistWriteString >>$F IFPkgFlagBackgroundAlignment      topright
159   plistWriteString >>$F IFPkgFlagBackgroundScaling        none
160   plistWriteString >>$F IFPkgFlagDefaultLocation          /
161   #plistWriteBool   >>$F IFPkgFlagFollowLinks              true
162
163   #plistWriteBool   >>$F IFPkgFlagInstallFat               true
164
165   #plistWriteBool   >>$F IFPkgFlagIsRequired               false
166   #plistWriteBool   >>$F IFPkgFlagOverwritePermissions     false
167
168   if test "x${PKG_IS_RELOCATABLE}" = "xyes"; then
169     plistWriteBool   >>$F IFPkgFlagRelocatable            true
170   else
171     plistWriteBool   >>$F IFPkgFlagRelocatable            false
172   fi
173   
174   plistWriteString >>$F IFPkgFlagRestartAction            NoRestart
175   plistWriteBool   >>$F IFPkgFlagRootVolumeOnly           false
176   plistWriteBool   >>$F IFPkgFlagUpdateInstalledLanguages false
177   #plistWriteBool   >>$F IFPkgFlagUseUserMask              false
178   plistWriteReal   >>$F IFPkgFormatVersion "${INSTALLER_FORMAT_KEY}"
179   
180   plistWriteString >>$F IFPkgFlagComponentDirectory "../Packages"
181   
182   # generate sub-package list
183   echo >>$F "    <key>IFPkgFlagPackageList</key>"
184   echo >>$F "    <array>"
185   for i in sope-xml sope-core sope-mime sope-appserver; do
186     genSubPkgEntry >>$F $i.pkg required
187   done
188   for i in sope-ical sope-ldap sope-gdl1 sopex; do
189     genSubPkgEntry >>$F $i.pkg selected
190   done
191   echo >>$F "    </array>"
192   
193   # close plist
194   echo >>$F "  </dict>"
195   echo >>$F "</plist>"
196   if test "x$CHECK_XML" = "xyes"; then
197     xmllint --noout $F
198   fi
199   
200   echo ".. done."
201 }
202
203 function genVersionPList() {
204   # http://developer.apple.com/documentation/DeveloperTools/Conceptual/
205   #   SoftwareDistribution/Concepts/sd_pkg_flags.html
206   F="${PKG_DIR}/Contents/version.plist"
207   echo -n "  gen version.plist: $F .."
208   
209   echo >$F  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
210   echo >>$F "<!DOCTYPE plist PUBLIC \"${PLIST_DT_ID}\" \"${PLIST_DT_LOC}\">"
211   echo >>$F "<plist version=\"1.0\">"
212   echo >>$F "  <dict>"
213
214   # TODO: find out about BuildVersion
215   plistWriteString >>$F BuildVersion               4
216   
217   plistWriteString >>$F CFBundleShortVersionString "${PKG_VERSION}"
218   plistWriteString >>$F ProjectName                "${PKG_NAME}"
219   plistWriteString >>$F SourceVersion ${PKG_MAJOR_VERSION}${PKG_MINOR_VERSION}000
220   
221   # close plist
222   echo >>$F "  </dict>"
223   echo >>$F "</plist>"
224   if test "x$CHECK_XML" = "xyes"; then
225     xmllint --noout $F
226   fi
227   
228   echo ".. done."
229 }
230
231 function genEnDescription() {
232   F="${PKG_RSRC_DIR}/English.lproj/Description.plist"
233   echo -n "  gen description plist: $F .."
234   
235   echo >$F  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
236   echo >>$F "<!DOCTYPE plist PUBLIC \"${PLIST_DT_ID}\" \"${PLIST_DT_LOC}\">"
237   echo >>$F "<plist version=\"1.0\">"
238   echo >>$F "  <dict>"
239   
240   plistWriteString >>$F IFPkgDescriptionDescription "${PKG_NAME}"
241   plistWriteString >>$F IFPkgDescriptionTitle       "${PKG_NAME}"
242   plistWriteString >>$F IFPkgDescriptionVersion     "${PKG_VERSION}"
243   
244   echo >>$F "  </dict>"
245   echo >>$F "</plist>"
246   if test "x$CHECK_XML" = "xyes"; then
247     xmllint --noout $F
248   fi
249   echo ".. done."
250 }
251
252 function genInfoFile() {
253   F="${PKG_RSRC_DIR}/English.lproj/${PKG_NAME}.info"
254   echo -n "  gen info file: $F .."
255   
256   echo >$F  "Title                 ${PKG_NAME}"
257   echo >>$F "Version               ${PKG_VERSION}"
258   echo >>$F "Description           ${PKG_VERSION}"
259   
260   # TODO: find documentation for this one
261   # echo >>$F "PackageLocation      ../Packages"
262   echo >>$F "FastInstall          NO"
263   
264   echo >>$F "Require Reboot        NO"  # TODO: consolidate
265   echo >>$F "OverwritePermissions  NO"  # TODO: consolidate
266   echo >>$F "UseUserMask           NO"  # TODO: consolidate
267   echo >>$F "RootVolumeOnly        NO"  # TODO: consolidate
268
269   if test "x${PKG_AUTHORIZATION}" = "x"; then
270     echo >>$F "NeedsAuthorization    NO"
271   else
272     # need to check Admin/Root?
273     echo >>$F "NeedsAuthorization    YES"
274   fi
275   
276   echo >>$F "DefaultLocation       /"   # TODO: consolidate
277   
278   if test "x${PKG_IS_RELOCATABLE}" = "xyes"; then
279     echo >>$F "Relocatable           YES"
280   else
281     echo >>$F "Relocatable           NO"
282   fi
283   
284   #echo >>$F "Install Fat           YES" # TODO: consolidate
285   echo >>$F "LibrarySubdirectory   Standard"
286
287   GIOLDDIR="$PWD"  
288   cd "${PKG_RSRC_DIR}/English.lproj/"
289   ln -s "${PKG_NAME}.info" Install.info
290   cd "$GIOLDDIR"
291   echo ".. done."
292 }
293
294
295 function genPkgInfoFile() {
296   F="${PKG_DIR}/Contents/PkgInfo"
297   echo -n "  gen PkgInfo: $F .."
298   echo >$F "pmkrpkg1"
299   echo ".. done."
300 }
301
302 function genPkgVersionFile() {
303   F="${PKG_RSRC_DIR}/package_version"
304   echo -n "  gen package_version: $F .."
305   echo >$F  "major: ${PKG_MAJOR_VERSION}"
306   echo >>$F "minor: ${PKG_MINOR_VERSION}"
307   echo ".. done."
308 }
309
310 function genRequiredPkgs() {
311   F="${PKG_RSRC_DIR}/Install.list"
312   echo -n "  gen Install.list (requirements): $F .."
313   echo >$F  "BSD.pkg:required"
314   echo >>$F "BSDSDK.pkg:required"
315   echo >>$F "DeveloperTools.pkg:required"
316   echo ".. done."
317 }
318
319
320 # ****************************** resources ****************************
321
322 function copyBackgroundImage() {
323   if test -f "${BACKGROUND_TIFF}"; then
324     cp "${BACKGROUND_TIFF}" "${PKG_RSRC_DIR}/background.tiff"
325   else
326     echo "ERROR: did not find background image: ${BACKGROUND_TIFF}"
327   fi
328 }
329
330 function copyLicenseFile() {
331   if test -f "${LICENSE_FILE}"; then
332     cp "${LICENSE_FILE}" "${PKG_RSRC_DIR}/English.lproj/License.rtf"
333   else
334     echo "ERROR: did not find file: ${LICENSE_FILE}"
335   fi
336 }
337 function copyWelcomeFile() {
338   if test -f "${WELCOME_FILE}"; then
339     cp "${WELCOME_FILE}" "${PKG_RSRC_DIR}/English.lproj/Welcome.rtf"
340   else
341     echo "ERROR: did not find file: ${WELCOME_FILE}"
342   fi
343 }
344
345
346 # ****************************** debugging ****************************
347
348 function debugShowResults() {
349   echo ""
350   echo "prepared contents:"
351   find -s $PKG_BUILD_DIR \
352   | sed "sX${PKG_BUILD_DIR}/X  Xg"
353 }
354
355
356 # ****************************** sudo *********************************
357
358 function ensureSudo() {
359   # this will bring up the 'sudo' authentication
360   if test "x$USER" != "xroot"; then
361     echo "We need to run some commands using 'sudo', so please enter your "
362     echo "credentials when being asked for them (unless you already did so)"
363     sudo touch /tmp/osx-pkg-sudo-tmp
364     sudo rm    /tmp/osx-pkg-sudo-tmp
365   fi
366 }
367
368
369 # ****************************** sudo *********************************
370
371 function copyPackages() {
372   for i in */*.pkg; do
373     cp -R $i "${ROOT_DIR}"/
374   done
375 }
376
377
378 # ****************************** running ******************************
379
380 echo "Building SOPE MacOSX Installer.app multipackage $PKG_NAME.mpkg .."
381 validateArgs;
382
383 ensureSudo;
384
385 prepareTmpDirs;
386 copyPackages;
387
388 genInfoPList;
389 genVersionPList;
390 genEnDescription;
391 genInfoFile;
392 genPkgInfoFile;
393 genRequiredPkgs;
394 genPkgVersionFile;
395
396 copyBackgroundImage;
397 copyLicenseFile;
398 copyWelcomeFile;
399
400
401 # debugging, print results
402 debugShowResults;
403
404
405 #cleanupTmpDirs;