unount skeleton as soon as not needed anymore
[sface.git] / macos / build-dmg.sh
index 930d55f..87fb1c7 100755 (executable)
@@ -3,22 +3,37 @@
 # PURPOSE
 # package a combination of sfa+sface into a snow leopard dmg install disk
 # 
-# NOTES
-# we leverage the first similar packaging initially made by Baris Metin
-# 
 # REQUIREMENTS
-# sface-skel-snow-leopard.dmg is the skeleton that has Qt and all the other third-party software
+# sface-skel-snow-leopard<arch>.dmg is the skeleton that has Qt and all the other third-party software
 #   it is expected to be found in the local directory
-#   otherwise it gets fetched at http://mirror.onelab.eu/third-party/ 
+#   otherwise, or if -f is specified, it gets fetched 
+#     from http://mirror.onelab.eu/third-party/ 
 # the script expects the taglevels for both sfa and sface, 
 #   in order to retrieve the corresponding code and to label the resulting package properly
-#
+#   alternatively, a build-dir and tags file can be used instead
+
+# NOTES
+# we initially leveraged the first similar packaging initially made by Baris Metin
+# as of sface-0.1-9 we have bootstrapped our own skeleton images, 
+#   i.e. you can use vn as a skeleton for vn+1
+# about that, the way the background image gets (or not) found 
+#   on the final system is as follows 
+#   before compressing the image, you should open the image through the finder
+#   and tweak it, as described in http://el-tramo.be/guides/fancy-dmg
+#   that's the raison d'ĂȘtre for the -i option
+# basically: open two finder windows, one on the .backgrounf dir (use cmd-shift G)
+#   and one on the image itself; then using Finder->view->show view options
+#   drag the background image as appropriate
+# the important point being that the filename for the background must 
+#   exist - and so be the same - on the target system.
+# that's why the image 'volname' is constant across versions
 
 # the place to search for the  skeleton
 SKEL_REPO=http://mirror.onelab.eu/third-party
 
-# hard-wired for snow-leopard for now
-arch=snow-leopard
+# default is snow-leopard
+DEFAULT_ARCH=snow-leopard
+ALL_ARCHS="leopard snow-leopard"
 
 # does not affect final dmg size as it's compressed
 DISK_SIZE=100M
@@ -50,14 +65,14 @@ function git_retrieve () {
     giturl=$(git_url $gitpath)
     gittag=$(git_tag $gitpath)
     if [ -z "$filemode" ] ; then
-       [ -d $dest ] || mkdir -p $dest
-       pushd $dest
+       [ -d "$dest" ] || mkdir -p "$dest"
+       pushd "$dest" >& /dev/null
        git archive --remote=${giturl} ${gittag} | tar -xf - ${path}
-       popd
+       popd >& /dev/null
     else
-       destdir=$(dirname $dest)
-       [ -d $destdir ] || mkdir -p $destdir
-       git archive --remote=${giturl} ${gittag} | tar -xOf - ${path} > ${dest}
+       destdir=$(dirname "$dest")
+       [ -d "$destdir" ] || mkdir -p "$destdir"
+       git archive --remote=${giturl} ${gittag} | tar -xOf - ${path} > "${dest}"
     fi
 }
 
