source: trunk/base/portmgr/packaging/rpmall.tcl @ 27961

Last change on this file since 27961 was 26177, checked in by jmpp@…, 13 years ago

Finally merging the dp2mp-move branch into trunk, woot!

This basically means all strings in our sources,
whether it's something we output to the user or something
internal, such as a function/proc naming, are entirely in
the macports namespace and we no longer mix darwinports
with apple with macports strings.

It also means we now have new paths in svn and on
the client side at installation time, added to a
cleaner structure under ${prefix}/var/. Read
http://trac.macports.org/projects/macports/wiki/MacPortsRenaming
for more information.

NOTE: This commit also marks the rsync server finally
being moved over to the macosforge boxes, with the new
layout outlined in the dp2mp-move branch in place.
DNS entries still point to the old rsync server for
macports, however, so sync'ing/selfupdating an installation
based on these sources will be temporarily broken
until dns refresh.

To developers and testers, please do test the upgrade
target in the main base/Makefile as thouroughly as
possible and report any bugs/shortcomings/unexpected_behavior
to me, thanks!

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 13.7 KB
Line 
1#!/usr/bin/env tclsh
2# rpmall.tcl
3# $Id: rpmall.tcl 26177 2007-06-15 10:11:22Z jmpp@macports.org $
4#
5# Copyright (c) 2003 Benjamin Reed <ranger@befunk.com>
6# Copyright (c) 2003 Kevin Van Vechten <kevin@opendarwin.org>
7# Copyright (c) 2002 Apple Computer, Inc.
8# All rights reserved.
9#
10# Redistribution and use in source and binary forms, with or without
11# modification, are permitted provided that the following conditions
12# are met:
13# 1. Redistributions of source code must retain the above copyright
14#    notice, this list of conditions and the following disclaimer.
15# 2. Redistributions in binary form must reproduce the above copyright
16#    notice, this list of conditions and the following disclaimer in the
17#    documentation and/or other materials provided with the distribution.
18# 3. Neither the name of Apple Computer, Inc. nor the names of its contributors
19#    may be used to endorse or promote products derived from this software
20#    without specific prior written permission.
21#
22# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32# POSSIBILITY OF SUCH DAMAGE.
33
34package require darwinports
35
36# globals
37set portdir .
38
39# UI Instantiations
40array set ui_options {}
41# ui_options(ports_debug) - If set, output debugging messages.
42# ui_options(ports_verbose) - If set, output info messages (ui_info)
43# ui_options(ports_quiet) - If set, don't output "standard messages"
44
45# ui_options accessor
46proc ui_isset {val} {
47    global ui_options
48    if {[info exists ui_options($val)]} {
49        if {$ui_options($val) == "yes"} {
50            return 1
51        }
52    }
53    return 0
54}
55
56set options(package.destpath) "/darwinports/rpms"
57
58# UI Callback
59
60proc ui_prefix {priority} {
61    switch $priority {
62        debug {
63                return "DEBUG: "
64        }
65        error {
66                return "Error: "
67        }
68        warn {
69                return "Warning: "
70        }
71        default {
72                return ""
73        }
74    }
75}
76
77proc ui_channels {priority} {
78    global logfd
79    switch $priority {
80        debug {
81            if {[ui_isset ports_debug]} {
82                return {stdout}
83            } else {
84                return {}
85            }
86        }
87        info {
88                        # put verbose stuff only to the log file
89            if {[ui_isset ports_verbose]} {
90                return {$logfd}
91            } else {
92                return {}
93                        }
94                }
95        msg {
96            if {[ui_isset ports_quiet]} {
97                return {}
98                        } else {
99                                return {stdout}
100                        }
101                }
102        default {
103                return {stdout}
104        }
105    }
106}
107       
108proc pkg_ui_log {message} {
109    global logfd
110    if {[string length $logfd] > 0 } {
111        log_message $logfd $message
112    }
113}
114
115proc log_message {channel message} {
116    seek $channel 0 end
117    puts $channel $message
118    flush $channel
119}
120
121# Recursive bottom-up approach of building a list of dependencies.
122proc get_dependencies {portname includeBuildDeps} {
123        set result {}
124       
125        if {[catch {set search [dportsearch "^$portname\$"]} error]} {
126                global errorInfo
127                ui_debug "$errorInfo"
128                ui_error "Internal error: port search failed: $error"
129                return {}
130        }
131        foreach {name array} $search {
132                array set portinfo $array
133                if {![info exists portinfo(name)] ||
134                        ![info exists portinfo(version)] || 
135                        ![info exists portinfo(categories)]} {
136                        ui_error "Internal error: $name missing some portinfo keys"
137                        continue
138                }
139                if {![info exists portinfo(revision)]} {
140                        set portinfo(revision) 0
141                }
142               
143                set portname $portinfo(name)
144                set portversion $portinfo(version)
145                set revision $portinfo(revision)
146
147                # Append the package itself to the result list
148                lappend result [list $portname $portversion $revision]
149
150                # Append the package's dependents to the result list
151                set depends {}
152                if {[info exists portinfo(depends_run)]} { eval "lappend depends $portinfo(depends_run)" }
153                if {[info exists portinfo(depends_lib)]} { eval "lappend depends $portinfo(depends_lib)" }
154                if {$includeBuildDeps != "" && [info exists portinfo(depends_build)]} { 
155                        eval "lappend depends $portinfo(depends_build)"
156                }
157                foreach depspec $depends {
158                        set dep [lindex [split $depspec :] end]
159                        set x [get_dependencies $dep $includeBuildDeps]
160                        eval "lappend result $x"
161                        set result [lsort -unique $result]
162                }
163        }
164        return $result
165}
166
167# Install binary packages if they've already been built.  This will
168# speed up the testing, since we won't have to recompile dependencies
169# which have already been compiled.
170
171proc install_binary_if_available {dep} {
172        set portname [lindex $dep 0]
173        set portversion [lindex $dep 1]
174        set revision [lindex $dep 2]
175
176        foreach dir {"${prefix}/src/apple/RPMS" "/usr/src/apple/RPMS" "/darwinports/rpms/RPMS"} {
177                foreach arch {"ppc" "i386" "fat"} {
178                        set rpmpath "${dir}/${arch}/${portname}-${portversion}-${revision}.${arch}.rpm"
179                        if {[file readable $rpmpath]} {
180                                ui_msg "Installing binary: $rpmpath"
181                                if {[catch {system "rpm -Uvh --force $rpmpath"} error ]} {
182                                        global errorInfo
183                                        ui_debug "$errorInfo"
184                                        ui_error "Internal error: $error"
185                                } else {
186                                        return true
187                                }
188                        }
189                }
190        }
191        return false
192}
193
194
195# Standard procedures
196
197proc fatal args {
198    global argv0
199    puts stderr "$argv0: $args"
200    exit
201}
202
203# Main
204array set options [list]
205array set variations [list]
206
207#       set ui_options(ports_verbose) yes
208if {![file exists /usr/bin/sw_vers]} {
209        set variations(puredarwin) "+"
210}
211
212if {[catch {dportinit ui_options options variations} result]} {
213    puts "Failed to initialize ports system, $result"
214    exit 1
215}
216
217package require Pextlib
218
219# If no arguments were given, default to all ports.
220if {[llength $argv] == 0} {
221        lappend argv ".*"
222}
223
224foreach pname $argv {
225
226if {[catch {set allpackages [dportsearch "^${pname}\$"]} result]} {
227        puts "port search failed: $result"
228        exit 1
229}
230
231set logpath "/darwinports/logs"
232set logfd ""
233
234foreach {name array} $allpackages {
235        array unset portinfo
236        array set portinfo $array
237
238        #ui_msg "foo $portinfo(porturl)"
239
240        # Start with verbose output off;
241        # this will prevent the repopulation of /opt from getting logged.
242        set ui_options(ports_verbose) no
243
244        if {![info exists portinfo(porturl)]} {
245                puts stderr "Internal error: no porturl for $name"
246                continue
247        }
248        if {![info exists portinfo(revision)]} {
249                set portinfo(revision) 0
250        }
251
252        set porturl $portinfo(porturl)
253
254        # this is used to short-circuit the RPM check and
255        # move on to the next package
256
257        global exit_loop
258        set exit_loop false
259
260        # Skip up-to-date packages
261        if {[regsub {^file://} $portinfo(porturl) "" portpath]} {
262                if {[info exists portinfo(name)] &&
263                        [info exists portinfo(version)] &&
264                        [info exists portinfo(revision)]} {
265                        set portname $portinfo(name)
266                        set portversion $portinfo(version)
267                        set revision $portinfo(revision)
268
269                        foreach dir {"/opt/local/src/apple/RPMS" "/usr/src/apple/RPMS" "/darwinports/rpms/RPMS"} {
270                                foreach arch {"ppc" "i386" "fat"} {
271                                        set rpmpath "${dir}/${arch}/${portname}-${portversion}-${revision}.${arch}.rpm"
272                                        #ui_msg "trying ${rpmpath}"
273                                        if {[file readable $rpmpath] && ([file mtime ${rpmpath}] >= [file mtime ${portpath}/Portfile])} {
274                                                puts stderr "->    skipping ${portname}-${portversion}; package is up to date."
275                                                set exit_loop true
276                                                break
277                                        }
278                                }
279                                if {${exit_loop}} {
280                                        break
281                                }
282                        }
283                }
284        }
285        if {${exit_loop}} {
286                continue
287        }
288       
289        # Skip packages which previously failed
290        set exit_loop false
291               
292        # Skip up-to-date packages
293        if {[regsub {^file://} $portinfo(porturl) "" portpath]} {
294                if {[info exists portinfo(name)] &&
295                        [info exists portinfo(version)] &&
296                        [info exists portinfo(revision)]} {
297                        set portname $portinfo(name)
298                        set portversion $portinfo(version)
299                        set revision $portinfo(revision)
300
301                        set logfilepath "${logpath}/${portname}.log"
302                        if {[file readable ${logfilepath}] && ([file mtime ${logfilepath}] > [file mtime ${portpath}/Portfile])} {
303                                puts stderr "->    skipping ${portname}-${portversion}; package failed, but has not changed."
304                                set exit_loop true
305                        }
306                }
307        }
308        if {${exit_loop}} {
309                continue
310        }
311       
312        # Building the port:
313        # - remove /opt so it won't pollute the port.
314        # - re-install DarwinPorts.
315        # - keep distfiles outside /opt so we don't have to keep fetching them.
316        # - send out an email to the maintainer if any errors occurred.
317
318        set remove_files ""
319        foreach dir {"/opt/local/src/apple/RPMS" "/usr/src/apple/RPMS" "/darwinports/rpms/RPMS"} {
320                foreach arch {"ppc" "i386" "fat"} {
321                        set remove_files "${remove_files} '${dir}/${arch}/'*.rpm"
322                }
323        }
324        system "rpm -q --queryformat='%{name} ' -p ${remove_files} | xargs rpm -e || true"
325
326        ui_msg "->    Removing /opt"
327        #unset ui_options(ports_verbose)
328        if {[catch {system "rm -Rf /opt"} error]} {
329                puts stderr "Internal error: $error"
330        }
331        # this is bad on pure darwin  :)
332        #if {[catch {system "rm -Rf /usr/X11R6"} error]} {
333        #       puts stderr "Internal error: $error"
334        #}
335        #if {[catch {system "rm -Rf /etc/X11"} error]} {
336        #       puts stderr "Internal error: $error"
337        #}
338        #if {[catch {system "rm -Rf /etc/fonts"} error]} {
339        #       puts stderr "Internal error: $error"
340        #}
341        ui_msg "->    Installing darwinports"
342        if {[catch {system "cd $env(HOME)/darwinports && make && make install"} error]} {
343                puts stderr "Internal error: $error"
344        }
345        if {[catch {system "rmdir /opt/local/var/db/dports/distfiles"} error]} {
346                puts stderr "Internal error: $error"
347        }
348        if {[catch {system "ln -s /darwinports/distfiles /opt/local/var/db/dports/distfiles"} error]} {
349                puts stderr "Internal error: $error"
350        }
351        #set ui_options(ports_verbose) yes
352
353        # If there was a log file left over from the previous pass,
354        # then the port failed with an error.  Send the log in an
355        # email to the maintainers.
356        if {[string length $logfd] > 0} {
357                close $logfd
358                set logfd ""
359        }
360        #if {[file readable $logfilename]} {
361        #       if {[catch {system "cat $logfilename | /usr/sbin/sendmail -t"} error]} {
362        #               puts stderr "Internal error: $error"
363        #       }
364        #}
365
366        # Open the log file for writing
367        set logfd [open ${logpath}/${name}.log w]
368
369        set valid 1
370
371        set lint_errors {}
372        set portname ""
373        set portversion ""
374        set description ""
375        set category ""
376
377        if {![info exists portinfo(name)]} {
378                lappend lint_errors "missing name key"
379                set valid 0
380        } else {
381                set portname $portinfo(name)
382        }
383       
384        if {![info exists portinfo(description)]} {
385                lappend lint_errors "missing description key"
386                set valid 0
387        } else {
388                set description $portinfo(description)
389        }
390       
391        if {![info exists portinfo(version)]} {
392                lappend lint_errors "missing version key"
393                set valid 0
394        } else {
395                set portversion $portinfo(version)
396        }
397       
398        if {![info exists portinfo(categories)]} {
399                lappend lint_errors "missing categories key"
400                set valid 0
401        } else {
402                set category [lindex $portinfo(categories) 0]
403        }
404       
405        if {![info exists portinfo(maintainers)]} {
406                append lint_errors "missing maintainers key"
407                set valid 0
408                set maintainers kevin@opendarwin.org
409        } else {
410                set maintainers $portinfo(maintainers)
411        }
412       
413        pkg_ui_log "To: [join $maintainers {, }]"
414        pkg_ui_log "From: donotreply@opendarwin.org"
415        pkg_ui_log "Subject: DarwinPorts $portinfo(name)-$portinfo(version) build failure"
416        pkg_ui_log ""
417        pkg_ui_log "The following is a transcript produced by the DarwinPorts automated build       "
418        pkg_ui_log "system.  You are receiving this email because you are listed as a maintainer    "
419        pkg_ui_log "of this port, which has failed the automated packaging process.  Please update  "
420        pkg_ui_log "the port as soon as possible."
421        pkg_ui_log ""
422        pkg_ui_log ""
423        pkg_ui_log "Thank you,"
424        pkg_ui_log "The DarwinPorts Team"
425        pkg_ui_log ""
426        pkg_ui_log "================================================================================"
427        pkg_ui_log ""
428
429        if {!$valid} {
430                foreach error $lint_errors {
431                        ui_error $error
432                }
433        }
434
435        ui_msg "-->   Packaging ${category}/${portname}-${portversion}"
436
437        foreach prebuild {"ccache" "rpm" "unzip"} {
438                if {![file exists /bin/${prebuild}] && ![file exists /usr/bin/${prebuild}]} {
439                        ui_msg "--->  Pre-installing ${prebuild}"
440                        if {[catch {set search [dportsearch "^${prebuild}\$"]} error]} {
441                                global errorInfo
442                                ui_debug "$errorInfo"
443                                ui_error "Internal error: port search ${prebuild} failed: $error"
444                        }
445                        array set prebuildinfo [lindex $search 1]
446                        set ui_options(ports_verbose) yes
447                        if {[catch {set workername [dportopen $prebuildinfo(porturl) [array get options] [array get variations] yes]} result] ||
448                                $result == 1} {
449                                global errorInfo
450                                ui_debug "$errorInfo"
451                                ui_error "Internal error: unable to install ${prebuild}... exiting"
452                                exit 1
453                        }
454                        if {[catch {set result [dportexec $workername install]} result] ||
455                                $result == 1} {
456                                global errorInfo
457                                ui_debug "$errorInfo"
458                                ui_error "installation of ${prebuild} failed: $result"
459                                dportclose $workername
460                                exit 1
461                        }
462                }
463        }
464
465        # Turn on verbose output for the build
466        set ui_options(ports_verbose) yes
467        if {[catch {set workername [dportopen $porturl [array get options] [array get variations]]} result] ||
468                $result == 1} {
469                global errorInfo
470                ui_debug "$errorInfo"
471            ui_error "Internal error: unable to open port: $result"
472            continue
473        }
474        if {[catch {set result [dportexec $workername rpmpackage]} result] ||
475                $result == 1} {
476                global errorInfo
477                ui_debug "$errorInfo"
478            ui_error "port package failed: $result"
479                dportclose $workername
480            continue
481        }
482        set ui_options(ports_verbose) no
483        # Turn verbose output off after the build
484
485        dportclose $workername
486
487        # We made it to the end.  We can delete the log file.
488        close $logfd
489        set logfd ""
490        file delete ${logpath}/${name}.log
491}
492
493}
494# end foreach pname
Note: See TracBrowser for help on using the repository browser.