Changeset 2084 for trunk/base


Ignore:
Timestamp:
Feb 26, 2003, 12:08:23 PM (21 years ago)
Author:
kevin
Message:

Re-use the Port API dependency engine for handling portfile dependencies.
Allow multiple Portfiles to be opened simultaneously.
Bug#: 333, 354

Location:
trunk/base/src/darwinports1.0
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/base/src/darwinports1.0/darwinports.tcl

    r2082 r2084  
    3030#
    3131package provide darwinports 1.0
     32package require darwinports_dlist 1.0
    3233
    3334namespace eval darwinports {
    34     namespace export bootstrap_options portinterp_options uniqid 0
     35    namespace export bootstrap_options portinterp_options open_dports
    3536    variable bootstrap_options "portdbpath libpath auto_path sources_conf prefix"
    3637    variable portinterp_options "portdbpath portpath auto_path prefix portsharepath"
    37     variable uniqid 0
     38       
     39        variable open_dports {}
    3840}
    3941
     
    6668
    6769proc dportinit {args} {
    68     global auto_path env darwinports::portdbpath darwinports::bootstrap_options darwinports::uniqid darwinports::portinterp_options darwinports::portconf darwinports::sources darwinports::sources_conf darwinports::portsharepath
     70    global auto_path env darwinports::portdbpath darwinports::bootstrap_options darwinports::portinterp_options darwinports::portconf darwinports::sources darwinports::sources_conf darwinports::portsharepath
    6971
    7072    if {[llength [array names env HOME]] > 0} {
     
    145147
    146148proc darwinports::worker_init {workername portpath options variations} {
    147     global darwinports::uniqid darwinports::portinterp_options auto_path
     149    global darwinports::portinterp_options auto_path
    148150
    149151    # Create package require abstraction procedure
     
    167169            $workername eval set system_options($opt) \"[set $opt]\"
    168170            $workername eval set $opt \"[set $opt]\"
    169         }
     171        } #"
    170172    }
    171173
     
    231233}
    232234
     235# dportopen
     236# Opens a DarwinPorts portfile specified by a URL.  The portfile is
     237# opened with the given list of options and variations.  The result
     238# of this function should be treated as an opaque handle to a
     239# DarwinPorts Portfile.
     240
    233241proc dportopen {porturl {options ""} {variations ""}} {
    234     global darwinports::uniqid darwinports::portinterp_options darwinports::portdbpath darwinports::portconf auto_path
    235     set portdir [darwinports::getportdir $porturl]
    236     cd $portdir
    237     set portpath [pwd]
    238     set workername workername[incr uniqid]
    239     interp create $workername
     242    global darwinports::portinterp_options darwinports::portdbpath darwinports::portconf darwinports::open_dports auto_path
     243
     244        # Look for an already-open DPort with the same URL.
     245        # XXX: should compare options and variations here too.
     246        # if found, return the existing reference and bump the refcount.
     247        set dport [dlist_search $darwinports::open_dports porturl $porturl]
     248        if {$dport != {}} {
     249                set refcnt [ditem_key $dport refcnt]
     250                incr refcnt
     251                ditem_key $dport refcnt $refcnt
     252                return $dport
     253        }
     254
     255        set portdir [darwinports::getportdir $porturl]
     256        cd $portdir
     257        set portpath [pwd]
     258        set workername [interp create]
     259
     260        set dport [ditem_create]
     261        lappend darwinports::open_dports $dport
     262        ditem_key $dport porturl $porturl
     263        ditem_key $dport portpath $portpath
     264        ditem_key $dport workername $workername
     265        ditem_key $dport options $options
     266        ditem_key $dport variations $variations
     267        ditem_key $dport refcnt 1
     268
    240269    darwinports::worker_init $workername $portpath $options $variations
    241270    if ![file isfile Portfile] {
    242271        return -code error "Could not find Portfile in $portdir"
    243272    }
     273
    244274    $workername eval source Portfile
    245 
    246     return $workername
    247 }
    248 
    249 proc dportexec {workername target} {
    250     global darwinports::portinterp_options darwinports::uniqid
    251 
     275       
     276        ditem_key $dport provides [$workername eval return \$portname]
     277
     278    return $dport
     279}
     280
     281proc _dporttest {dport} {
     282        # Check for the presense of the port in the registry
     283        set workername [ditem_key $dport workername]
     284        set res [$workername eval registry_exists \${portname} \${portversion}]
     285        if {$res != ""} {
     286                return 1
     287        } else {
     288                return 0
     289        }
     290}
     291
     292proc _dportexec {target dport} {
     293        set workername [ditem_key $dport workername]
     294        return [$workername eval eval_targets $target]
     295}
     296
     297# dportexec
     298# Execute the specified target of the given dport.
     299
     300proc dportexec {dport target} {
     301    global darwinports::portinterp_options
     302
     303        set workername [ditem_key $dport workername]
     304
     305        # XXX: move this into dportopen?
    252306        if {[$workername eval eval_variants variations $target] != 0} {
    253307                return 1
    254308        }
    255 
    256         return [$workername eval eval_targets $target]
     309       
     310        # Before we build the port, we must build its dependencies.
     311        # XXX: need a more general way of comparing against targets
     312        set dlist {}
     313        if {$target == "configure" || $target == "build" || $target == "install" ||
     314                $target == "package" || $target == "mpkg"} {
     315
     316                dportdepends $dport 1 1
     317               
     318                # Select out the dependents along the critical path
     319                set dlist [dlist_append_dependents $darwinports::open_dports $dport {}]
     320               
     321                # install them
     322                set dlist [dlist_eval $darwinports::open_dports _dporttest [list _dportexec "install"]]
     323        }
     324
     325        if {$dlist != {}} {
     326                ui_error "$target terminated due to an error while installing a dependency."
     327        } else {
     328                return [$workername eval eval_targets $target]
     329        }
     330        return 0
    257331}
    258332
     
    325399}
    326400
    327 proc dportinfo {workername} {
     401proc dportinfo {dport} {
     402        set workername [ditem_key $dport workername]
    328403    return [$workername eval array get PortInfo]
    329404}
    330405
    331 proc dportclose {workername} {
    332     interp delete $workername
     406proc dportclose {dport} {
     407        global darwinports::open_dports
     408        set refcnt [ditem_key $dport refcnt]
     409        incr refcnt -1
     410        ditem_key $dport refcnt $refcnt
     411        if {$refcnt == 0} {
     412                dlist_delete darwinports::open_dports $dport
     413                set workername [ditem_key $dport workername]
     414                interp delete $workername
     415        }
    333416}
    334417
     
    337420##### "
    338421
    339 # dportdepends returns a list of port names which the given port depends on.
    340 # xxx: should return the depspec itself once we have better depspec processing.
     422# dportdepends returns a list of dports which the given port depends on.
    341423# - optionally includes the build dependencies in the list.
    342424# - optionally recurses through the dependencies, looking for dependencies
    343425#       of dependencies.
    344426
    345 proc dportdepends {portname includeBuildDeps recurseDeps} {
    346         set result {}
    347 
    348         if {[catch {set res [dportsearch "^$portname\$"]} error]} {
    349                 ui_puts err "Internal error: port search failed: $error"
    350                 return
    351         }
    352 
    353         foreach {name array} $res {
    354                 array set portinfo $array
    355                 set depends {}
    356                 if {[info exists portinfo(depends_run)]} { eval "lappend depends $portinfo(depends_run)" }
    357                 if {[info exists portinfo(depends_lib)]} { eval "lappend depends $portinfo(depends_lib)" }
    358                 if {$includeBuildDeps != "" && [info exists portinfo(depends_build)]} {
    359                         eval "lappend depends $portinfo(depends_build)"
     427proc dportdepends {dport includeBuildDeps recurseDeps} {
     428        array set portinfo [dportinfo $dport]
     429        set depends {}
     430        if {[info exists portinfo(depends_run)]} { eval "lappend depends $portinfo(depends_run)" }
     431        if {[info exists portinfo(depends_lib)]} { eval "lappend depends $portinfo(depends_lib)" }
     432        if {$includeBuildDeps != "" && [info exists portinfo(depends_build)]} {
     433                eval "lappend depends $portinfo(depends_build)"
     434        }
     435
     436        foreach depspec $depends {
     437                # grab the portname portion of the depspec
     438                set portname [lindex [split $depspec :] 2]
     439               
     440                # Find the porturl
     441                if {[catch {set res [dportsearch "^$portname\$"]} error]} {
     442                        ui_puts err "Internal error: port search failed: $error"
     443                        return 1
    360444                }
    361                 foreach depspec $depends {
    362                         # grab the portname portion of the depspec
    363                         set dep [lindex [split $depspec :] 2]
    364                        
    365                         lappend result $dep
    366                        
    367                         if {$recurseDeps != ""} {
    368                                 set rdeps [dportdepends $dep $includeBuildDeps $recurseDeps]
    369                                 if {$rdeps == -1} {
    370                                         return -1
    371                                 } else {
    372                                         eval "lappend result $rdeps"
    373                                 }
     445                foreach {name array} $res {
     446                        array set portinfo $array
     447                        if {[info exists portinfo(porturl)]} {
     448                                set porturl $portinfo(porturl)
     449                                break
    374450                        }
    375451                }
     452
     453                set options [ditem_key $dport options]
     454                set variations [ditem_key $dport variations]
     455               
     456                set subport [dportopen $porturl $options $variations]
     457
     458                # Append the sub-port's provides to the port's requirements list.
     459                ditem_append $dport requires "[ditem_key $subport provides]"
     460
     461                if {$recurseDeps != ""} {
     462                        set res [dportdepends $subport $includeBuildDeps $recurseDeps]
     463                        if {$res != 0} {
     464                                return $res
     465                        }
     466                }
    376467        }
    377468       
    378         return $result
    379 }
     469        return 0
     470}
  • trunk/base/src/darwinports1.0/darwinports_dlist.tcl

    r2083 r2084  
    6969}
    7070
     71# dlist_delete
     72# Deletes the specified ditem from the dlist.
     73#       dlist - the list to search
     74#       ditem - the item to delete
     75proc dlist_delete {dlist ditem} {
     76    upvar $dlist uplist
     77    set ix [lsearch -exact $uplist $ditem]
     78    if {$ix >= 0} {
     79                set uplist [lreplace $uplist $ix $ix]
     80    }
     81}
     82
    7183# dlist_has_pending
    7284# Returns true if the dlist contains ditems
     
    225237# or {} if all ditems were evaluated.
    226238#       dlist    - the dependency list to evaluate
     239#       testcond - test condition to populate the status dictionary
     240#                  should return {-1, 0, 1}
    227241#       handler  - the handler to invoke on each ditem
     242#       canfail  - If 1, then progress will not stop when a failure
     243#                  occures; if 0, then dlist_eval will return on the
     244#                  first failure
    228245#       selector - the selector for determining eligibility
    229246
    230 proc dlist_eval {dlist handler {selector "dlist_get_next"}} {
     247proc dlist_eval {dlist testcond handler {canfail "0"} {selector "dlist_get_next"}} {
    231248        array set statusdict [list]
    232249       
    233250        # Do a pre-run seeing if any items automagically
    234251        # can evaluate to true.
    235         foreach ditem $dlist {
    236                 #if test ditem
    237                 if {0} {
    238                         foreach token [dlist_key $ditem provides] {
    239                                 set statusdict($name) 1
     252        if {$testcond != ""} {
     253                foreach ditem $dlist {
     254                        if {[eval "expr \[\$testcond \$ditem\] == 1"]} {
     255                                foreach token [ditem_key $ditem provides] {
     256                                        set statusdict($token) 1
     257                                }
     258                                dlist_delete dlist $ditem
    240259                        }
    241                         ldelete dlist $ditem
    242260                }
    243261        }
     
    252270                        # $handler should return a unix status code, 0 for success.
    253271                        # statusdict notation is 1 for success
    254                         if {[catch {$handler $ditem} result]} {
     272                        if {[catch {eval "$handler $ditem"} result]} {
    255273                                puts $result
    256274                                return $dlist
     
    263281                        }
    264282                       
     283                        # Abort if we're not allowed to fail
     284                        if {$canfail == 0 && $result != 0} {
     285                                return $dlist
     286                        }
     287                       
    265288                        # Delete the ditem from the waiting list.
    266                         darwinports_dlist::ldelete dlist $ditem
     289                        dlist_delete dlist $ditem
    267290                }
    268291        }
     
    331354}
    332355
    333 proc ldelete {list value} {
    334     upvar $list uplist
    335     set ix [lsearch -exact $uplist $value]
    336     if {$ix >= 0} {
    337         set uplist [lreplace $uplist $ix $ix]
    338     }
    339 }
    340 
    341356# End of darwinports_dlist namespace
    342357}
Note: See TracChangeset for help on using the changeset viewer.