Ticket #620: rpmall.patch

File rpmall.patch, 13.6 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 res [dportsearch "^$portname\$"]} error]} {
     117                ui_error "Internal error: port search failed: $error"
     118                return {}
     119        }
     120        foreach {name array} $res {
     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 res [dportsearch "^${pname}\$"]} result]} {
     213        puts "port search failed: $result"
     214        exit 1
     215}
     216
     217set logpath "/darwinports/logs"
     218set logfd ""
     219
     220foreach {name array} $res {
     221        array unset portinfo
     222        array set portinfo $array
     223
     224        # Start with verbose output off;
     225        # this will prevent the repopulation of /opt from getting logged.
     226        set ui_options(ports_verbose) no
     227
     228        if ![info exists portinfo(porturl)] {
     229                puts stderr "Internal error: no porturl for $name"
     230                continue
     231        }
     232       
     233        set porturl $portinfo(porturl)
     234
     235        # this is used to short-circuit the RPM check and
     236        # move on to the next package
     237
     238        global exit_loop
     239        set exit_loop false
     240
     241        # Skip up-to-date packages
     242        if {[regsub {^file://} $portinfo(porturl) "" portpath]} {
     243                if {[info exists portinfo(name)] &&
     244                        [info exists portinfo(version)] &&
     245                        [info exists portinfo(revision)]} {
     246                        set portname $portinfo(name)
     247                        set portversion $portinfo(version)
     248                        set revision $portinfo(revision)
     249
     250                        foreach dir {"/opt/local/src/apple/RPMS" "/usr/src/apple/RPMS" "/darwinports/rpms/RPMS"} {
     251                                foreach arch {"ppc" "i386" "fat"} {
     252                                        set rpmpath "${dir}/${arch}/${portname}-${portversion}-${revision}.${arch}.rpm"
     253                                        if {[file readable $rpmpath] && ([file mtime ${rpmpath}] > [file mtime ${portpath}/Portfile])} {
     254                                                puts stderr "->    skipping ${portname}-${portversion}; package is up to date."
     255                                                set exit_loop true
     256                                                break
     257                                        }
     258                                }
     259                                if {${exit_loop}} {
     260                                        break
     261                                }
     262                        }
     263                }
     264        }
     265        if {${exit_loop}} {
     266                continue
     267        }
     268       
     269        # Skip packages which previously failed
     270               
     271        # Building the port:
     272        # - remove /opt so it won't pollute the port.
     273        # - re-install DarwinPorts.
     274        # - keep distfiles outside /opt so we don't have to keep fetching them.
     275        # - send out an email to the maintainer if any errors occurred.
     276
     277        set remove_files ""
     278        foreach dir {"/opt/local/src/apple/RPMS" "/usr/src/apple/RPMS" "/darwinports/rpms/RPMS"} {
     279                foreach arch {"ppc" "i386" "fat"} {
     280                        set remove_files "${remove_files} '${dir}/${arch}/'*.rpm"
     281                }
     282        }
     283        system "rpm -q --queryformat='%{name} ' -p ${remove_files} | xargs rpm -e || true"
     284
     285        ui_msg "->    Removing /opt"
     286        #unset ui_options(ports_verbose)
     287        if {[catch {system "rm -Rf /opt"} error]} {
     288                puts stderr "Internal error: $error"
     289        }
     290        # this is bad on pure darwin  :)
     291        #if {[catch {system "rm -Rf /usr/X11R6"} error]} {
     292        #       puts stderr "Internal error: $error"
     293        #}
     294        #if {[catch {system "rm -Rf /etc/X11"} error]} {
     295        #       puts stderr "Internal error: $error"
     296        #}
     297        #if {[catch {system "rm -Rf /etc/fonts"} error]} {
     298        #       puts stderr "Internal error: $error"
     299        #}
     300        ui_msg "->    Installing darwinports"
     301        if {[catch {system "cd $env(HOME)/darwinports && make && make install"} error]} {
     302                puts stderr "Internal error: $error"
     303        }
     304        if {[catch {system "rmdir /opt/local/var/db/dports/distfiles"} error]} {
     305                puts stderr "Internal error: $error"
     306        }
     307        if {[catch {system "ln -s /darwinports/distfiles /opt/local/var/db/dports/distfiles"} error]} {
     308                puts stderr "Internal error: $error"
     309        }
     310        #set ui_options(ports_verbose) yes
     311
     312        # If there was a log file left over from the previous pass,
     313        # then the port failed with an error.  Send the log in an
     314        # email to the maintainers.
     315        if {[string length $logfd] > 0} {
     316                close $logfd
     317                set logfd ""
     318        }
     319        #if {[file readable $logfilename]} {
     320        #       if {[catch {system "cat $logfilename | /usr/sbin/sendmail -t"} error]} {
     321        #               puts stderr "Internal error: $error"
     322        #       }
     323        #}
     324
     325        # Open the log file for writing
     326        set logfd [open ${logpath}/${name}.log w]
     327
     328        set valid 1
     329
     330        set lint_errors {}
     331        set portname ""
     332        set portversion ""
     333        set description ""
     334        set category ""
     335
     336        if ![info exists portinfo(name)] {
     337                lappend lint_errors "missing name key"
     338                set valid 0
     339        } else {
     340                set portname $portinfo(name)
     341        }
     342       
     343        if ![info exists portinfo(description)] {
     344                lappend lint_errors "missing description key"
     345                set valid 0
     346        } else {
     347                set description $portinfo(description)
     348        }
     349       
     350        if ![info exists portinfo(version)] {
     351                lappend lint_errors "missing version key"
     352                set valid 0
     353        } else {
     354                set portversion $portinfo(version)
     355        }
     356       
     357        if ![info exists portinfo(categories)] {
     358                lappend lint_errors "missing categories key"
     359                set valid 0
     360        } else {
     361                set category [lindex $portinfo(categories) 0]
     362        }
     363       
     364        if ![info exists portinfo(maintainers)] {
     365                append lint_errors "missing maintainers key"
     366                set valid 0
     367                set maintainers kevin@opendarwin.org
     368        } else {
     369                set maintainers $portinfo(maintainers)
     370        }
     371       
     372        pkg_ui_log "To: [join $maintainers {, }]"
     373        pkg_ui_log "From: donotreply@opendarwin.org"
     374        pkg_ui_log "Subject: DarwinPorts $portinfo(name)-$portinfo(version) build failure"
     375        pkg_ui_log ""
     376        pkg_ui_log "The following is a transcript produced by the DarwinPorts automated build       "
     377        pkg_ui_log "system.  You are receiving this email because you are listed as a maintainer    "
     378        pkg_ui_log "of this port, which has failed the automated packaging process.  Please update  "
     379        pkg_ui_log "the port as soon as possible."
     380        pkg_ui_log ""
     381        pkg_ui_log ""
     382        pkg_ui_log "Thank you,"
     383        pkg_ui_log "The DarwinPorts Team"
     384        pkg_ui_log ""
     385        pkg_ui_log "================================================================================"
     386        pkg_ui_log ""
     387
     388        if {!$valid} {
     389                foreach error $lint_errors {
     390                        ui_error $error
     391                }
     392        }
     393
     394        ui_msg "-->   Packaging ${category}/${portname}-${portversion}"
     395
     396        foreach prebuild {"ccache" "rpm"} {
     397                if {![file exists /bin/${prebuild}]} {
     398                        ui_msg "--->  Pre-installing ${prebuild}"
     399                        if {[catch {set res [dportsearch "^${prebuild}\$"]} error]} {
     400                                ui_error "Internal error: port search ${prebuild} failed: $error"
     401                        }
     402                        array set prebuildinfo [lindex $res 1]
     403                        set ui_options(ports_verbose) yes
     404                        if {[catch {set workername [dportopen $prebuildinfo(porturl) [array get options] [array get variations]]} result] ||
     405                                $result == 1} {
     406                                ui_error "Internal error: unable to install ${prebuild}... exiting"
     407                                exit 1
     408                        }
     409                        if {[catch {set result [dportexec $workername install]} result] ||
     410                                $result == 1} {
     411                                ui_error "installation of ${prebuild} failed: $result"
     412                                dportclose $workername
     413                                exit 1
     414                        }
     415                }
     416        }
     417
     418        # Turn on verbose output for the build
     419        set ui_options(ports_verbose) yes
     420        if {[catch {set workername [dportopen $porturl [array get options] [array get variations]]} result] ||
     421                $result == 1} {
     422            ui_error "Internal error: unable to open port: $result"
     423            continue
     424        }
     425        if {[catch {set result [dportexec $workername rpmpackage]} result] ||
     426                $result == 1} {
     427            ui_error "port package failed: $result"
     428                dportclose $workername
     429            continue
     430        }
     431        set ui_options(ports_verbose) no
     432        # Turn verbose output off after the build
     433
     434        dportclose $workername
     435
     436        # We made it to the end.  We can delete the log file.
     437        close $logfd
     438        set logfd ""
     439        file delete ${logpath}/${name}.log
     440}
     441
     442}
     443# end foreach pname