# et:ts=4
# portmpkg.tcl
# $Id: portmpkg.tcl,v 1.9 2005/08/27 00:07:27 pguyot Exp $
#
# Copyright (c) 2002 - 2003 Apple Computer, Inc.
# 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 of Apple Computer, Inc. nor the names of its 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 EXPRESS 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 COPYRIGHT OWNER 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.
#
package provide portmpkg 1.0
package require portutil 1.0
set com.apple.mpkg [target_new com.apple.mpkg mpkg_main]
target_runtype ${com.apple.mpkg} always
target_provides ${com.apple.mpkg} mpkg
target_requires ${com.apple.mpkg} pkg
# define options
options package.destpath
set_ui_prefix
proc mpkg_main {args} {
global portname portversion portrevision package.destpath UI_PREFIX
# Make sure the destination path exists.
system "mkdir -p ${package.destpath}"
return [package_mpkg $portname $portversion $portrevision]
}
proc make_dependency_list {portname} {
set result {}
if {[catch {set res [dport_search "^$portname\$"]} error]} {
global errorInfo
ui_debug "$errorInfo"
ui_error "port search failed: $error"
return 1
}
foreach {name array} $res {
array set portinfo $array
if {[info exists portinfo(depends_run)] || [info exists portinfo(depends_lib)]} {
# get the union of depends_run and depends_lib
# xxx: only examines the portfile component of the depspec
set depends {}
if {[info exists portinfo(depends_run)]} { eval "lappend depends $portinfo(depends_run)" }
if {[info exists portinfo(depends_lib)]} { eval "lappend depends $portinfo(depends_lib)" }
foreach depspec $depends {
set dep [lindex [split $depspec :] end]
# xxx: nasty hack
if {$dep != "XFree86"} {
eval "lappend result [make_dependency_list $dep]"
}
}
}
lappend result $portinfo(name)/$portinfo(version)
unset portinfo
}
ui_debug "dependencies for ${portname}: $result"
return $result
}
proc make_one_package {portname portversion mpkgpath} {
global prefix package.destpath
if {[catch {set res [dport_search "^$portname\$"]} result]} {
global errorInfo
ui_debug "$errorInfo"
ui_error "port search failed: $result"
return 1
}
foreach {name array} $res {
array set portinfo $array
if {[info exists portinfo(porturl)] && [info exists portinfo(version)] && $portinfo(version) == $portversion} {
# only the prefix gets passed to the worker.
ui_debug "building dependency package: $portname"
set worker [dport_open $portinfo(porturl) [list prefix $prefix package.destpath ${mpkgpath}/Contents/Resources] {} yes]
dport_exec $worker pkg
dport_close $worker
}
unset portinfo
}
}
proc package_mpkg {portname portversion portrevision} {
global portdbpath destpath workpath prefix portresourcepath description package.destpath long_description homepage depends_run depends_lib
set pkgpath ${package.destpath}/${portname}-${portversion}.pkg
set mpkgpath ${package.destpath}/${portname}-${portversion}.mpkg
system "mkdir -p -m 0755 ${mpkgpath}/Contents/Resources"
set dependencies {}
# get deplist
set deps [make_dependency_list $portname]
set deps [lsort -unique $deps]
foreach dep $deps {
set name [lindex [split $dep /] 0]
set vers [lindex [split $dep /] 1]
# don't re-package ourself
if {$name != $portname} {
make_one_package $name $vers $mpkgpath
lappend dependencies ${name}-${vers}.pkg
}
}
# copy our own pkg into the mpkg
system "cp -PR ${pkgpath} ${mpkgpath}/Contents/Resources/"
lappend dependencies ${portname}-${portversion}.pkg
write_PkgInfo ${mpkgpath}/Contents/PkgInfo
mpkg_write_info_plist ${mpkgpath}/Contents/Info.plist $portname $portversion $portrevision $prefix $dependencies
write_description_plist ${mpkgpath}/Contents/Resources/Description.plist $portname $portversion $description
# long_description, description, or homepage may not exist
foreach variable {long_description description homepage} {
if {![info exists $variable]} {
set pkg_$variable ""
} else {
set pkg_$variable [set $variable]
}
}
write_welcome_html ${mpkgpath}/Contents/Resources/Welcome.rtf $portname $portversion $pkg_long_description $pkg_description $pkg_homepage
file copy -force -- ${portresourcepath}/package/background.tiff ${mpkgpath}/Contents/Resources/background.tiff
return 0
}
proc xml_escape {s} {
regsub -all {&} $s {\&} s
regsub -all {<} $s {\<} s
regsub -all {>} $s {\>} s
return $s
}
proc mpkg_write_info_plist {infofile portname portversion portrevision destination dependencies} {
set vers [split $portversion "."]
if {[string index $destination end] != "/"} {
append destination /
}
set depxml ""
foreach dep $dependencies {
set dep [xml_escape $dep]
append depxml "
IFPkgFlagPackageLocation
${dep}
IFPkgFlagPackageSelection
selected
"
}
set portname [xml_escape $portname]
set portversion [xml_escape $portversion]
set portrevision [xml_escape $portrevision]
set infofd [open ${infofile} w+]
puts $infofd {
}
puts $infofd "
CFBundleGetInfoString
${portname} ${portversion}
CFBundleIdentifier
org.opendarwin.darwinports.mpkg.${portname}
CFBundleName
${portname}
CFBundleShortVersionString
${portversion}
IFMajorVersion
${portrevision}
IFMinorVersion
0
IFPkgFlagComponentDirectory
./Contents/Resources
IFPkgFlagPackageList
${depxml}
IFPkgFormatVersion
0.10000000149011612
"
close $infofd
}