source: trunk/base/src/port1.0/portdestroot.tcl @ 30086

Last change on this file since 30086 was 30086, checked in by nox@…, 12 years ago

port1.0/startupitem (closes #12931): Added daemondo --restart-netchange flag (bool startupitem.netchange).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 13.0 KB
Line 
1# et:ts=4
2# portdestroot.tcl
3# $Id: portdestroot.tcl 30086 2007-10-19 11:44:14Z nox@macports.org $
4#
5# Copyright (c) 2002 - 2003 Apple Computer, Inc.
6# Copyright (c) 2004 - 2005 Robert Shaw <rshaw@opendarwin.org>
7# All rights reserved.
8#
9# Redistribution and use in source and binary forms, with or without
10# modification, are permitted provided that the following conditions
11# are met:
12# 1. Redistributions of source code must retain the above copyright
13#    notice, this list of conditions and the following disclaimer.
14# 2. Redistributions in binary form must reproduce the above copyright
15#    notice, this list of conditions and the following disclaimer in the
16#    documentation and/or other materials provided with the distribution.
17# 3. Neither the name of Apple Computer, Inc. nor the names of its contributors
18#    may be used to endorse or promote products derived from this software
19#    without specific prior written permission.
20#
21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31# POSSIBILITY OF SUCH DAMAGE.
32#
33
34package provide portdestroot 1.0
35package require portutil 1.0
36
37set org.macports.destroot [target_new org.macports.destroot destroot_main]
38target_provides ${org.macports.destroot} destroot
39target_requires ${org.macports.destroot} main fetch extract checksum patch configure build
40target_prerun ${org.macports.destroot} destroot_start
41target_postrun ${org.macports.destroot} destroot_finish
42
43# define options
44options destroot.target destroot.destdir destroot.clean destroot.keepdirs destroot.umask
45options destroot.violate_mtree
46options startupitem.create startupitem.requires startupitem.init
47options startupitem.name startupitem.start startupitem.stop startupitem.restart
48options startupitem.type startupitem.executable
49options startupitem.pidfile startupitem.logfile startupitem.logevents startupitem.netchange
50commands destroot
51
52# Set defaults
53default destroot.dir {${build.dir}}
54default destroot.cmd {${build.cmd}}
55default destroot.pre_args {${destroot.target}}
56default destroot.target install
57default destroot.post_args {${destroot.destdir}}
58default destroot.destdir {DESTDIR=${destroot}}
59default destroot.umask {$system_options(destroot_umask)}
60default destroot.clean no
61default destroot.keepdirs ""
62default destroot.violate_mtree no
63
64default startupitem.name        {${portname}}
65default startupitem.init        ""
66default startupitem.start       ""
67default startupitem.stop        ""
68default startupitem.restart     ""
69default startupitem.requires    ""
70default startupitem.executable  ""
71default startupitem.type        {$system_options(startupitem_type)}
72default startupitem.pidfile     ""
73default startupitem.logfile     ""
74default startupitem.logevents   no
75default startupitem.netchange   no
76
77set_ui_prefix
78
79namespace eval destroot {
80    # Save old umask
81    variable oldmask
82}
83
84proc destroot_start {args} {
85    global UI_PREFIX prefix portname destroot portresourcepath os.platform destroot.clean
86    global destroot::oldmask destroot.umask
87   
88    ui_msg "$UI_PREFIX [format [msgcat::mc "Staging %s into destroot"] ${portname}]"
89
90    set oldmask [umask ${destroot.umask}]
91    set mtree ${portutil::autoconf::mtree_path}
92   
93    if { ${destroot.clean} == "yes" } {
94        system "rm -Rf \"${destroot}\""
95    }
96   
97    file mkdir "${destroot}"
98    if { ${os.platform} == "darwin" } {
99        system "cd \"${destroot}\" && ${mtree} -e -U -f ${portresourcepath}/install/macosx.mtree"
100    }
101    file mkdir "${destroot}/${prefix}"
102    system "cd \"${destroot}/${prefix}\" && ${mtree} -e -U -f ${portresourcepath}/install/prefix.mtree"
103}
104
105proc destroot_main {args} {
106    command_exec destroot
107    return 0
108}
109
110proc destroot_finish {args} {
111    global UI_PREFIX destroot prefix portname startupitem.create destroot::oldmask destroot.violate_mtree
112    global os.platform os.version
113
114    # Create startup-scripts/items
115    if {[tbool startupitem.create]} {
116        package require portstartupitem 1.0
117        startupitem_create
118    }
119
120    # Prune empty directories in ${destroot}
121    set exclude_dirs [list]
122    set exclude_phrase ""
123    foreach path [option destroot.keepdirs] {
124        if {![file isdirectory ${path}]} {
125            xinstall -m 0755 -d ${path}
126        }
127        if {![file exists ${path}/.turd_${portname}]} {
128            xinstall -c -m 0644 /dev/null ${path}/.turd_${portname}
129        }
130        lappend exclude_dirs "-path \"${path}\""
131    }
132    if { [llength ${exclude_dirs}] > 0 } {
133        set exclude_phrase "! \\( [join ${exclude_dirs} " -or "] \\)"
134    }
135    catch {system "find \"${destroot}\" -depth -type d ${exclude_phrase} -exec rmdir -- \{\} \\; 2>/dev/null"}
136
137    # Compress all manpages with gzip (instead)
138    # but NOT on Jaguar (Darwin 6.x)
139    if {![regexp {darwin6} "${os.platform}${os.version}"]} {
140        set manpath "${destroot}${prefix}/share/man"
141        if {[file isdirectory ${manpath}] && [file type ${manpath}] == "directory"} {
142            ui_info "$UI_PREFIX [format [msgcat::mc "Compressing man pages for %s"] ${portname}]"
143            set found 0
144            set manlinks [list]
145            foreach mandir [readdir "${manpath}"] {
146                if {![regexp {^(cat|man)(.)$} ${mandir} match ignore manindex]} { continue }
147                set mandirpath [file join ${manpath} ${mandir}]
148                if {[file isdirectory ${mandirpath}] && [file type ${mandirpath}] == "directory"} {
149                    ui_debug "Scanning ${mandir}"
150                    foreach manfile [readdir ${mandirpath}] {
151                        set manfilepath [file join ${mandirpath} ${manfile}]
152                        if {[file isfile ${manfilepath}] && [file type ${manfilepath}] == "file"} {
153                            if {[regexp "^(.*\[.\]${manindex}\[a-z\]*)\[.\]gz\$" ${manfile} gzfile manfile]} {
154                                set found 1
155                                system "cd ${manpath} && \
156                                gunzip -f [file join ${mandir} ${gzfile}] && \
157                                gzip -9vf [file join ${mandir} ${manfile}]"
158                            } elseif {[regexp "^(.*\[.\]${manindex}\[a-z\]*)\[.\]bz2\$" ${manfile} bz2file manfile]} {
159                                set found 1
160                                system "cd ${manpath} && \
161                                bunzip2 -f [file join ${mandir} ${bz2file}] && \
162                                gzip -9vf [file join ${mandir} ${manfile}]"
163                            } elseif {[regexp "\[.\]${manindex}\[a-z\]*\$" ${manfile}]} {
164                                set found 1
165                                system "cd ${manpath} && \
166                                gzip -9vf [file join ${mandir} ${manfile}]"
167                            }
168                            set gzmanfile ${manfile}.gz
169                            set gzmanfilepath [file join ${mandirpath} ${gzmanfile}]
170                            if {[file exists ${gzmanfilepath}]} {
171                                set desired 00444
172                                set current [file attributes ${gzmanfilepath} -permissions]
173                                if {$current != $desired} {
174                                    ui_info "[file join ${mandir} ${gzmanfile}]: changing permissions from $current to $desired"
175                                    file attributes ${gzmanfilepath} -permissions $desired
176                                }
177                            }
178                        } elseif {[file type ${manfilepath}] == "link"} {
179                            lappend manlinks [file join ${mandir} ${manfile}]
180                        }
181                    }
182                }
183            }
184            if {$found == 1} {
185                # check man page links and rename/repoint them if necessary
186                foreach manlink $manlinks {
187                    set manlinkpath [file join $manpath $manlink]
188                    # if link destination is not gzipped, check it
189                    set manlinksrc [file readlink $manlinkpath]
190                    if {![regexp "\[.\]gz\$" ${manlinksrc}]} {
191                        set mandir [file dirname $manlink]
192                        set mandirpath [file join $manpath $mandir]
193                        set pwd [pwd]
194                        if {[catch {_cd $mandirpath} err]} {
195                            puts $err
196                            return
197                        }
198                        # if gzipped destination exists, fix link
199                        if {[file isfile ${manlinksrc}.gz]} {
200                            # if actual link name does not end with gz, rename it
201                            if {![regexp "\[.\]gz\$" ${manlink}]} {
202                                ui_debug "renaming link: $manlink to ${manlink}.gz"
203                                file rename $manlinkpath ${manlinkpath}.gz
204                                set manlink ${manlink}.gz
205                                set manlinkpath [file join $manpath $manlink]
206                            }
207                            # repoint the link
208                            ui_debug "repointing link: $manlink from $manlinksrc to ${manlinksrc}.gz"
209                            file delete $manlinkpath
210                            system "ln -s \"${manlinksrc}.gz\" \"$manlinkpath\""
211                        }
212                        _cd $pwd
213                    }
214                }
215            } else {
216                ui_debug "No man pages found to compress."
217            }
218        }
219    } else {
220        ui_debug "No man page compression on ${os.platform}${os.version}."
221    }
222
223    if [file exists "${destroot}${prefix}/share/info/dir"] {
224        ui_debug "Deleting stray info/dir file."
225        file delete "${destroot}${prefix}/share/info/dir"
226    }
227
228    # test for violations of mtree
229    if { ${destroot.violate_mtree} != "yes" } {
230        ui_debug "checking for mtree violations"
231        set mtree_violation "no"
232
233        set prefixPaths [list bin etc include lib libexec sbin share src var www Applications Developer Library]
234
235        set pathsToCheck [list /]
236        while {[llength $pathsToCheck] > 0} {
237            set pathToCheck [lshift pathsToCheck]
238            foreach file [glob -nocomplain -directory $destroot$pathToCheck .* *] {
239                if {[file tail $file] eq "." || [file tail $file] eq ".."} {
240                    continue
241                }
242                if {[string equal -length [string length $destroot] $destroot $file]} {
243                    # just double-checking that $destroot is a prefix, as is appropriate
244                    set dfile [file join / [string range $file [string length $destroot] end]]
245                } else {
246                    throw MACPORTS "Unexpected filepath `${file}' while checking for mtree violations"
247                }
248                if {$dfile eq $prefix} {
249                    # we've found our prefix
250                    foreach pfile [glob -nocomplain -tails -directory $file .* *] {
251                        if {$pfile eq "." || $pfile eq ".."} {
252                            continue
253                        }
254                        if {[lsearch -exact $prefixPaths $pfile] == -1} {
255                            ui_warn "violation by [file join $dfile $pfile]"
256                            set mtree_violation "yes"
257                        }
258                    }
259                } elseif {[string equal -length [expr [string length $dfile] + 1] $dfile/ $prefix]} {
260                    # we've found a subpath of our prefix
261                    lpush pathsToCheck $dfile
262                } else {
263                    # these files are outside of the prefix
264                    switch $dfile {
265                        /Applications -
266                        /Developer -
267                        /Library { ui_debug "port installs files in $dfile" }
268                        default {
269                            ui_warn "violation by $dfile"
270                            set mtree_violation "yes"
271                        }
272                    }
273                }
274            }
275        }
276
277        # abort here only so all violations can be observed
278        if { ${mtree_violation} != "no" } {
279            ui_warn "[format [msgcat::mc "%s violates the layout of the ports-filesystems!"] [option portname]]"
280            ui_warn "Please fix or indicate this misbehavior (if it is intended), it will be an error in future releases!"
281            # error "mtree violation!"
282        }
283    } else {
284        ui_warn "[format [msgcat::mc "%s requests to install files outside the common directory structure!"] [option portname]]"
285    }
286
287    # Restore umask
288    umask $oldmask
289
290    return 0
291}
Note: See TracBrowser for help on using the repository browser.