source: trunk/base/src/port1.0/portpackage.tcl @ 1607

Last change on this file since 1607 was 1607, checked in by landonf (Landon Fuller), 18 years ago

Pull contents out of registry, and do not set package destination to install prefix
This allows us to support ports who have files that must be installed in /

  • Property svn:eol-style set to native
File size: 11.9 KB
Line 
1# et:ts=4
2# portpackage.tcl
3#
4# Copyright (c) 2002 Apple Computer, Inc.
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15# 3. Neither the name of Apple Computer, Inc. nor the names of its contributors
16#    may be used to endorse or promote products derived from this software
17#    without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29# POSSIBILITY OF SUCH DAMAGE.
30#
31
32package provide portpackage 1.0
33package require portutil 1.0
34
35set com.apple.package [target_new com.apple.package package_main]
36${com.apple.package} set runtype always
37${com.apple.package} provides package
38${com.apple.package} requires registry
39
40# define options
41options package.type package.destpath
42
43# Set defaults
44default package.type pkg
45default package.destpath {${workpath}}
46
47set UI_PREFIX "---> "
48
49proc package_main {args} {
50    global portname portversion package.type package.destpath UI_PREFIX
51
52    set rfile [registry_exists $portname $portversion]
53    if ![string length $rfile] {
54        ui_error "Package ${portname}-${portversion} not installed on this system"
55        return -code error "Package ${portname}-${portversion} not installed on this system"
56    }
57    ui_msg "$UI_PREFIX Creating ${package.type} format package for ${portname}-${portversion}"
58    if [regexp .bz2$ $rfile] {
59        set fd [open "|bunzip2 -c $rfile" r]
60    } else {
61        set fd [open $rfile r]
62    }
63    set entry [read $fd]
64    close $fd
65
66    # Make sure the destination path exists.
67    system "mkdir -p ${package.destpath}"
68
69    # For now we only support pkg and tarball package types.
70    switch -exact -- ${package.type} {
71        pkg {
72            return [package_pkg $portname $portversion $entry]
73        }
74        tarball {
75            return [package_tarball $portname $portversion $entry]
76        }
77        default {
78            ui_error "Do not know how to generate package of type ${package.type}"
79            return -code error "Unknown package type: ${package.type}"
80        }
81    }
82}
83
84# Make a tarball version of a package.  This is our "built-in" packaging
85# method.
86proc package_tarball {portname portversion entry} {
87    global portdbpath package.destpath
88
89    set rfile [registry_exists $portname $portversion]
90    set ix [lsearch $entry contents]
91    if {$ix >= 0} {
92        set contents [lindex $entry [incr ix]]
93        set plist [mkstemp /tmp/XXXXXXXX]
94        set pfile [lindex $plist 0]
95        foreach f $contents {
96            set fname [lindex $f 0]
97            puts $pfile $fname
98        }
99        puts $pfile $rfile
100        close $pfile
101
102        set ptarget ${package.destpath}/${portname}-${portversion}.tar.gz
103        if [catch {system "gnutar -T [lindex $plist 1] -czPpf ${ptarget}"} err] {
104            ui_error "Package creation failed - gnutar returned error status: $err"
105            ui_info "Failed packing list left in [lindex $plist 1]"
106            return -code error "Package creation failed - gnutar returned error status: $err"
107        }
108        exec rm [lindex $plist 1]
109    } else {
110        ui_error "Bad registry entry for ${portname}-${portversion}, no contents"
111        return -code error "Bad registry entry for ${portname}-${portversion}, no contents"
112    }
113    return 0
114}
115
116proc package_pkg {portname portversion entry} {
117    global portdbpath destpath workpath prefix portresourcepath description package.destpath long_description homepage
118
119    set resourcepath ${workpath}/pkg_resources
120    set rfile [registry_exists $portname $portversion]
121    set ix [lsearch $entry contents]
122    # If contents entry exists, transplant installed files into ${destpath}
123    # Otherwise, presume that they are already installed in ${destpath} path
124    if {$ix >= 0} {
125        set plist [mkstemp ${workpath}/.${portname}.plist.XXXXXXXXX]
126        set pfile [lindex $plist 0]
127
128        set receipt_contents [lindex $entry [incr ix]]
129        foreach f $receipt_contents {
130            set fname [lindex $f 0]
131            puts $pfile $fname
132        }
133        close $pfile
134
135        if {![file isdirectory $destpath]} {
136            if {[catch {file mkdir $destpath} result]} {
137                ui_error "Unable to create destination root path: $result"
138                return -code error "Unable to create destination root path: $result"
139            }
140        }
141
142        if [catch {system "gnutar -T [lindex $plist 1] -cPpf - | (cd ${destpath} && tar xvf -)"} return] {
143            ui_error "Package creation failed - gnutar returned error status: $return"
144            file delete [lindex $plist 1]
145            return -code error "Package creation failed - gnutar returned error status: $return"
146        }
147        file delete [lindex $plist 1]
148    }
149    if {![file isdirectory $resourcepath]} {
150        if {[catch {file mkdir $resourcepath} result]} {
151            ui_error "Unable to create package resource directory: $result"
152            return -code error "Unable to create package resource directory: $result"
153        }
154    }
155
156    # XXX: we need to support .lproj in resources.
157    set pkgpath ${package.destpath}/${portname}.pkg
158    system "mkdir -p -m 0755 ${pkgpath}/Contents/Resources"
159    write_PkgInfo ${pkgpath}/Contents/PkgInfo
160    write_info_file ${pkgpath}/Contents/Resources/${portname}.info $portname $portversion $description
161    write_info_plist ${pkgpath}/Contents/Info.plist $portname $portversion
162    write_description_plist ${pkgpath}/Contents/Resources/Description.plist $portname $portversion $description
163    # long_description, description, or homepage may not exist
164    foreach variable {long_description description homepage} {
165        if {![info exists $variable]} {
166            set pkg_$variable ""
167        } else {
168            set pkg_$variable [set $variable]
169        }
170    }
171    write_welcome_rtf ${pkgpath}/Contents/Resources/Welcome.rtf $portname $portversion $pkg_long_description $pkg_description $pkg_homepage
172    file copy -force -- ${portresourcepath}/package/background.tiff ${pkgpath}/Contents/Resources/background.tiff
173    system "mkbom ${destpath} ${pkgpath}/Contents/Archive.bom"
174    system "cd ${pkgpath}/Contents/Resources/ && ln -fs ../Archive.bom ${portname}.bom"
175    system "cd ${destpath} && pax -w -z . > ${pkgpath}/Contents/Archive.pax.gz"
176    system "cd ${pkgpath}/Contents/Resources/ && ln -fs ../Archive.pax.gz ${portname}.pax.gz"
177
178    write_sizes_file ${pkgpath}/Contents/Resources/${portname}.sizes ${portname} ${pkgpath} ${destpath}
179
180    return 0
181}
182
183proc dirSize {dir} {
184    set size    0;
185    foreach file [readdir $dir] {
186        if {$file == "." || $file == ".."} {
187            continue
188        }
189        if {[file isdirectory [file join $dir $file]]} {
190            incr size [dirSize [file join $dir $file]]
191        } else {
192            incr size [file size [file join $dir $file]];
193        }
194    }
195    return $size;
196}
197
198proc write_PkgInfo {infofile} {
199        set infofd [open ${infofile} w+]
200        puts $infofd "pmkrpkg1"
201        close $infofd
202}
203
204proc write_info_file {infofile portname portversion description} {
205        set infofd [open ${infofile} w+]
206        puts $infofd "Title ${portname}
207Version ${portversion}
208Description ${description}
209DefaultLocation /
210DeleteWarning
211
212### Package Flags
213
214NeedsAuthorization YES
215Required NO
216Relocatable NO
217RequiresReboot NO
218UseUserMask YES
219OverwritePermissions NO
220InstallFat NO
221RootVolumeOnly NO"
222        close $infofd
223}
224
225proc write_info_plist {infofile portname portversion} {
226        set vers [split $portversion "."]
227        set major [lindex $vers 0]
228        set minor [lindex $vers 1]
229        if {$major == ""} {set major "0"}
230        if {$minor == ""} {set minor "0"}
231               
232        set infofd [open ${infofile} w+]
233        puts $infofd {<?xml version="1.0" encoding="UTF-8"?>
234<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
235<plist version="1.0">
236}
237        puts $infofd "<dict>
238        <key>CFBundleGetInfoString</key>
239        <string>${portname} ${portversion}</string>
240        <key>CFBundleIdentifier</key>
241        <string>org.opendarwin.darwinports.${portname}</string>
242        <key>CFBundleName</key>
243        <string>${portname}</string>
244        <key>CFBundleShortVersionString</key>
245        <string>${portversion}</string>
246        <key>IFMajorVersion</key>
247        <integer>${major}</integer>
248        <key>IFMinorVersion</key>
249        <integer>${minor}</integer>
250        <key>IFPkgFlagAllowBackRev</key>
251        <true/>
252        <key>IFPkgFlagAuthorizationAction</key>
253        <string>RootAuthorization</string>
254        <key>IFPkgFlagDefaultLocation</key>
255        <string>/</string>
256        <key>IFPkgFlagInstallFat</key>
257        <false/>
258        <key>IFPkgFlagIsRequired</key>
259        <false/>
260        <key>IFPkgFlagRelocatable</key>
261        <false/>
262        <key>IFPkgFlagRestartAction</key>
263        <string>NoRestart</string>
264        <key>IFPkgFlagRootVolumeOnly</key>
265        <false/>
266        <key>IFPkgFlagUpdateInstalledLanguages</key>
267        <false/>
268        <key>IFPkgFormatVersion</key>
269        <real>0.10000000149011612</real>
270</dict>
271</plist>"
272        close $infofd
273}
274
275proc write_description_plist {infofile portname portversion description} {
276        set infofd [open ${infofile} w+]
277        puts $infofd {<?xml version="1.0" encoding="UTF-8"?>
278<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
279<plist version="1.0">
280}
281        puts $infofd "<dict>
282        <key>IFPkgDescriptionDeleteWarning</key>
283        <string></string>
284        <key>IFPkgDescriptionDescription</key>
285        <string>${description}</string>
286        <key>IFPkgDescriptionTitle</key>
287        <string>${portname}</string>
288        <key>IFPkgDescriptionVersion</key>
289        <string>${portversion}</string>
290</dict>
291</plist>"
292        close $infofd
293}
294
295proc write_welcome_rtf {filename portname portversion long_description description homepage} {
296    set fd [open ${filename} w+]
297    if {$long_description == ""} {
298        set long_description $description
299    }
300    puts $fd \
301"{\\rtf1\\mac\\ansicpg10000\\cocoartf102
302{\\fonttbl\\f0\\fswiss\\fcharset77 Helvetica-Bold;\\f1\\fswiss\\fcharset77 Helvetica;}
303{\\colortbl;\\red255\\green255\\blue255;\\red1\\green1\\blue1;}
304\\vieww9000\\viewh9000\\viewkind0
305\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\ql\\qnatural
306
307\\f0\\b\\fs24 \\cf2 Welcome to the ${portname} for Mac OS X Installer\\
308\\
309\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\ql\\qnatural
310"
311    puts $fd "\\f1\\b0 \\cf2 ${long_description} \\\n\\"
312    if {$homepage != ""} {
313        puts $fd "${homepage} \\\n\\"
314    }
315    puts $fd "This installer guides you through the steps necessary to install ${portname} ${portversion} for Mac OS X. To get started, click Continue.\\\n}"
316
317    close $fd
318}
319
320proc write_sizes_file {sizesfile portname pkgpath destpath} {
321   
322    if {[catch {set numFiles [exec lsbom -s ${pkgpath}/Contents/Archive.bom | wc -l]} result]} {
323        return -code error "Reading package bom failed: $result"
324    }
325    if {[catch {set compressedSize [expr [dirSize ${pkgpath}] / 1024]} result]} {
326        return -code error "Error determining compressed size: $result"
327    }
328    if {[catch {set installedSize [expr [dirSize ${destpath}] / 1024]} result]} {
329        return -code error "Error determining installed size: $result"
330    }
331    if {[catch {set infoSize [file size ${pkgpath}/Contents/Resources/${portname}.info]} result]} {
332        return -code error "Error determining info file size: $result"
333    }
334    if {[catch {set bomSize [file size ${pkgpath}/Contents/Archive.bom]} result]} {
335        return -code error "Error determining bom file size: $result"
336    }
337    incr installedSize $infoSize
338    incr installedSize $bomSize
339       
340    set fd [open ${sizesfile} w+]
341    puts $fd "NumFiles $numFiles
342InstalledSize $installedSize
343CompressedSize $compressedSize"
344    close $fd
345}
Note: See TracBrowser for help on using the repository browser.