sip the graphics file for showing a logo
[sface.git] / macos / build-dmg.sh
1 #!/bin/sh
2
3 # PURPOSE
4 # package a combination of sfa+sface into a dmg install disk
5 # supports leopard and snow leopard
6
7 # REQUIREMENTS
8 # sface-skel-snow-leopard<arch>.dmg is the skeleton that has Qt and all the other third-party software
9 #   it is expected to be found in the local directory
10 #   otherwise, or if -f is specified, it gets fetched 
11 #     from http://mirror.onelab.eu/third-party/ 
12 # the script expects the taglevels for both sfa and sface, 
13 #   in order to retrieve the corresponding code and to label the resulting package properly
14 #   alternatively, a build-dir and tags file can be used instead
15
16 # NOTES
17 # we initially leveraged the first similar packaging initially made by Baris Metin
18 # as of sface-0.1-9 we have bootstrapped our own skeleton images, 
19 #   i.e. you can use vn as a skeleton for vn+1
20 # about that, the way the background image gets (or not) found 
21 #   on the final system is as follows 
22 #   before compressing the image, you should open the image through the finder
23 #   and tweak it, as described in http://el-tramo.be/guides/fancy-dmg
24 #   that's the raison d'ĂȘtre for the -i option
25 # basically: open two finder windows, one on the .backgrounf dir (use cmd-shift G)
26 #   and one on the image itself; then using Finder->view->show view options
27 #   drag the background image as appropriate
28 # the important point being that the filename for the background must 
29 #   exist - and so be the same - on the target system.
30 # that's why the image 'volname' is constant across versions
31
32 # the place to search for the  skeleton
33 SKEL_REPO=http://mirror.onelab.eu/third-party
34
35 # default is snow-leopard
36 DEFAULT_ARCH=snow-leopard
37 ALL_ARCHS="leopard snow-leopard"
38
39 # does not affect final dmg size as it's compressed
40 DISK_SIZE=100M
41
42 ########################################
43 COMMAND=$(basename $0)
44
45 # extract the tag part of a GITPATH
46 function git_url () { echo $1 | cut -d @ -f 1 ; }
47 function git_tag () { echo $1 | cut -d @ -f 2 ; }
48
49 # go in $dest and retrieve $path part of codebase based on gitpath, e.g.
50 # git_retrieve \
51 #     git://git.onelab.eu/sface.git@sface-0.1-5 
52 #     sface 
53 #     /Volumes/sface-skel-sn/sface.app/Contents/Resources/
54 # or, with the -f (-file) option:
55 # git_retrieve -f \
56 #     git://git.onelab.eu/sface.git@sface-0.1-5 
57 #     macos/appIcon.icns 
58 #     /Volumes/sface-skel-sn/sface.app/appIcon.icns 
59 function git_retrieve () {
60     filemode=""
61     case "$1" in -f|--file) filemode=true; shift;; esac
62     gitpath=$1; shift
63     path=$1; shift
64     dest=$1; shift
65
66     giturl=$(git_url $gitpath)
67     gittag=$(git_tag $gitpath)
68     if [ -z "$filemode" ] ; then
69         [ -d "$dest" ] || mkdir -p "$dest"
70         pushd "$dest" >& /dev/null
71         git archive --remote=${giturl} ${gittag} | tar -xf - ${path}
72         popd >& /dev/null
73     else
74         destdir=$(dirname "$dest")
75         [ -d "$destdir" ] || mkdir -p "$destdir"
76         git archive --remote=${giturl} ${gittag} | tar -xOf - ${path} > "${dest}"
77     fi
78 }
79
80 function die () {
81     echo "$@" "- exiting" 
82     exit 1
83 }
84
85 function package () {
86     
87     sface_GITPATH=$1; shift
88     sfa_GITPATH=$1; shift
89     arch=$1; shift
90
91     skel_name=sface-skel-${arch}
92     skel_dmg=./${skel_name}.dmg
93     skel_mnt="/Volumes/${skel_name}"
94
95     sfa_release=sfa-$(git_tag $sfa_GITPATH | sed -e s,sfa-,,)
96     sface_release=sface-$(git_tag $sface_GITPATH | sed -e s,sface-,,)
97     release=$(git_tag $sfa_GITPATH)-$(git_tag $sface_GITPATH)
98
99     img_name=${sface_release}-${sfa_release}-${arch}
100     img_dmg=./${img_name}.dmg
101     img_raw_dmg=./${img_name}.raw.dmg
102     img_mnt_name="sface ($arch)"
103     img_mnt="/Volumes/${img_mnt_name}"
104
105     # check we're clear
106     [ -f $img_dmg ] && die "output dmg $img_dmg already exists"
107     [ -f $img_raw_dmg ] && die "please clean up tmp file $img_raw_dmg"
108
109     if [ -n "$FORCE_DOWNLOAD" ] ; then
110         [ -d "$skel_mnt" ] && hdiutil unmount "$skel_mnt"
111         [ -f "$skel_dmg" ] && rm -f "$skel_dmg"
112     fi
113
114     # mount the skeleton if not yet avail.
115     if [ ! -d "$skel_mnt" ] ; then
116         # locate skel dmg
117         if [ ! -f $skel_dmg ] ; then
118             echo "Retrieving $skel_dmg from $SKEL_REPO"
119             curl -O $SKEL_REPO/$skel_dmg
120         fi
121         # needless to check for existence as curl will have created on anyway
122         echo "Mounting skeleton"
123         if ! hdiutil mount -quiet -mountpoint $skel_mnt $skel_dmg ; then
124             die "Could not mount $skel_dmg
125 Please check it is published at $SKEL_REPO
126 Also make sure to trash the current one before retrying"
127         fi
128     fi
129     [ -d "$skel_mnt" ] || die "Could not mount skeleton $skel_dmg"
130
131     # if image already mounted, it's an old run
132     [ -d "$img_mnt" ] && die "Image already mounted on $img_mnt"
133
134     echo "Initializing image ..."
135     hdiutil create -quiet -size $DISK_SIZE -fs HFS -volname "${img_mnt_name}" $img_raw_dmg 
136     hdiutil attach -readwrite -mount required "$img_raw_dmg"
137     
138     # copy skeleton as-is
139     echo "Populating from  skeleton.."
140     ( cd "$skel_mnt" ; find . 2> /dev/null | cpio --quiet -c -o) | ( cd "$img_mnt" ; cpio -diu )
141
142     # places relative to mount point
143     app=sface.app
144     # xxx tmp
145     skelapp_path=$(ls -d "$skel_mnt"/*.app)
146     skelapp=$(basename "$skelapp_path")
147     if [ "$skelapp" != "$app" ] ; then
148         mv "$img_mnt/$skelapp" "$img_mnt/$app"
149     fi
150     # unmount the skeleton
151     hdiutil unmount "$skel_mnt"
152
153     # 
154     resource_path=$app/Contents/Resources
155     bin_path=$app/Contents/MacOS
156
157     # retrieve sfa/sfa and sface/sface in the image
158     rm -rf "$img_mnt"/$resource_path/{sfa,sface}
159     git_retrieve $sfa_GITPATH sfa "$img_mnt"/$resource_path/
160     git_retrieve $sface_GITPATH sface "$img_mnt"/$resource_path/
161     # copy binaries from sface to the bin dir
162     for bin in sface.bin sface-run; do 
163         # don't use the --file mode as this loses the executable bit
164         git_retrieve $sface_GITPATH $bin "$img_mnt"/$bin_path
165     done
166
167     ### install background and app icons
168     # clean up any 'background' dir if exists
169     rm -rf "$img_mnt"/{,.}background 
170     git_retrieve --file $sface_GITPATH macos/graphic-install-background.png "$img_mnt"/.background/background.png
171     git_retrieve --file $sface_GITPATH macos/graphic-sfa.icns "$img_mnt"/$resource_path/appIcon.icns
172     # the volume icons won't work - who cares
173 #    git_retrieve --file $sface_GITPATH macos/graphic-vol-sface.icns "$img_mnt"/.background/volumeIcon.icns
174 #    git_retrieve --file $sface_GITPATH macos/graphic-vol-sface.png "$img_mnt"/.background/volumeIcon.png
175
176     # instantiate version
177     sed -e "s,@VERSIONTAG@,$sfa_release,g" -e "s,@SCMURL@,${sfa_GITPATH},g" \
178         "$img_mnt"/$resource_path/sfa/util/version.py.in > "$img_mnt"/$resource_path/sfa/util/version.py
179
180     # clean up just in case
181     find "$img_mnt" -name '*pyc' | xargs rm -f
182     find "$img_mnt" -name '*~' | xargs rm -f
183
184     if [ -n "$INTERACTIVE" ] ; then
185         echo "Please tweak icons layout in $img_mnt under Finder, and press enter when done ..."
186         read _
187     fi
188
189     hdiutil detach "$img_mnt"
190     rm -f $img_dmg
191     echo "Compressing..."
192     hdiutil convert -quiet -format UDZO -imagekey zlib-level=9 -o $img_dmg $img_raw_dmg 
193     # clean up the raw image
194     rm -f $img_raw_dmg
195
196     echo "=================================================="
197     echo "Install image ready in $img_dmg"
198     echo "You may publish it by running e.g."
199     echo "rsync -av $img_dmg root@build.onelab.eu:/build/sface"
200     echo "=================================================="
201
202 }
203
204 ########################################
205 # either provide a build dir and tags file
206 # or sface-GITPATH sfa-GITPATH 
207 function usage () {
208     echo "$COMMAND -b <build-dir> -t <tags-file>"
209     echo " or"
210     echo "$COMMAND -c <sface-GITPATH> -s <sfa-GITPATH>"
211     echo ""
212     echo "Common options"
213     echo " -i : interactive : let you align icons properly in the image before it gets wrapped"
214     echo " -f : force download of the skeleton package"
215     echo " -a leopard|snow-leopard"
216     echo " -A : run on all known archs"
217     echo " -n : dry-run"
218     echo " -v : verbose"
219     echo " -h : this help"
220 }
221
222 DEFAULT_BUILD_DIR=$HOME/git/build
223 DEFAULT_TAGS_FILE=onelab-k32-tags.mk
224
225 function main () {
226     while getopts "b:t:c:s:ifa:Anvh" opt ; do
227         case $opt in 
228             b) BUILD_DIR=$OPTARG;;
229             t) TAGS_FILE=$OPTARG;;
230             c) sface_GITPATH=$OPTARG;;
231             s) sfa_GITPATH=$OPTARG;;
232             i) INTERACTIVE=true;;
233             f) FORCE_DOWNLOAD=true;;
234             a) ARCHS="$ARCHS $OPTARG";;
235             A) ARCHS="leopard snow-leopard";;
236             n) dry_run=true;;
237             v) set -x;;
238             h) usage; exit 1 ;;
239         esac
240     done
241     shift $(($OPTIND - 1))
242
243     [ -z "$BUILD_DIR" ] && BUILD_DIR=$DEFAULT_BUILD_DIR
244     [ -z "$TAGS_FILE" ] && TAGS_FILE=$DEFAULT_TAGS_FILE
245     [ -z "$ARCHS" ] && ARCHS=$DEFAULT_ARCH
246     [[ -n "$@" ]] && { usage ; exit 1; }
247     if [ -z "$sface_GITPATH" ] ; then
248         sface_GITPATH=$(make -C $BUILD_DIR stage1=true PLDISTROTAGS=$TAGS_FILE +sface-GITPATH 2> /dev/null)
249         echo "Retrieved from $BUILD_DIR/$TAGS_FILE.."
250         echo " sface_GITPATH=$sface_GITPATH"
251     fi
252     if [ -z "$sfa_GITPATH" ] ; then
253         sfa_GITPATH=$(make -C $BUILD_DIR stage1=true PLDISTROTAGS=$TAGS_FILE +sfa-GITPATH 2> /dev/null)
254         echo "Retrieved from $BUILD_DIR/$TAGS_FILE.."
255         echo " sfa_GITPATH=$sfa_GITPATH"
256     fi
257     for ARCH in $ARCHS; do 
258         if [ -z "$dry_run" ] ; then
259             package $sface_GITPATH $sfa_GITPATH $ARCH
260         else
261             echo "Would run package $sface_GITPATH $sfa_GITPATH $ARCH"
262         fi
263     done
264         
265 }
266
267 main "$@"