Files
mpbb/mpab-functions

437 lines
15 KiB
Plaintext

#
# Copyright (c) 2006,2008 Bryan L Blackburn. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name Bryan L Blackburn, nor the names of any contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
# AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#------------------------------------------------------------------------
# Check necessary bits are available. Either svn export tarball, or svn
# working directory, or release tarball have to be present.
# $1 - data directory
# $2 - MacPorts source tarball
# $3 - MacPosts svn working copy
# $4 - MacPorts release tarball
function checkDependencies()
{
local dataDir=$1
local mpTarball=$2
local mpSvnWorkdir=$3
local installPackage=$4
if [[ `id -u` != 0 ]]; then
echo "This must be run as root, please do so"
return 1
fi
if [[ ! -f ${dataDir}/${mpTarball} && ! -d ${dataDir}/${mpSvnWorkdir} && ! -f ${dataDir}/${installPackage} ]]; then
cat << EOF
Need to have a MacPorts source tarball ${mpTarball} or svn working directory ${mpSvnWorkDir}
See the ReadMe.txt file.
EOF
return 2
fi
}
#------------------------------------------------------------------------
# Print out usage help and exit
function printUsageAndExit()
{
cat << EOF
Usage: $0 [help | mount | umount | shell | buildmp [RELEASE_FILE] | rebuildmp [RELEASE_FILE] |
buildports [portlist_file]]
help: this help
mount: just mount the chroot images
umount: unmount the chroot images
shell: start an interactive shell in the chroot
buildmp: build/install MacPorts inside the chroot
rebuildmp: force a rebuild of MacPorts inside the chroot
buildports: build ports; if a portlist file is given, use it, otherwise
build all; portlist_file is a simple text file with one port
per line; dependencies will be built as needed
default is to do everything (except rebuildmp); buildmp and buildports
will unmount the chroot when done
EOF
exit 0
}
#------------------------------------------------------------------------
# Do whatever cleanup is necessary
# $1 - base directory
# $2 - chroot path
function exitFunction()
{
local baseDir=$1
local chrootPath=$2
if [[ -n $exitMessage ]]; then
echo $exitMessage
fi
if [[ -d ${chrootPath}/var/tmp/portresults/fail ]]; then
moveAndReport ${baseDir} "${chrootPath}"
fi
if [[ -n "$chrootPath" && -d ${chrootPath} ]]; then
umountChroot ${chrootPath}
fi
}
#------------------------------------------------------------------------
# Build the base chroot and distfile cache disk images
# $1 - base directory
# $2 - chroot path
# $3 - base name for the disk images
function buildImages()
{
local baseDir=$1
local chrootPath=$2
local imgBaseName=$3
if [[ -z "$chrootPath" ]]; then
return 0
fi
echo "Building MP chroot images, if necessary"
# Paths to create within the chroot
pathsToCreate="private/etc private/var/folders private/var/log private/var/spool private/var/run private/var/tmp private/var/db/dyld private/tmp"
os_major=$(uname -r | sed 's/\..*//')
# Paths to copy to the chroot
if [[ $os_major -eq 8 ]]; then
# XXX these are just copied from the leopard list and so are probably wrong for tiger
pathsToCopy="private/etc/bashrc private/etc/group private/etc/hosts private/etc/pam.d private/etc/passwd private/etc/profile private/etc/shells private/var/root bin sbin etc tmp var usr/bin usr/include usr/lib usr/libexec usr/sbin usr/share usr/X11 usr/X11R6 Developer/Headers Developer/Library Developer/Makefiles Developer/Platforms Developer/Private Developer/SDKs Developer/Tools Developer/usr System/Library/CoreServices System/Library/Filesystems System/Library/Frameworks System/Library/Java System/Library/Perl System/Library/PrivateFrameworks System/Library/Tcl Developer/Applications/Xcode.app"
fi
if [[ $os_major -eq 9 ]]; then
pathsToCopy="private/etc/bashrc private/etc/group private/etc/hosts private/etc/pam.d private/etc/passwd private/etc/profile private/etc/shells private/var/root bin sbin etc tmp var usr/bin usr/include usr/lib usr/libexec usr/sbin usr/share usr/X11 usr/X11R6 Developer/Headers Developer/Library Developer/Makefiles Developer/Platforms Developer/Private Developer/SDKs Developer/Tools Developer/usr System/Library/CoreServices System/Library/Filesystems System/Library/Frameworks System/Library/Java System/Library/Perl System/Library/PrivateFrameworks System/Library/Tcl Developer/Applications/Xcode.app"
fi
# update this for future releases
if [[ $os_major -ge 10 ]]; then
pathsToCopy="private/etc/bashrc private/etc/group private/etc/hosts private/etc/pam.d private/etc/passwd private/etc/profile private/etc/shells private/var/root bin sbin etc tmp var usr/bin usr/include usr/lib usr/libexec usr/sbin usr/share usr/X11 usr/X11R6 Developer/Headers Developer/Library Developer/Makefiles Developer/Platforms Developer/Private Developer/SDKs Developer/Tools Developer/usr System/Library/CoreServices System/Library/Filesystems System/Library/Frameworks System/Library/Java System/Library/Perl System/Library/PrivateFrameworks System/Library/Tcl Developer/Applications/Xcode.app"
fi
# Size of the disk images (hdiutil nomenclature)
imageSize="32g"
# Filesystem of the disk images (hdiutil nomenclature)
imageFileSystem="HFS+J"
mkdir -p ${chrootPath}
if [[ ! -f ${baseDir}/${imgBaseName}.dmg ]]; then
hdiutil create -size ${imageSize} -fs ${imageFileSystem} -volname MPRoot -imagekey sparse-band-size=16384 ${baseDir}/${imgBaseName}.sparseimage ${HDIUTILDEBUG}
returnValue=$?
if [[ ${returnValue} != 0 ]]; then
echo "hdiutil create (MPRoot) failed"
return ${returnValue}
fi
hdiutil attach ${baseDir}/${imgBaseName}.sparseimage -mountpoint ${chrootPath} -owners on -nobrowse -noautofsck ${HDIUTILDEBUG}
returnValue=$?
if [[ ${returnValue} != 0 ]]; then
echo "Failed to attach"
return ${returnValue}
fi
mkdir ${chrootPath}/dev
mount_devfs devfs ${chrootPath}/dev
mount_fdesc -o union fdesc ${chrootPath}/dev
if [[ ! -d ${chrootPath}/usr ]]; then
cd /
for createpath in ${pathsToCreate}; do
mkdir -p ${chrootPath}/${createpath}
done
for copypath in ${pathsToCopy}; do
echo "Copying ${copypath}..." ###
pax -r -w -pe $copypath ${chrootPath}
done
cd - > /dev/null
fi
umount -f ${chrootPath}/dev
umount -f ${chrootPath}/dev
hdiutil detach ${chrootPath} ${HDIUTILDEBUG}
returnValue=$?
if [[ ${returnValue} != 0 ]]; then
echo "hdiutil detach failed"
return ${returnValue}
fi
hdiutil convert ${baseDir}/${imgBaseName}.sparseimage -format UDRO -o ${baseDir}/${imgBaseName}.dmg ${HDIUTILDEBUG}
returnValue=$?
if [[ ${returnValue} != 0 ]]; then
echo "hdiutil convert failed"
return ${returnValue}
fi
rm ${baseDir}/${imgBaseName}.sparseimage
fi
if [[ ! -f ${baseDir}/${imgBaseName}_distcache.sparseimage ]]; then
hdiutil create -size ${imageSize} -fs ${imageFileSystem} -volname MPCache -imagekey sparse-band-size=16384 ${baseDir}/${imgBaseName}_distcache.sparseimage ${HDIUTILDEBUG}
returnValue=$?
if [[ ${returnValue} != 0 ]]; then
echo "hdiutil create (MPCache) failed"
return ${returnValue}
fi
fi
return 0
}
#------------------------------------------------------------------------
# Build MacPorts in the chroot (if not already there)
# $1 - base directory
# $2 - dataDir
# $3 - chroot path
# $4 - MacPorts source tarball or svn checkout directory
function buildMacPorts()
{
local baseDir=$1
local dataDir=$2
local chrootPath=$3
local mpExport=$4
needIndex=""
if [[ ! -d ${chrootPath}${SRC_PREFIX} ]]; then
if [[ -f ${dataDir}/${mpExport} ]]; then
mkdir -p ${chrootPath}${SRC_PREFIX}
echo ${mpExport} | grep -q "MacPorts-......tar.gz"
if [[ $? == 0 ]]; then
cp ${mpExport} ${chrootPath}${SRC_PREFIX}
cd ${chrootPath}${SRC_PREFIX}
tar xzf ${mpExport} || return 1
rm -rf base 2>/dev/null
mv $(ls -d MacPorts-?.?.?) base || return 1
else
cd ${chrootPath}${SRC_PREFIX}
bunzip2 -c ${dataDir}/${mpExport} | tar xf -
fi
cd - > /dev/null
elif [[ -d ${dataDir}/${mpExport} ]]; then
mkdir -p ${chrootPath}${SRC_PREFIX}
cd ${dataDir}/${mpExport} && \
rsync -r --del --exclude '*~' --exclude '.svn' . ${chrootPath}${SRC_PREFIX}
cd - > /dev/null
else
echo "No ${mpExport} found"
return 1
fi
chmod -R a+rX ${chrootPath}${SRC_PREFIX}
needIndex=1
fi
if [[ ! -f ${chrootPath}${PREFIX}/bin/port ]]; then
chrootExec installmacports
needIndex=1
fi
if [[ -n "$needIndex" ]]; then
chrootExec recreateportindex
fi
return 0
}
#------------------------------------------------------------------------
# Build MP ports, either those listed in a file given or by generating
# a list of all ports and using that
# $1 - base directory
# $2 - chroot path
function buildPorts()
{
local baseDir=$1
local chrootPath=$2
if [[ $baseDir == "." ]]; then
baseDir=`pwd`
fi
echo "Building ports"
cp -p ${baseDir}/chroot-scripts/genportlist.tcl ${chrootPath}/var/tmp/
cp -p ${baseDir}/chroot-scripts/archivepath.tcl ${chrootPath}/var/tmp/
cp -p ${baseDir}/chroot-scripts/dep_ports.tcl ${chrootPath}/var/tmp/
rm -f ${chrootPath}/var/tmp/progress.log ${baseDir}/progress.log
touch ${baseDir}/progress.log
if ! ln ${baseDir}/progress.log ${chrootPath}/var/tmp/progress.log 2>/dev/null ; then
ln -s ${baseDir}/progress.log ${chrootPath}/var/tmp/progress.log
fi
mkdir -p ${baseDir}/failcache
rsync -a ${baseDir}/failcache ${chrootPath}/var/tmp
chrootExec buildports
rsync -a --delete ${chrootPath}/var/tmp/failcache ${baseDir}
return 0
}
#------------------------------------------------------------------------
# Start a shell inside of the chroot jail.
function chrootShell()
{
echo "Starting chroot shell"
cp -p ${baseDir}/chroot-scripts/chrootshell ${chrootPath}/var/tmp/
chrootExec chrootshell
echo "Chroot shell exited"
return 0
}
#------------------------------------------------------------------------
# Move logs and report results
# $1 - base directory
# $2 - chroot path
function moveAndReport()
{
local baseDir=$1
local chrootPath=$2
now=`date '+%Y%m%d-%H%M%S'`
mkdir ${baseDir}/logs-${now}
mv ${chrootPath}/var/tmp/portresults/fail ${baseDir}/logs-${now}
mv ${chrootPath}/var/tmp/portresults/success ${baseDir}/logs-${now}
chmod -R a+rX ${baseDir}/logs-${now}
failcount=`ls -1 ${baseDir}/logs-${now}/fail | wc -l`
successcount=`ls -1 ${baseDir}/logs-${now}/success | wc -l`
echo "Ports built successfully: $successcount"
echo "Ports failed: $failcount"
echo "All logs are located in ${baseDir}/logs-${now}"
return 0
}
#------------------------------------------------------------------------
# Mount the full chroot stuff
# $1 - base directory
# $2 - chroot path
# $3 - base name for the disk images
function mountChroot()
{
local baseDir=$1
local chrootPath=$2
local imgBaseName=$3
if [[ -z "$chrootPath" ]]; then
return 0
fi
echo "Mounting chroot images"
mkdir -p ${chrootPath}
if [[ ! -d ${chrootPath}/usr ]]; then
if [[ ! -f ${baseDir}/${imgBaseName}.dmg ]]; then
echo "MPRoot image ${baseDir}/${imgBaseName}.dmg not found"
return 1
fi
hdiutil attach ${baseDir}/${imgBaseName}.dmg -mountpoint ${chrootPath} -shadow -noverify -owners on -nobrowse -noautofsck ${HDIUTILDEBUG}
returnValue=$?
if [[ ${returnValue} != 0 ]]; then
echo "Failed to attach root image"
return ${returnValue}
fi
mount_devfs devfs ${chrootPath}/dev
mount_fdesc -o union fdesc ${chrootPath}/dev
mkdir -p ${chrootPath}${PREFIX}/var/macports/distfiles
hdiutil attach ${baseDir}/${imgBaseName}_distcache.sparseimage -mountpoint ${chrootPath}${PREFIX}/var/macports/distfiles -noverify -owners on -nobrowse -noautofsck ${HDIUTILDEBUG}
returnValue=$?
if [[ ${returnValue} != 0 ]]; then
echo "Failed to attach distfiles image"
return ${returnValue}
fi
fi
return 0
}
#------------------------------------------------------------------------
# Unmount everything for the MP chroot
# $1 - chroot path
function umountChroot()
{
local chrootPath=$1
if [[ -z "$chrootPath" ]]; then
return 0
fi
if [[ -d ${chrootPath}/dev ]]; then
# First for the fdesc
umount -f ${chrootPath}/dev
# And again for the devfs
umount -f ${chrootPath}/dev
fi
if [[ -d ${chrootPath}${PREFIX}/var/macports/distfiles ]]; then
# Now the cache image for the dist files
hdiutil detach ${chrootPath}${PREFIX}/var/macports/distfiles ${HDIUTILDEBUG}
fi
if [[ -d ${chrootPath} ]]; then
# Finally, the main image itself
hdiutil detach ${chrootPath} ${HDIUTILDEBUG}
rmdir ${chrootPath}
fi
return 0
}
#------------------------------------------------------------------------
# Execute a script inside the chroot environment. Includes copying it
# into a temp file and removing it afterwards
# $1 - script to execute
function chrootExec () {
cp -p ${baseDir}/chroot-scripts/$1 ${chrootPath}/var/tmp
if [[ -n "$chrootPath" ]]; then
# Set DYLD_NO_FIX_PREBINDING as otherwise, on 10.5, dyld will spew
# errors to syslog/console log like:
# com.apple.launchd[1] (com.apple.dyld): Throttling respawn: Will start in 10 seconds
env -i PATH=/bin:/usr/bin:/sbin:/usr/sbin HOME=/var/root DYLD_NO_FIX_PREBINDING=1 PREFIX=${PREFIX} SRC_PREFIX=${SRC_PREFIX} /usr/sbin/chroot ${chrootPath} /bin/sh /var/tmp/$1
else
env -i PATH=/bin:/usr/bin:/sbin:/usr/sbin HOME=/var/root PREFIX=${PREFIX} SRC_PREFIX=${SRC_PREFIX} /bin/sh /var/tmp/$1
fi
rm ${chrootPath}/var/tmp/$1
}
# Local Variables:
# mode: shell-script
# indent-tabs-mode: nil
# sh-basic-offset: 3
# End: