source: branches/gsoc09-logging/base/src/package1.0/portpkg.tcl @ 52218

Last change on this file since 52218 was 52218, checked in by enl@…, 11 years ago

Merge from trunk

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 12.5 KB
Line 
1# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:filetype=tcl:et:sw=4:ts=4:sts=4
2# portpkg.tcl
3# $Id: portpkg.tcl 52218 2009-06-12 08:57:53Z enl@macports.org $
4#
5# Copyright (c) 2002 - 2003 Apple Computer, Inc.
6# All rights reserved.
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions
10# are met:
11# 1. Redistributions of source code must retain the above copyright
12#    notice, this list of conditions and the following disclaimer.
13# 2. Redistributions in binary form must reproduce the above copyright
14#    notice, this list of conditions and the following disclaimer in the
15#    documentation and/or other materials provided with the distribution.
16# 3. Neither the name of Apple Computer, Inc. nor the names of its contributors
17#    may be used to endorse or promote products derived from this software
18#    without specific prior written permission.
19#
20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30# POSSIBILITY OF SUCH DAMAGE.
31#
32
33package provide portpkg 1.0
34package require portutil 1.0
35
36set org.macports.pkg [target_new org.macports.pkg portpkg::pkg_main]
37target_runtype ${org.macports.pkg} always
38target_provides ${org.macports.pkg} pkg
39if {[option portarchivemode] == "yes"} {
40    target_requires ${org.macports.pkg} unarchive destroot
41} else {
42    target_requires ${org.macports.pkg} destroot
43}
44
45namespace eval portpkg {
46}
47
48# define options
49options package.type package.destpath package.flat
50
51# Set defaults
52default package.destpath {${workpath}}
53default package.flat     false
54
55set_ui_prefix
56
57proc portpkg::pkg_main {args} {
58    global name version revision package.type package.destpath package.flat UI_PREFIX
59
60    ui_msg "$UI_PREFIX [format [msgcat::mc "Creating pkg for %s-%s"] ${name} ${version}]"
61
62    return [package_pkg $name $version $revision]
63}
64
65proc portpkg::package_pkg {portname portversion portrevision} {
66    global UI_PREFIX portdbpath destpath workpath prefix description package.destpath package.flat long_description homepage portpath porturl
67    global os.version os.major
68
69    set pkgpath ${package.destpath}/${portname}-${portversion}.pkg
70
71    if {[file readable $pkgpath] && ([file mtime ${pkgpath}] >= [file mtime ${portpath}/Portfile])} {
72        ui_msg "$UI_PREFIX [format [msgcat::mc "Package for %s-%s is up-to-date"] ${portname} ${portversion}]"
73        return 0
74    }
75
76    set packagemaker "[option developer_dir]/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker"
77    if ([file exists "$packagemaker"]) {
78        set resourcepath ${workpath}/pkg_resources
79    } else {
80        set resourcepath "${pkgpath}/Contents/Resources"
81    }
82
83    set language "English"
84    file mkdir "${resourcepath}/${language}.lproj"
85    file attributes "${resourcepath}/${language}.lproj" -permissions 0755
86       
87    # long_description, description, or homepage may not exist
88    foreach variable {long_description description homepage} {
89        if {![info exists $variable]} {
90            set pkg_$variable ""
91        } else {
92            set pkg_$variable [set $variable]
93        }
94    }
95    write_welcome_html ${resourcepath}/${language}.lproj/Welcome.html $portname $portversion $pkg_long_description $pkg_description $pkg_homepage
96    file copy -force -- [getportresourcepath $porturl "port1.0/package/background.tiff"] ${resourcepath}/${language}.lproj/background.tiff
97
98    foreach dir {etc var tmp} {
99        if ([file exists "${destpath}/$dir"]) {
100            # certain toplevel directories really are symlinks. leaving them as directories make pax lose the symlinks. that's bad.
101            file mkdir "${destpath}/private/${dir}"
102            eval file rename [glob ${destpath}/${dir}/*] "${destpath}/private/${dir}"
103            delete "${destpath}/${dir}"
104        }
105    }
106
107    if ([file exists "$packagemaker"]) {
108
109        ui_debug "Calling $packagemaker for $portname pkg"
110        if {${os.major} >= 9} {
111            if {${package.flat}} {
112                set pkgtarget "10.5"
113                set pkgresources ""
114                set infofile "${workpath}/PackageInfo"
115                write_package_info ${workpath}/PackageInfo $portname $portversion $portrevision
116            } else {
117                set pkgtarget "10.3"
118                set pkgresources " --resources ${resourcepath} --title \"$portname-$portversion\""
119                set infofile "${workpath}/Info.plist"
120                write_info_plist ${workpath}/Info.plist $portname $portversion $portrevision
121            }
122            system "PMResourceLocale=${language} $packagemaker -AppleLanguages \"(${language})\" --root ${destpath} --out ${pkgpath} ${pkgresources} --info $infofile --target $pkgtarget --domain system --id org.macports.$portname"
123        } else {
124            write_info_plist ${workpath}/Info.plist $portname $portversion $portrevision
125            write_description_plist ${workpath}/Description.plist $portname $portversion $description
126            system "$packagemaker -build -f ${destpath} -p ${pkgpath} -r ${resourcepath} -i ${workpath}/Info.plist -d ${workpath}/Description.plist"
127        }
128
129        file delete ${workpath}/Info.plist
130        file delete ${workpath}/PackageInfo
131        file delete ${workpath}/Description.plist
132        file delete -force ${workpath}/pkg_resources
133
134    } else {
135
136        write_PkgInfo ${pkgpath}/Contents/PkgInfo
137        write_info_plist ${pkgpath}/Contents/Info.plist $portname $portversion $portrevision
138
139        system "[findBinary mkbom $portutil::autoconf::mkbom_path] ${destpath} ${pkgpath}/Contents/Archive.bom"
140        system "cd ${destpath} && [findBinary pax $portutil::autoconf::pax_path] -x [findBinary cpio $portutil::autoconf::cpio_path] -w -z . > ${pkgpath}/Contents/Archive.pax.gz"
141
142        write_description_plist ${resourcepath}/Description.plist $portname $portversion $description
143        write_sizes_file ${resourcepath}/Archive.sizes ${portname} ${portversion} ${pkgpath} ${destpath}
144
145    }
146
147    foreach dir {etc var tmp} {
148        if ([file exists "${destpath}/private/$dir"]) {
149            # restore any directories that were moved, to avoid confusing the rest of the ports system.
150            file rename ${destpath}/private/$dir ${destpath}/$dir
151        }
152    }
153    catch {file delete ${destpath}/private}
154
155    return 0
156}
157
158proc portpkg::write_PkgInfo {infofile} {
159    set infofd [open ${infofile} w+]
160    puts $infofd "pmkrpkg1"
161    close $infofd
162}
163
164# XXX: deprecated
165proc portpkg::write_info_file {infofile portname portversion description} {
166    set infofd [open ${infofile} w+]
167    puts $infofd "Title ${portname}
168Version ${portversion}
169Description ${description}
170DefaultLocation /
171DeleteWarning
172
173### Package Flags
174
175NeedsAuthorization YES
176Required NO
177Relocatable NO
178RequiresReboot NO
179UseUserMask YES
180OverwritePermissions NO
181InstallFat NO
182RootVolumeOnly NO"
183    close $infofd
184}
185
186proc portpkg::xml_escape {s} {
187    regsub -all {&} $s {\&} s
188    regsub -all {<} $s {\&lt;} s
189    regsub -all {>} $s {\&gt;} s
190    return $s
191}
192
193proc portpkg::write_info_plist {infofile portname portversion portrevision} {
194    set portname [xml_escape $portname]
195    set portversion [xml_escape $portversion]
196    set portrevision [xml_escape $portrevision]
197
198    set infofd [open ${infofile} w+]
199    puts $infofd {<?xml version="1.0" encoding="UTF-8"?>
200<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
201<plist version="1.0">
202    }
203    puts $infofd "<dict>
204    <key>CFBundleGetInfoString</key>
205    <string>${portname} ${portversion}</string>
206    <key>CFBundleIdentifier</key>
207    <string>org.macports.${portname}</string>
208    <key>CFBundleName</key>
209    <string>${portname}</string>
210    <key>CFBundleShortVersionString</key>
211    <string>${portversion}</string>
212    <key>IFMajorVersion</key>
213    <integer>${portrevision}</integer>
214    <key>IFMinorVersion</key>
215    <integer>0</integer>
216    <key>IFPkgFlagAllowBackRev</key>
217    <true/>
218    <key>IFPkgFlagAuthorizationAction</key>
219    <string>RootAuthorization</string>
220    <key>IFPkgFlagDefaultLocation</key>
221    <string>/</string>
222    <key>IFPkgFlagInstallFat</key>
223    <false/>
224    <key>IFPkgFlagIsRequired</key>
225    <false/>
226    <key>IFPkgFlagRelocatable</key>
227    <false/>
228    <key>IFPkgFlagRestartAction</key>
229    <string>NoRestart</string>
230    <key>IFPkgFlagRootVolumeOnly</key>
231    <false/>
232    <key>IFPkgFlagUpdateInstalledLanguages</key>
233    <false/>
234    <key>IFPkgFormatVersion</key>
235    <real>0.10000000149011612</real>
236</dict>
237</plist>"
238    close $infofd
239}
240
241proc portpkg::write_description_plist {infofile portname portversion description} {
242    set portname [xml_escape $portname]
243    set portversion [xml_escape $portversion]
244    set description [xml_escape $description]
245
246    set infofd [open ${infofile} w+]
247    puts $infofd {<?xml version="1.0" encoding="UTF-8"?>
248<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
249<plist version="1.0">
250    }
251    puts $infofd "<dict>
252    <key>IFPkgDescriptionDeleteWarning</key>
253    <string></string>
254    <key>IFPkgDescriptionDescription</key>
255    <string>${description}</string>
256    <key>IFPkgDescriptionTitle</key>
257    <string>${portname}</string>
258    <key>IFPkgDescriptionVersion</key>
259    <string>${portversion}</string>
260</dict>
261</plist>"
262    close $infofd
263}
264
265proc portpkg::write_welcome_html {filename portname portversion long_description description homepage} {
266    set fd [open ${filename} w+]
267    if {$long_description == ""} {
268        set long_description $description
269    }
270
271    set portname [xml_escape $portname]
272    set portversion [xml_escape $portversion]
273    set long_description [xml_escape $long_description]
274    set description [xml_escape $description]
275    set homepage [xml_escape $homepage]
276       
277    puts $fd "
278<html lang=\"en\">
279<head>
280        <meta http-equiv=\"content-type\" content=\"text/html; charset=iso-8859-1\">
281        <title>Install ${portname}</title>
282</head>
283<body>
284<font face=\"Helvetica\"><b>Welcome to the ${portname} for Mac OS X Installer</b></font>
285<p>
286<font face=\"Helvetica\">${long_description}</font>
287<p>"
288
289    if {$homepage != ""} {
290        puts $fd "<font face=\"Helvetica\"><a href=\"${homepage}\">${homepage}</a></font><p>"
291    }
292
293    puts $fd "<font face=\"Helvetica\">This installer guides you through the steps necessary to install ${portname} ${portversion} for Mac OS X. To get started, click Continue.</font>
294</body>
295</html>"
296
297    close $fd
298}
299
300proc portpkg::write_sizes_file {sizesfile portname portversion pkgpath destpath} {
301   
302    if {[catch {set numFiles [llength [split [exec [findBinary lsbom $portutil::autoconf::lsbom_path] -s ${pkgpath}/Contents/Archive.bom] "\n"]]} result]} {
303        return -code error [format [msgcat::mc "Reading package bom failed: %s"] $result]
304    }
305    if {[catch {set compressedSize [expr [dirSize ${pkgpath}] / 1024]} result]} {
306        return -code error [format [msgcat::mc "Error determining compressed size: %s"] $result]
307    }
308    if {[catch {set installedSize [expr [dirSize ${destpath}] / 1024]} result]} {
309        return -code error [format [msgcat::mc "Error determining installed size: %s"] $result]
310    }
311    if {[catch {set infoSize [file size ${pkgpath}/Contents/Info.plist]} result]} {
312       return -code error [format [msgcat::mc "Error determining plist file size: %s"] $result]
313    }
314    if {[catch {set bomSize [file size ${pkgpath}/Contents/Archive.bom]} result]} {
315        return -code error [format [msgcat::mc "Error determining bom file size: %s"] $result]
316    }
317    incr installedSize $infoSize
318    incr installedSize $bomSize
319       
320    set fd [open ${sizesfile} w+]
321    puts $fd "NumFiles $numFiles
322InstalledSize $installedSize
323CompressedSize $compressedSize"
324    close $fd
325}
326
327proc portpkg::write_package_info {infofile portname portversion portrevision} {
328    set portname [xml_escape $portname]
329    set portversion [xml_escape $portversion]
330    set portrevision [xml_escape $portrevision]
331
332    set infofd [open ${infofile} w+]
333    puts $infofd "
334<pkg-info install-location=\"/\" relocatable=\"false\" auth=\"root\">
335</pkg-info>"
336    close $infofd
337}
Note: See TracBrowser for help on using the repository browser.