Ticket #620: rpmall.2.patch

File rpmall.2.patch, 14.5 KB (added by ranger@…, 21 years ago)

rpmall.patch

  • SETUP.chroot.sh

    RCS file: /Volumes/src/cvs/od/proj/darwinports/base/src/portmgr/SETUP.chroot.sh,v
    retrieving revision 1.1
    diff -u -u -r1.1 SETUP.chroot.sh
     
    3131mkdir -p /darwinports/logs
    3232mkdir -p /darwinports/pkgs
    3333mkdir -p /darwinports/mpkgs
     34mkdir -p /darwinports/rpms
    3435
    3536cd $HOME/darwinports
    3637#tclsh base/src/portmgr/packageall.tcl
  • new file rpmall.tcl

    RCS file: rpmall.tcl
    diff -N rpmall.tcl
    - +  
     1#!/usr/bin/env tclsh
     2# packageall.tcl
     3#
     4# Copyright (c) 2003 Kevin Van Vechten <kevin@opendarwin.org>
     5# Copyright (c) 2002 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
     32package require darwinports
     33
     34# globals
     35set portdir .
     36
     37# UI Instantiations
     38# ui_options(ports_debug) - If set, output debugging messages.
     39# ui_options(ports_verbose) - If set, output info messages (ui_info)
     40# ui_options(ports_quiet) - If set, don't output "standard messages"
     41
     42# ui_options accessor
     43proc ui_isset {val} {
     44    global ui_options
     45    if {[info exists ui_options($val)]} {
     46        if {$ui_options($val) == "yes"} {
     47            return 1
     48        }
     49    }
     50    return 0
     51}
     52
     53set options(package.destpath) "/darwinports/rpms"
     54
     55# UI Callback
     56
     57proc ui_puts {messagelist} {
     58    global logfd
     59    set channel $logfd
     60    array set message $messagelist
     61    switch $message(priority) {
     62        debug {
     63            if [ui_isset ports_debug] {
     64                set str "DEBUG: $message(data)"
     65            } else {
     66                return
     67            }
     68        }
     69        info {
     70            # put verbose stuff only to the log file
     71            if ![ui_isset ports_verbose] {
     72                return
     73            } else {
     74                if {[string length $channel] > 0} {
     75                    log_message $channel $message(data)
     76                }
     77                return
     78            }
     79        }
     80        msg {
     81            if [ui_isset ports_quiet] {
     82                return
     83            }
     84            set str $message(data)
     85        }
     86        error {
     87            set str "Error: $message(data)"
     88        }
     89        warn {
     90            set str "Warning: $message(data)"
     91        }
     92    }
     93    if {[string length $channel] > 0 } {
     94        log_message $channel $str
     95    }
     96    puts stderr $str
     97}
     98
     99proc pkg_ui_log {message} {
     100    global logfd
     101    if {[string length $logfd] > 0 } {
     102        log_message $logfd $message
     103    }
     104}
     105
     106proc log_message {channel message} {
     107    seek $channel 0 end
     108    puts $channel $message
     109    flush $channel
     110}
     111
     112# Recursive bottom-up approach of building a list of dependencies.
     113proc get_dependencies {portname includeBuildDeps} {
     114        set result {}
     115       
     116        if {[catch {set search [dportsearch "^$portname\$"]} error]} {
     117                ui_error "Internal error: port search failed: $error"
     118                return {}
     119        }
     120        foreach {name array} $search {
     121                array set portinfo $array
     122                if {![info exists portinfo(name)] ||
     123                        ![info exists portinfo(version)] ||
     124                        ![info exists portinfo(categories)]} {
     125                        ui_error "Internal error: $name missing some portinfo keys"
     126                        continue
     127                }
     128                if {![info exists portinfo(revision)]} {
     129                        set portinfo(revision) 0
     130                }
     131               
     132                set portname $portinfo(name)
     133                set portversion $portinfo(version)
     134                set revision $portinfo(revision)
     135
     136                # Append the package itself to the result list
     137                lappend result [list $portname $portversion $revision]
     138
     139                # Append the package's dependents to the result list
     140                set depends {}
     141                if {[info exists portinfo(depends_run)]} { eval "lappend depends $portinfo(depends_run)" }
     142                if {[info exists portinfo(depends_lib)]} { eval "lappend depends $portinfo(depends_lib)" }
     143                if {$includeBuildDeps != "" && [info exists portinfo(depends_build)]} {
     144                        eval "lappend depends $portinfo(depends_build)"
     145                }
     146                foreach depspec $depends {
     147                        set dep [lindex [split $depspec :] 2]
     148                        set x [get_dependencies $dep $includeBuildDeps]
     149                        eval "lappend result $x"
     150                        set result [lsort -unique $result]
     151                }
     152        }
     153        return $result
     154}
     155
     156# Install binary packages if they've already been built.  This will
     157# speed up the testing, since we won't have to recompile dependencies
     158# which have already been compiled.
     159
     160proc install_binary_if_available {dep} {
     161        set portname [lindex $dep 0]
     162        set portversion [lindex $dep 1]
     163        set revision [lindex $dep 2]
     164
     165        foreach dir {"/opt/local/src/apple/RPMS" "/usr/src/apple/RPMS" "/darwinports/rpms/RPMS"} {
     166                foreach arch {"ppc" "i386" "fat"} {
     167                        set rpmpath "${dir}/${arch}/${portname}-${portversion}-${revision}.${arch}.rpm"
     168                        if {[file readable $rpmpath]} {
     169                                ui_msg "Installing binary: $rpmpath"
     170                                if {[catch {system "rpm -Uvh --force $rpmpath"} error ]} {
     171                                        ui_error "Internal error: $error"
     172                                } else {
     173                                        return true
     174                                }
     175                        }
     176                }
     177        }
     178        return false
     179}
     180
     181
     182# Standard procedures
     183
     184proc fatal args {
     185    global argv0
     186    puts stderr "$argv0: $args"
     187    exit
     188}
     189
     190# Main
     191array set options [list]
     192array set variations [list]
     193#       set ui_options(ports_verbose) yes
     194if ![file exists /usr/bin/sw_vers] {
     195        set variations(puredarwin) "+"
     196}
     197
     198if {[catch {dportinit} result]} {
     199    puts "Failed to initialize ports system, $result"
     200    exit 1
     201}
     202
     203package require Pextlib
     204
     205# If no arguments were given, default to all ports.
     206if {[llength $argv] == 0} {
     207        lappend argv ".*"
     208}
     209
     210foreach pname $argv {
     211
     212if {[catch {set allpackages [dportsearch "^${pname}\$"]} result]} {
     213        puts "port search failed: $result"
     214        exit 1
     215}
     216
     217set logpath "/darwinports/logs"
     218set logfd ""
     219
     220foreach {name array} $allpackages {
     221        array unset portinfo
     222        array set portinfo $array
     223
     224        #ui_msg "foo $portinfo(porturl)"
     225
     226        # Start with verbose output off;
     227        # this will prevent the repopulation of /opt from getting logged.
     228        set ui_options(ports_verbose) no
     229
     230        if ![info exists portinfo(porturl)] {
     231                puts stderr "Internal error: no porturl for $name"
     232                continue
     233        }
     234        if {![info exists portinfo(revision)]} {
     235                set portinfo(revision) 0
     236        }
     237
     238        set porturl $portinfo(porturl)
     239
     240        # this is used to short-circuit the RPM check and
     241        # move on to the next package
     242
     243        global exit_loop
     244        set exit_loop false
     245
     246        # Skip up-to-date packages
     247        if {[regsub {^file://} $portinfo(porturl) "" portpath]} {
     248                if {[info exists portinfo(name)] &&
     249                        [info exists portinfo(version)] &&
     250                        [info exists portinfo(revision)]} {
     251                        set portname $portinfo(name)
     252                        set portversion $portinfo(version)
     253                        set revision $portinfo(revision)
     254
     255                        foreach dir {"/opt/local/src/apple/RPMS" "/usr/src/apple/RPMS" "/darwinports/rpms/RPMS"} {
     256                                foreach arch {"ppc" "i386" "fat"} {
     257                                        set rpmpath "${dir}/${arch}/${portname}-${portversion}-${revision}.${arch}.rpm"
     258                                        #ui_msg "trying ${rpmpath}"
     259                                        if {[file readable $rpmpath] && ([file mtime ${rpmpath}] >= [file mtime ${portpath}/Portfile])} {
     260                                                puts stderr "->    skipping ${portname}-${portversion}; package is up to date."
     261                                                set exit_loop true
     262                                                break
     263                                        }
     264                                }
     265                                if {${exit_loop}} {
     266                                        break
     267                                }
     268                        }
     269                }
     270        }
     271        if {${exit_loop}} {
     272                continue
     273        }
     274       
     275        # Skip packages which previously failed
     276        set exit_loop false
     277               
     278        # Skip up-to-date packages
     279        if {[regsub {^file://} $portinfo(porturl) "" portpath]} {
     280                if {[info exists portinfo(name)] &&
     281                        [info exists portinfo(version)] &&
     282                        [info exists portinfo(revision)]} {
     283                        set portname $portinfo(name)
     284                        set portversion $portinfo(version)
     285                        set revision $portinfo(revision)
     286
     287                        set logfilepath "${logpath}/${portname}.log"
     288                        if {[file readable ${logfilepath}] && ([file mtime ${logfilepath}] > [file mtime ${portpath}/Portfile])} {
     289                                puts stderr "->    skipping ${portname}-${portversion}; package failed, but has not changed."
     290                                set exit_loop true
     291                        }
     292                }
     293        }
     294        if {${exit_loop}} {
     295                continue
     296        }
     297       
     298        # Building the port:
     299        # - remove /opt so it won't pollute the port.
     300        # - re-install DarwinPorts.
     301        # - keep distfiles outside /opt so we don't have to keep fetching them.
     302        # - send out an email to the maintainer if any errors occurred.
     303
     304        set remove_files ""
     305        foreach dir {"/opt/local/src/apple/RPMS" "/usr/src/apple/RPMS" "/darwinports/rpms/RPMS"} {
     306                foreach arch {"ppc" "i386" "fat"} {
     307                        set remove_files "${remove_files} '${dir}/${arch}/'*.rpm"
     308                }
     309        }
     310        system "rpm -q --queryformat='%{name} ' -p ${remove_files} | xargs rpm -e || true"
     311
     312        ui_msg "->    Removing /opt"
     313        #unset ui_options(ports_verbose)
     314        if {[catch {system "rm -Rf /opt"} error]} {
     315                puts stderr "Internal error: $error"
     316        }
     317        # this is bad on pure darwin  :)
     318        #if {[catch {system "rm -Rf /usr/X11R6"} error]} {
     319        #       puts stderr "Internal error: $error"
     320        #}
     321        #if {[catch {system "rm -Rf /etc/X11"} error]} {
     322        #       puts stderr "Internal error: $error"
     323        #}
     324        #if {[catch {system "rm -Rf /etc/fonts"} error]} {
     325        #       puts stderr "Internal error: $error"
     326        #}
     327        ui_msg "->    Installing darwinports"
     328        if {[catch {system "cd $env(HOME)/darwinports && make && make install"} error]} {
     329                puts stderr "Internal error: $error"
     330        }
     331        if {[catch {system "rmdir /opt/local/var/db/dports/distfiles"} error]} {
     332                puts stderr "Internal error: $error"
     333        }
     334        if {[catch {system "ln -s /darwinports/distfiles /opt/local/var/db/dports/distfiles"} error]} {
     335                puts stderr "Internal error: $error"
     336        }
     337        #set ui_options(ports_verbose) yes
     338
     339        # If there was a log file left over from the previous pass,
     340        # then the port failed with an error.  Send the log in an
     341        # email to the maintainers.
     342        if {[string length $logfd] > 0} {
     343                close $logfd
     344                set logfd ""
     345        }
     346        #if {[file readable $logfilename]} {
     347        #       if {[catch {system "cat $logfilename | /usr/sbin/sendmail -t"} error]} {
     348        #               puts stderr "Internal error: $error"
     349        #       }
     350        #}
     351
     352        # Open the log file for writing
     353        set logfd [open ${logpath}/${name}.log w]
     354
     355        set valid 1
     356
     357        set lint_errors {}
     358        set portname ""
     359        set portversion ""
     360        set description ""
     361        set category ""
     362
     363        if ![info exists portinfo(name)] {
     364                lappend lint_errors "missing name key"
     365                set valid 0
     366        } else {
     367                set portname $portinfo(name)
     368        }
     369       
     370        if ![info exists portinfo(description)] {
     371                lappend lint_errors "missing description key"
     372                set valid 0
     373        } else {
     374                set description $portinfo(description)
     375        }
     376       
     377        if ![info exists portinfo(version)] {
     378                lappend lint_errors "missing version key"
     379                set valid 0
     380        } else {
     381                set portversion $portinfo(version)
     382        }
     383       
     384        if ![info exists portinfo(categories)] {
     385                lappend lint_errors "missing categories key"
     386                set valid 0
     387        } else {
     388                set category [lindex $portinfo(categories) 0]
     389        }
     390       
     391        if ![info exists portinfo(maintainers)] {
     392                append lint_errors "missing maintainers key"
     393                set valid 0
     394                set maintainers kevin@opendarwin.org
     395        } else {
     396                set maintainers $portinfo(maintainers)
     397        }
     398       
     399        pkg_ui_log "To: [join $maintainers {, }]"
     400        pkg_ui_log "From: donotreply@opendarwin.org"
     401        pkg_ui_log "Subject: DarwinPorts $portinfo(name)-$portinfo(version) build failure"
     402        pkg_ui_log ""
     403        pkg_ui_log "The following is a transcript produced by the DarwinPorts automated build       "
     404        pkg_ui_log "system.  You are receiving this email because you are listed as a maintainer    "
     405        pkg_ui_log "of this port, which has failed the automated packaging process.  Please update  "
     406        pkg_ui_log "the port as soon as possible."
     407        pkg_ui_log ""
     408        pkg_ui_log ""
     409        pkg_ui_log "Thank you,"
     410        pkg_ui_log "The DarwinPorts Team"
     411        pkg_ui_log ""
     412        pkg_ui_log "================================================================================"
     413        pkg_ui_log ""
     414
     415        if {!$valid} {
     416                foreach error $lint_errors {
     417                        ui_error $error
     418                }
     419        }
     420
     421        ui_msg "-->   Packaging ${category}/${portname}-${portversion}"
     422
     423        foreach prebuild {"ccache" "rpm"} {
     424                if {![file exists /bin/${prebuild}]} {
     425                        ui_msg "--->  Pre-installing ${prebuild}"
     426                        if {[catch {set search [dportsearch "^${prebuild}\$"]} error]} {
     427                                ui_error "Internal error: port search ${prebuild} failed: $error"
     428                        }
     429                        array set prebuildinfo [lindex $search 1]
     430                        set ui_options(ports_verbose) yes
     431                        if {[catch {set workername [dportopen $prebuildinfo(porturl) [array get options] [array get variations]]} result] ||
     432                                $result == 1} {
     433                                ui_error "Internal error: unable to install ${prebuild}... exiting"
     434                                exit 1
     435                        }
     436                        if {[catch {set result [dportexec $workername install]} result] ||
     437                                $result == 1} {
     438                                ui_error "installation of ${prebuild} failed: $result"
     439                                dportclose $workername
     440                                exit 1
     441                        }
     442                }
     443        }
     444
     445        # Turn on verbose output for the build
     446        set ui_options(ports_verbose) yes
     447        if {[catch {set workername [dportopen $porturl [array get options] [array get variations]]} result] ||
     448                $result == 1} {
     449            ui_error "Internal error: unable to open port: $result"
     450            continue
     451        }
     452        if {[catch {set result [dportexec $workername rpmpackage]} result] ||
     453                $result == 1} {
     454            ui_error "port package failed: $result"
     455                dportclose $workername
     456            continue
     457        }
     458        set ui_options(ports_verbose) no
     459        # Turn verbose output off after the build
     460
     461        dportclose $workername
     462
     463        # We made it to the end.  We can delete the log file.
     464        close $logfd
     465        set logfd ""
     466        file delete ${logpath}/${name}.log
     467}
     468
     469}
     470# end foreach pname