#!/usr/bin/perl -w # # Do-pkg - convert a binary distribution into a Mac OS X PKG and put it # inside a Disk Image (.dmg). Additionally, add a separate package, # including the required Startup Item to automatically start MySQL on # bootup. # # The script currently assumes the following environment (which should exist # like that, if the Do-compile script was used to build the binary # distribution) # # - there must be a binary distribution (*.tar.gz) in the directory # `hostname` of the current directory # - the extracted and compiled source tree should be located in the # `hostname` directory, too # # Use the "--help" option for more info! # # written by Lenz Grimmer # use Cwd; use File::Basename; use File::Copy; use Getopt::Long; Getopt::Long::Configure ("bundling"); use Sys::Hostname; $opt_dry_run= undef; $opt_help= undef; $opt_log= undef; $opt_mail= ""; $opt_skip_dmg= undef; $opt_skip_si= undef; $opt_suffix= undef; $opt_verbose= undef; $opt_version= undef; GetOptions( "dry-run", "help|h", "log|l:s", "mail|m=s", "skip-dmg|skip-disk-image|s", "skip-si|skip-startup-item", "suffix=s", "verbose|v", "version=s", ) || &print_help; # Include helper functions $PWD= cwd(); $LOGGER= "$PWD/logger.pm"; if (-f "$LOGGER") { do "$LOGGER"; } else { die "ERROR: $LOGGER cannot be found!\n"; } $PM= "/Developer/Applications/PackageMaker.app/Contents/MacOS/PackageMaker"; $TMP= $ENV{TMPDIR}; $TMP eq "" ? $TMP= $TMP . "/PKGBUILD.$$": $TMP= "/tmp/PKGBUILD.$$"; $PKGROOT= "$TMP/PMROOT"; $PKGDEST= "$TMP/PKG"; $RESOURCE_DIR= "$TMP/Resources"; $SUFFIX= $opt_suffix; $VERSION= $opt_version; ($MAJOR, $MINOR, $RELEASE)= split(/\./, $VERSION); $NAME= "mysql$SUFFIX-$VERSION"; $HOST= hostname(); $ID= getpwuid($>); $HOST=~ /^([^.-]*)/; $HOST= $1; $LOGFILE= "$PWD/Logs/$HOST-$MAJOR.$MINOR$SUFFIX.log"; $BUILDDIR= "$PWD/$HOST"; $SRCBASEDIR= <$BUILDDIR/mysql*-$VERSION>; $SUPFILEDIR= <$SRCBASEDIR/support-files/MacOSX>; $TAR= <$BUILDDIR/$NAME-apple-darwin*-powerpc.tar.gz>; $INFO= <$SUPFILEDIR/Info.plist>; $DESC= <$SUPFILEDIR/Description.plist>; $SI_INFO= <$SUPFILEDIR/StartupItem.Info.plist>; $SI_DESC= <$SUPFILEDIR/StartupItem.Description.plist>; $SI_PARAMS= <$SUPFILEDIR/StartupParameters.plist>; $SI_POST= <$SUPFILEDIR/StartupItem.postinstall>; $SI_NAME= "MySQLStartupItem"; $SI_SCRIPT= <$SUPFILEDIR/MySQL>; @RESOURCES= qw/ ReadMe.txt postinstall preinstall /; @LICENSES= ("$SRCBASEDIR/COPYING","$SRCBASEDIR/MySQLEULA.txt"); &print_help("") if ($opt_help || !$opt_suffix || !$opt_version); # # Override predefined Log file name # if (defined $opt_log) { if ($opt_log ne "") { if ($opt_log =~ /^\/.*/) { $LOGFILE= $opt_log; } else { $LOGFILE= $PWD . "/" . $opt_log; } } } # Creating the UFS disk image requires root privileges die("You must be root to run this script!") if ($ID ne "root" && !$opt_dry_run); @files= ($TAR, $INFO, $DESC); @files= (@files, $SI_INFO, $SI_DESC, $SI_POST, $SI_SCRIPT) unless $opt_skip_si; foreach $file (@files) { &abort("Unable to find $file!") unless (-f "$file"); } # Remove old temporary build directories first &logger("Cleaning up temporary build directories"); &run_command("rm -rf $TMP", "Could not clean up $TMP!"); &logger("Creating temp directories"); foreach $dir ($TMP, $PKGROOT, $PKGDEST, $RESOURCE_DIR) { if (!-d $dir) { &logger("Creating directory $dir!"); unless($opt_dry_run) { mkdir($dir) or &abort("Could not make directory $dir!"); } } } foreach $resfile (@RESOURCES) { &logger("Copying $SUPFILEDIR/$resfile to $RESOURCE_DIR"); unless($opt_dry_run) { copy("$SUPFILEDIR/$resfile", "$RESOURCE_DIR") or &abort("Error while copying $SUPFILEDIR/$resfile to $RESOURCE_DIR"); } } # Search for license file foreach $license (@LICENSES) { if (-f "$license") { &logger("Copy $license to $RESOURCE_DIR/License.txt"); unless($opt_dry_run) { copy("$license", "$RESOURCE_DIR/License.txt") or &abort("Error while copying $license to $RESOURCE_DIR"); } } } &abort("Could not find a license file!") unless (-f "$RESOURCE_DIR/License.txt"); # Extract the binary tarball and create the "mysql" symlink &logger("Extracting $TAR to $PKGROOT"); &run_command("gnutar zxf $TAR -C $PKGROOT", "Unable to extract $TAR!"); &run_command("cd $PKGROOT ; ln -s mysql* ./mysql", "Unable to create symlink!"); &run_command("chown -R root.wheel $PKGROOT/*", "Cannot chown $PKGROOT!"); # Now build the PGK using PackageMaker # The "|| true" is a nasty hack to work around a problem with Package Maker # returning a non-zero value, even though the package was created correctly &logger("Running PackageMaker"); $command= "$PM -build -p $PKGDEST/$NAME.pkg -f $PKGROOT -r $RESOURCE_DIR -i $INFO -d $DESC || true"; &run_command($command, "Error while building package $NAME.pkg!"); # # Build the Startup Item PKG # unless ($opt_skip_si) { &logger("Cleaning up $PKGROOT"); &run_command("rm -rf $PKGROOT/*", "Unable to clean up $PKGROOT!"); &logger("Cleaning up $RESOURCE_DIR"); &run_command("rm -rf $RESOURCE_DIR/*", "Unable to clean up $RESOURCE_DIR!"); &logger("Installing MySQL StartupItem files into $PKGROOT/MySQL"); unless($opt_dry_run) { mkdir("$PKGROOT/MySQL") or &abort("Error creating $PKGROOT/MySQL"); copy("$SI_SCRIPT", "$PKGROOT/MySQL/") or &abort("Error copying $SI_SCRIPT!"); chmod(0755, "$PKGROOT/MySQL/" . basename("$SI_SCRIPT")); copy("$SI_PARAMS", "$PKGROOT/MySQL/") or &abort("Error copying $SI_PARAMS!"); chmod(0644, "$PKGROOT/MySQL/" . basename("$SI_PARAMS")); &run_command("chown -R root.wheel $PKGROOT/*", "Cannot chown $PKGROOT!"); copy("$SI_POST", "$RESOURCE_DIR/postinstall") or &abort("Error copying $SI_POST!"); chmod(0644, "$RESOURCE_DIR/postinstall"); } &logger("Building $SI_NAME.pkg using PackageMaker"); $command= "$PM -build -p $PKGDEST/$SI_NAME.pkg -f $PKGROOT -r $RESOURCE_DIR -i $SI_INFO -d $SI_DESC || true"; &run_command($command, "Error while building package $SI_NAME.pkg!"); } if ($opt_skip_dmg) { &logger("SUCCESS: Package $PKGDEST/$NAME.pkg created"); exit 0; } # Determine the size of the Disk image to be created and add a 5% safety # margin for filesystem overhead &logger("Determining required disk image size for $PKGDEST"); unless($opt_dry_run) { chomp($_= `du -sk $PKGDEST`); @size= split(); $size= int($size[0]+($size[0]*0.05)); &logger("Disk image size: $size KB"); } unless($opt_dry_run) { &abort("Zero bytes? Something is wrong here!") if ($size == 0); } # Now create and mount the disk image $TMPNAME= $NAME . ".tmp"; &logger("Creating temporary Disk image $TMPNAME.dmg"); $command= "hdiutil create $TMPNAME -size ${size}k -ov -fs UFS -volname $NAME"; &run_command($command, "Unable to create disk image $TMPNAME.dmg!"); &logger("Attaching Disk image $TMPNAME.dmg"); &run_command("hdid $TMPNAME.dmg", "Unable to attach $TMPNAME.dmg!"); # Install the PKG into the .dmg chomp($mountpoint=`mount | grep "\/Volumes\/$NAME" | cut -f3 -d" "`) if (!$opt_dry_run); &logger("Copying $PKGDEST/$NAME.pkg to Disk image /Volumes/$NAME"); &run_command("ditto $PKGDEST /Volumes/$NAME", "Could not copy $PKGDEST to /Volumes/$NAME!"); &run_command("ditto $SUPFILEDIR/ReadMe.txt /Volumes/$NAME", "Could not copy $SPFILEDIR/ReadMe.txt to /Volumes/$NAME!"); chomp($mountpoint=`mount | grep "\/Volumes\/$NAME" | cut -f1 -d" "`) if (!$opt_dry_run); &abort("/Volumes/$NAME not attached!") if (!$mountpoint && !$opt_dry_run); &logger("Unmounting $mountpoint"); &run_command("hdiutil detach $mountpoint", "Unable to detach $mountpoint"); &run_command("rm -f $NAME.dmg", "Unable to remove $NAME.dmg!") if (-f "$NAME.dmg"); &logger("Compressing disk image"); $command= "hdiutil convert $TMPNAME.dmg -format UDZO -imagekey zlib-level=9 -o $NAME.dmg"; &run_command($command, "Unable to compress disk image!"); # Final cleanups &logger("Removing $TMPNAME.dmg"); &run_command("rm -f $TMPNAME.dmg", "Unable to remove $TMPNAME.dmg!"); &logger("Removing $TMP"); &run_command("rm -rf $TMP", "Unable to remove $TMP!"); &logger("SUCCESS: $NAME.dmg created.") if (!$opt_dry_run); exit 0; sub print_help { my $message= $_[0]; if ($message ne "") { print "\n"; print "ERROR: $message\n"; } print < --suffix= --version= Creates a Mac OS X installation package (PKG) and stores it inside a Disk Image (.dmg) file. You need to create a binary distribution tarball with scripts/make_binary_distribution first! NOTE: You need to run this script with root privileges (required to create the disk image) Options: --dry-run Dry run without executing -h, --help Print this help -l, --log[=] Write a log file [to ] (default is "$LOGFILE") -m, --mail=
Mail a failure report to the given address (and include a log file snippet, if logging is enabled) Note that the \@-Sign needs to be quoted! Example: --mail=user\\\@domain.com -s, --skip-disk-image, --skip-dmg Just build the PKGs, don't put it into a disk image afterwards --skip-startup-item, --skip-si Skip the creation of the StartupItem PKG --suffix= The package suffix (e.g. "-standard" or "-pro) --version= The MySQL version number (e.g. 4.0.11-gamma) -v, --verbose Verbose execution EOF exit 1; }