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