@@ -70,10 +85,11 @@ function package () {
     
     sface_GITPATH=$1; shift
     sfa_GITPATH=$1; shift
+    arch=$1; shift
 
     skel_name=sface-skel-${arch}
     skel_dmg=./${skel_name}.dmg
-    skel_mnt=/Volumes/${skel_name}
+    skel_mnt="/Volumes/${skel_name}"
 
     sfa_release=sfa-$(git_tag $sfa_GITPATH | sed -e s,sfa-,,)
     sface_release=sface-$(git_tag $sface_GITPATH | sed -e s,sface-,,)
@@ -82,81 +98,105 @@ function package () {
     img_name=${sface_release}-${sfa_release}-${arch}
     img_dmg=./${img_name}.dmg
     img_raw_dmg=./${img_name}.raw.dmg
-    img_mnt=/Volumes/${img_name}
+    img_mnt_name="sface ($arch)"
+    img_mnt="/Volumes/${img_mnt_name}"
 
     # check we're clear
     [ -f $img_dmg ] && die "output dmg $img_dmg already exists"
     [ -f $img_raw_dmg ] && die "please clean up tmp file $img_raw_dmg"
 
+    if [ -n "$FORCE_DOWNLOAD" ] ; then
+       [ -d "$skel_mnt" ] && hdiutil unmount "$skel_mnt"
+       [ -f "$skel_dmg" ] && rm -f "$skel_dmg"
+    fi
+
     # mount the skeleton if not yet avail.
-    if [ ! -d $skel_mnt ] ; then
+    if [ ! -d "$skel_mnt" ] ; then
         # locate skel dmg
        if [ ! -f $skel_dmg ] ; then
            echo "Retrieving $skel_dmg from $SKEL_REPO"
            curl -O $SKEL_REPO/$skel_dmg
        fi
        # needless to check for existence as curl will have created on anyway
-       if ! hdiutil mount $skel_dmg ; then
+       echo "Mounting skeleton"
+       if ! hdiutil mount -quiet -mountpoint $skel_mnt $skel_dmg ; then
            die "Could not mount $skel_dmg
 Please check it is published at $SKEL_REPO
 Also make sure to trash the current one before retrying"
        fi
     fi
-    [ -d $skel_mnt ] || die "Could not mount skeleton $skel_dmg"
+    [ -d "$skel_mnt" ] || die "Could not mount skeleton $skel_dmg"
 
     # if image already mounted, it's an old run
-    [ -d $img_mnt ] && die "Image already mounted on $img_mnt"
-
-    hdiutil create -size $DISK_SIZE -fs HFS+J -volname ${img_name} $img_raw_dmg
-    hdiutil attach -readwrite -mount required $img_raw_dmg 
+    [ -d "$img_mnt" ] && die "Image already mounted on $img_mnt"
 
+    echo "Initializing image ..."
+    hdiutil create -quiet -size $DISK_SIZE -fs HFS -volname "${img_mnt_name}" $img_raw_dmg 
+    hdiutil attach -readwrite -mount required "$img_raw_dmg"
+    
     # copy skeleton as-is
-    tar -C $skel_mnt --exclude .Trashes -cf - . | tar -C $img_mnt -xf -
+    echo "Populating from  skeleton.."
+    ( cd "$skel_mnt" ; find . 2> /dev/null | cpio --quiet -c -o) | ( cd "$img_mnt" ; cpio -diu )
+
     # places relative to mount point
     app=sface.app
+    # xxx tmp
+    skelapp_path=$(ls -d "$skel_mnt"/*.app)
+    skelapp=$(basename "$skelapp_path")
+    if [ "$skelapp" != "$app" ] ; then
+       mv "$img_mnt/$skelapp" "$img_mnt/$app"
+    fi
+    # unmount the skeleton
+    hdiutil unmount "$skel_mnt"
+
+    # 
     resource_path=$app/Contents/Resources
     bin_path=$app/Contents/MacOS
-    icon_path=$app/Contents/Resources/
-    background_path=background
+
     # retrieve sfa/sfa and sface/sface in the image
-    git_retrieve $sfa_GITPATH sfa $img_mnt/$resource_path/
-    git_retrieve $sface_GITPATH sface $img_mnt/$resource_path/
+    rm -rf "$img_mnt"/$resource_path/{sfa,sface}
+    git_retrieve $sfa_GITPATH sfa "$img_mnt"/$resource_path/
+    git_retrieve $sface_GITPATH sface "$img_mnt"/$resource_path/
     # copy binaries from sface to the bin dir
     for bin in sface.bin sface-run; do 
        # don't use the --file mode as this loses the executable bit
-       git_retrieve $sface_GITPATH $bin $img_mnt/$bin_path
+       git_retrieve $sface_GITPATH $bin "$img_mnt"/$bin_path
     done
-    # install background and app icons
-    git_retrieve --file $sface_GITPATH macos/background.png $img_mnt/$background_path/background.png
-    git_retrieve --file $sface_GITPATH macos/appIcon.icns $img_mnt/$icon_path/appIcon.icns
-    # xxx ?
-    git_retrieve --file $sface_GITPATH macos/appIcon.icns $img_mnt/.VolumeIcon.icns
+
+    ### install background and app icons
+    # clean up any 'background' dir if exists
+    rm -rf "$img_mnt"/{,.}background 
+    git_retrieve --file $sface_GITPATH macos/graphic-install-background.png "$img_mnt"/.background/background.png
+    git_retrieve --file $sface_GITPATH macos/graphic-sfa.icns "$img_mnt"/$resource_path/appIcon.icns
+    # the volume icons won't work - who cares
+#    git_retrieve --file $sface_GITPATH macos/graphic-vol-sface.icns "$img_mnt"/.background/volumeIcon.icns
+#    git_retrieve --file $sface_GITPATH macos/graphic-vol-sface.png "$img_mnt"/.background/volumeIcon.png
 
     # instantiate version
     sed -e "s,@VERSIONTAG@,$sfa_release,g" -e "s,@SCMURL@,${sfa_GITPATH},g" \
-       $img_mnt/$resource_path/sfa/util/version.py.in > $img_mnt/$resource_path/sfa/util/version.py
-
-    # this apparently requires xcode
-    /Developer/Tools/SetFile -a V $img_mnt/$background_path
-
-
+       "$img_mnt"/$resource_path/sfa/util/version.py.in > "$img_mnt"/$resource_path/sfa/util/version.py
 
     # clean up just in case
-    find $img_mnt -name '*pyc' | xargs rm -f
-    find $img_mnt -name '*~' | xargs rm -f
+    find "$img_mnt" -name '*pyc' | xargs rm -f
+    find "$img_mnt" -name '*~' | xargs rm -f
 
     if [ -n "$INTERACTIVE" ] ; then
-       echo "Please open $img_mnt under Finder ..."
+       echo "Please tweak icons layout in $img_mnt under Finder, and press enter when done ..."
        read _
     fi
 
-    hdiutil detach $img_mnt
+    hdiutil detach "$img_mnt"
     rm -f $img_dmg
-    hdiutil convert -format UDZO -imagekey zlib-level=9 -o $img_dmg $img_raw_dmg
+    echo "Compressing..."
+    hdiutil convert -quiet -format UDZO -imagekey zlib-level=9 -o $img_dmg $img_raw_dmg 
     # clean up the raw image
     rm -f $img_raw_dmg
-    # unmount the skeleton
-    hdiutil unmount $skel_mnt
+
+    echo "=================================================="
+    echo "Install image ready in $img_dmg"
+    echo "You may publish it by running e.g."
+    echo "rsync -av $img_dmg root@build.onelab.eu:/build/sface"
+    echo "=================================================="
 
 }
 
@@ -169,8 +209,12 @@ function usage () {
     echo "$COMMAND -c <sface-GITPATH> -s <sfa-GITPATH>"
     echo ""
     echo "Common options"
+    echo " -i : interactive : let you align icons properly in the image before it gets wrapped"
+    echo " -f : force download of the skeleton package"
+    echo " -a leopard|snow-leopard"
+    echo " -A : run on all known archs"
     echo " -n : dry-run"
-    echo " -i : let you open the image before getting wrapped"
+    echo " -v : verbose"
     echo " -h : this help"
 }
 
@@ -178,14 +222,18 @@ DEFAULT_BUILD_DIR=$HOME/git/build
 DEFAULT_TAGS_FILE=onelab-k32-tags.mk
 
 function main () {
-    while getopts "b:t:c:s:hni" opt ; do
+    while getopts "b:t:c:s:ifa:Anvh" opt ; do
        case $opt in 
            b) BUILD_DIR=$OPTARG;;
            t) TAGS_FILE=$OPTARG;;
            c) sface_GITPATH=$OPTARG;;
            s) sfa_GITPATH=$OPTARG;;
-           n) dry_run=true;;
            i) INTERACTIVE=true;;
+           f) FORCE_DOWNLOAD=true;;
+           a) ARCHS="$ARCHS $OPTARG";;
+           A) ARCHS="leopard snow-leopard";;
+           n) dry_run=true;;
+           v) set -x;;
            h) usage; exit 1 ;;
        esac
     done
@@ -193,6 +241,8 @@ function main () {
 
     [ -z "$BUILD_DIR" ] && BUILD_DIR=$DEFAULT_BUILD_DIR
     [ -z "$TAGS_FILE" ] && TAGS_FILE=$DEFAULT_TAGS_FILE
+    [ -z "$ARCHS" ] && ARCHS=$DEFAULT_ARCH
+    [[ -n "$@" ]] && { usage ; exit 1; }
     if [ -z "$sface_GITPATH" ] ; then
        sface_GITPATH=$(make -C $BUILD_DIR stage1=true PLDISTROTAGS=$TAGS_FILE +sface-GITPATH 2> /dev/null)
        echo "Retrieved from $BUILD_DIR/$TAGS_FILE.."
@@ -203,7 +253,13 @@ function main () {
        echo "Retrieved from $BUILD_DIR/$TAGS_FILE.."
        echo " sfa_GITPATH=$sfa_GITPATH"
     fi
-    [ -z "$dry_run" ] && package "$@" $sface_GITPATH $sfa_GITPATH
+    for ARCH in $ARCHS; do 
+       if [ -z "$dry_run" ] ; then
+           package $sface_GITPATH $sfa_GITPATH $ARCH
+       else
+           echo "Would run package $sface_GITPATH $sfa_GITPATH $ARCH"
+       fi
+    done
        
 }