Ignore:
Timestamp:
Jan 7, 2006, 11:10:22 PM (15 years ago)
Author:
jberry
Message:

Merge changes for port from jberry-preview-13

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/base/src/port/port.tcl

    r15691 r15731  
    33exec @TCLSH@ "$0" "$@"
    44# port.tcl
    5 # $Id: port.tcl,v 1.146 2006/01/05 06:40:56 olegb Exp $
     5# $Id: port.tcl,v 1.147 2006/01/07 23:10:22 jberry Exp $
    66#
     7# Copyright (c) 2002-2006 DarwinPorts organization
    78# Copyright (c) 2004 Robert Shaw <rshaw@opendarwin.org>
    89# Copyright (c) 2002 Apple Computer, Inc.
     
    3637#       TODO:
    3738#
     39#               - Rename global_options to cmd_options
     40#               - Rename global_options_base to global_options
     41#               - Document -i, -F, -p, and -x
     42#               - In interactive mode, we might need to blow some caches between commands
     43#                 (do we cache anything except PortIndex?)
     44#               - Add auto-completion of filenames?
     45#
    3846
    3947catch {source \
     
    4149package require darwinports
    4250
    43 # globals
    44 set portdir .
    45 set argn 0
    46 set action ""
    47 set portlist {}
    48 array set ui_options            {}
    49 array set global_options        {}
    50 array set global_variations     {}
    51 
    52 # Save off a copy of the environment before dportinit monkeys with it
    53 global env
    54 array set boot_env [array get env]
    55 
    56 global argv0
    57 set cmdname [file tail $argv0]
    5851
    5952# UI Instantiations
     
    137130
    138131# Standard procedures
    139 proc print_usage args {
     132proc print_usage {args} {
    140133        global cmdname
    141134        set usage { [-vdqfonRsbcktu] [-D portdir] action [actionflags]
     
    148141
    149142
    150 proc print_help args {
     143proc print_help {args} {
    151144        global cmdname
    152145       
     
    210203        } else {
    211204                fatal $s
     205        }
     206}
     207
     208
     209# Produce an error message, and break, unless
     210# we're handling errors in a soft fashion, in which
     211# case we continue
     212proc break_softcontinue { msg status name_status } {
     213        upvar $name_status status_var
     214        ui_error $msg
     215        if {[ui_isset ports_processall]} {
     216                set status_var 0
     217                return -code continue
     218        } else {
     219                set status_var $status
     220                return -code break
    212221        }
    213222}
     
    308317                set port(name) $portname
    309318                if {$portname == ""} {
    310                         fatal "A default port name could not be supplied."
     319                        ui_error "A default port name could not be supplied."
    311320                }
    312321        }
     
    338347
    339348
    340 proc url_to_portname { url } {
     349proc url_to_portname { url {quiet 0} } {
    341350        # Save directory and restore the directory, since dportopen changes it
    342351        set savedir [pwd]
    343352        set portname ""
    344353        if {[catch {set ctx [dportopen $url]} result]} {
    345                 puts stderr "Can't map the URL '$url' to a port description file (${result}). Please verify that the directory and portfile syntax are correct."
     354                if {!$quiet} {
     355                        puts stderr "Can't map the URL '$url' to a port description file (${result}). Please verify that the directory and portfile syntax are correct."
     356                }
    346357        } else {
    347358                array set portinfo [dportinfo $ctx]
     
    355366
    356367# Supply a default porturl/portname if the portlist is empty
    357 proc require_portlist {} {
    358         upvar portlist portlist
     368proc require_portlist { nameportlist } {
     369        upvar $nameportlist portlist
    359370       
    360371        if {[llength $portlist] == 0} {
     
    458469        set portname [url_to_portname $url]
    459470        if {$portname == ""} {
    460                 fatal "To use the current port, you must be in a port's directory"
     471                ui_error "To use the current port, you must be in a port's directory"
    461472        }
    462473       
     
    585596# Port expressions
    586597##########################################
    587 proc moreargs {} {
    588         global argn argc
    589         return [expr {$argn < $argc}]
    590 }
    591 
    592 proc lookahead {} {
    593         global argn argc argv
    594         if {$argn < $argc} {
    595                 return [lindex $argv $argn]
    596         } else {
    597                 return _EOF_
    598         }
    599 }
    600 
    601 
    602 proc advance {} {
    603         global argn
    604         incr argn
    605 }
    606 
    607 
    608 proc match s {
    609         if {[lookahead] == $s} {
    610                 advance
    611                 return 1
    612         }
    613         return 0
    614 }
    615 
    616 
    617598proc portExpr resname {
    618599        upvar $resname reslist
     
    631612        while {$result} {
    632613                switch -- [lookahead] {
     614                        ;               -
    633615                        )               -
    634616                        _EOF_   { break }
     
    729711        set el 0
    730712       
     713        set url ""
    731714        set name ""
    732715        set version ""
     
    737720        switch -regex -- $token {
    738721                ^\\)$                   -
    739                 ^_EOF_$                 {       # End of file/expression
     722                ^\;                             -
     723                ^_EOF_$                 {       # End of expression/cmd/file
    740724                                                }
    741                
     725                                               
    742726                ^\\($                   {       # Parenthesized Expression
    743727                                                        advance
     
    809793                                                                parsePortSpec version variants options
    810794                                                                add_to_portlist reslist [list url $token \
    811                                                                                                                         name $name\
     795                                                                                                                        name $name \
    812796                                                                                                                        version $version \
    813797                                                                                                                        variants [array get variants] \
    814798                                                                                                                        options [array get options]]
    815799                                                        } else {
    816                                                                 fatal "Can't open URL '$token' as a port"
     800                                                                ui_error "Can't open URL '$token' as a port"
     801                                                                set el 0
    817802                                                        }
    818803                                                        set el 1
    819804                                                }
    820                
     805                                               
    821806                default                 {       # Treat anything else as a portspec (portname, version, variants, options
    822807                                                        # or some combination thereof).
    823                                                         parseFullPortSpec name version variants options
    824                                                         add_to_portlist reslist [list name $name \
    825                                                                                                                 version $version \
    826                                                                                                                 variants [array get variants] \
    827                                                                                                                 options [array get options]]
     808                                                        parseFullPortSpec url name version variants options
     809                                                        add_to_portlist reslist [list   url $url \
     810                                                                                                                        name $name \
     811                                                                                                                        version $version \
     812                                                                                                                        variants [array get variants] \
     813                                                                                                                        options [array get options]]
    828814                                                        set el 1
    829815                                                }
     
    976962
    977963
    978 proc parseFullPortSpec { namename vername varname optname } {
     964proc parseFullPortSpec { urlname namename vername varname optname } {
     965        upvar $urlname porturl
    979966        upvar $namename portname
    980967        upvar $vername portversion
     
    997984                set remainder ""
    998985                if {![regexp {^(@|[-+]|[[:alpha:]_]+[\w\.]*=)} $token match]} {
    999                         advance                 
     986                        advance
    1000987                        regexp {^([^@]+)(@.*)?} $token match portname remainder
     988                       
     989                        # If the portname contains a /, then try to use it as a URL
     990                        if {[string match "*/*" $portname]} {
     991                                set url "file://$portname"
     992                                set name [url_to_portname $url 1]
     993                                if { $name != "" } {
     994                                        # We mapped the url to valid port
     995                                        set porturl $url
     996                                        set portname $name
     997                                        # Continue to parse rest of portspec....
     998                                } else {
     999                                        # We didn't map the url to a port; treat it
     1000                                        # as a raw string for something like port contents
     1001                                        # or cd
     1002                                        set porturl ""
     1003                                        # Since this isn't a port, we don't try to parse
     1004                                        # any remaining portspec....
     1005                                        return
     1006                                }
     1007                        }
    10011008                }
    10021009               
     
    10661073                        if {[regexp {^([[:alpha:]_]+[\w\.]*)=(.*)} $opt match key val] == 1} {
    10671074                                # It's a variable setting
    1068                                 set portoptions($key) \"$val\"
     1075                                set portoptions($key) "\"$val\""
    10691076                                set opt ""
    10701077                                set consumed 1
     
    10841091
    10851092
     1093##########################################
     1094# Action Handlers
     1095##########################################
     1096
     1097proc action_usage { action portlist opts } {
     1098        print_usage
     1099        return 0
     1100}
     1101
     1102
     1103proc action_help { action portlist opts } {
     1104        print_help
     1105        return 0
     1106}
     1107
     1108
     1109proc action_info { action portlist opts } {
     1110        set status 0
     1111        require_portlist portlist
     1112        foreachport $portlist {
     1113                # Get information about the named port
     1114                if {[catch {dportsearch $portname no exact} result]} {
     1115                        global errorInfo
     1116                        ui_debug "$errorInfo"
     1117                        break_softcontinue "search for portname $portname failed: $result" 1 status
     1118                }
     1119       
     1120                if {$result == ""} {
     1121                        puts "No port $portname found."
     1122                } else {
     1123                        set found [expr [llength $result] / 2]
     1124                        if {$found > 1} {
     1125                                ui_warn "Found $found port $portname definitions, displaying first one."
     1126                        }
     1127                        array set portinfo [lindex $result 1]
     1128
     1129                        puts -nonewline "$portinfo(name) $portinfo(version)"
     1130                        if {[info exists portinfo(revision)] && $portinfo(revision) > 0} {
     1131                                puts -nonewline ", Revision $portinfo(revision)"
     1132                        }
     1133                        puts -nonewline ", $portinfo(portdir)"
     1134                        if {[info exists portinfo(variants)]} {
     1135                                puts -nonewline " (Variants: "
     1136                                for {set i 0} {$i < [llength $portinfo(variants)]} {incr i} {
     1137                                        if {$i > 0} { puts -nonewline ", " }
     1138                                        puts -nonewline "[lindex $portinfo(variants) $i]"
     1139                                }
     1140                                puts -nonewline ")"
     1141                        }
     1142                        puts ""
     1143                        if {[info exists portinfo(homepage)]} {
     1144                                puts "$portinfo(homepage)"
     1145                        }
     1146       
     1147                        if {[info exists portinfo(long_description)]} {
     1148                                puts "\n$portinfo(long_description)\n"
     1149                        }
     1150
     1151                        # find build dependencies
     1152                        if {[info exists portinfo(depends_build)]} {
     1153                                puts -nonewline "Build Dependencies: "
     1154                                for {set i 0} {$i < [llength $portinfo(depends_build)]} {incr i} {
     1155                                        if {$i > 0} { puts -nonewline ", " }
     1156                                        puts -nonewline "[lindex [split [lindex $portinfo(depends_build) $i] :] end]"
     1157                                }
     1158                                set nodeps false
     1159                                puts ""
     1160                        }
     1161       
     1162                        # find library dependencies
     1163                        if {[info exists portinfo(depends_lib)]} {
     1164                                puts -nonewline "Library Dependencies: "
     1165                                for {set i 0} {$i < [llength $portinfo(depends_lib)]} {incr i} {
     1166                                        if {$i > 0} { puts -nonewline ", " }
     1167                                        puts -nonewline "[lindex [split [lindex $portinfo(depends_lib) $i] :] end]"
     1168                                }
     1169                                set nodeps false
     1170                                puts ""
     1171                        }
     1172       
     1173                        # find runtime dependencies
     1174                        if {[info exists portinfo(depends_run)]} {
     1175                                puts -nonewline "Runtime Dependencies: "
     1176                                for {set i 0} {$i < [llength $portinfo(depends_run)]} {incr i} {
     1177                                        if {$i > 0} { puts -nonewline ", " }
     1178                                        puts -nonewline "[lindex [split [lindex $portinfo(depends_run) $i] :] end]"
     1179                                }
     1180                                set nodeps false
     1181                                puts ""
     1182                        }
     1183                        if {[info exists portinfo(platforms)]} { puts "Platforms: $portinfo(platforms)"}
     1184                        if {[info exists portinfo(maintainers)]} { puts "Maintainers: $portinfo(maintainers)"}
     1185                }
     1186        }
     1187       
     1188        return $status
     1189}
     1190
     1191
     1192proc action_location { action portlist opts } {
     1193        set status 0
     1194        require_portlist portlist
     1195        foreachport $portlist {
     1196                if { [catch {set ilist [registry_installed $portname [composite_version $portversion [array get variations]]]} result] } {
     1197                        global errorInfo
     1198                        ui_debug "$errorInfo"
     1199                        break_softcontinue "port location failed: $result" 1 status
     1200                } else {
     1201                        set version [lindex $ilist 1]
     1202                        set revision [lindex $ilist 2]
     1203                        set     variants [lindex $ilist 3]
     1204                }
     1205
     1206                set ref [registry::open_entry $portname $version $revision $variants]
     1207                if { [string equal [registry::property_retrieve $ref installtype] "image"] } {
     1208                        set imagedir [registry::property_retrieve $ref imagedir]
     1209                        puts "Port $portname ${version}_${revision}${variants} is installed as an image in:"
     1210                        puts $imagedir
     1211                } else {
     1212                        break_softcontinue "Port $portname is not installed as an image." 1 status
     1213                }
     1214        }
     1215       
     1216        return $status
     1217}
     1218
     1219
     1220proc action_provides { action portlist opts } {
     1221        # In this case, portname is going to be used for the filename... since
     1222        # that is the first argument we expect... perhaps there is a better way
     1223        # to do this?
     1224        if { ![llength $portlist] } {
     1225                ui_error "Please specify a filename to check which port provides that file."
     1226                return 1
     1227        }
     1228        foreachport $portlist {
     1229                set file [compat filenormalize $portname]
     1230                if {[file exists $file]} {
     1231                        if {![file isdirectory $file]} {
     1232                                set port [registry::file_registered $file]
     1233                                if { $port != 0 } {
     1234                                        puts "$file is provided by: $port"
     1235                                } else {
     1236                                        puts "$file is not provided by a DarwinPorts port."
     1237                                }
     1238                        } else {
     1239                                puts "$file is a directory."
     1240                        }
     1241                } else {
     1242                        puts "$file does not exist."
     1243                }
     1244        }
     1245       
     1246        return 0
     1247}
     1248
     1249
     1250proc action_activate { action portlist opts } {
     1251        set status 0
     1252        require_portlist portlist
     1253        foreachport $portlist {
     1254                if { [catch {portimage::activate $portname [composite_version $portversion [array get variations]] [array get options]} result] } {
     1255                        global errorInfo
     1256                        ui_debug "$errorInfo"
     1257                        break_softcontinue "port activate failed: $result" 1 status
     1258                }
     1259        }
     1260       
     1261        return $status
     1262}
     1263
     1264
     1265proc action_deactivate { action portlist opts } {
     1266        set status 0
     1267        require_portlist portlist
     1268        foreachport $portlist {
     1269                if { [catch {portimage::deactivate $portname [composite_version $portversion [array get variations]] [array get options]} result] } {
     1270                        global errorInfo
     1271                        ui_debug "$errorInfo"
     1272                        break_softcontinue "port deactivate failed: $result" 1 status
     1273                }
     1274        }
     1275       
     1276        return $status
     1277}
     1278
     1279
     1280proc action_selfupdate { action portlist opts } {
     1281        if { [catch {darwinports::selfupdate [array get global_options]} result ] } {
     1282                global errorInfo
     1283                ui_debug "$errorInfo"
     1284                fatal "selfupdate failed: $result"
     1285        }
     1286       
     1287        return 0
     1288}
     1289
     1290
     1291proc action_upgrade { action portlist opts } {
     1292        require_portlist portlist
     1293        foreachport $portlist {
     1294                # Merge global variations into the variations specified for this port
     1295                foreach { variation value } [array get global_variations] {
     1296                        if { ![info exists variations($variation)] } {
     1297                                set variations($variation) $value
     1298                        }
     1299                }
     1300               
     1301                darwinports::upgrade $portname "port:$portname" [array get variations] [array get options]
     1302        }
     1303       
     1304        return 0
     1305}
     1306
     1307
     1308proc action_version { action portlist opts } {
     1309        puts "Version: [darwinports::version]"
     1310        return 0
     1311}
     1312
     1313
     1314proc action_compact { action portlist opts } {
     1315        set status 0
     1316        require_portlist portlist
     1317        foreachport $portlist {
     1318                if { [catch {portimage::compact $portname [composite_version $portversion [array get variations]]} result] } {
     1319                        global errorInfo
     1320                        ui_debug "$errorInfo"
     1321                        break_softcontinue "port compact failed: $result" 1 status
     1322                }
     1323        }
     1324
     1325        return $status
     1326}
     1327
     1328
     1329proc action_uncompact { action portlist opts } {
     1330        set status 0
     1331        require_portlist portlist
     1332        foreachport $portlist {
     1333                if { [catch {portimage::uncompact $portname [composite_version $portversion [array get variations]]} result] } {
     1334                        global errorInfo
     1335                        ui_debug "$errorInfo"
     1336                        break_softcontinue "port uncompact failed: $result" 1 status
     1337                }
     1338        }
     1339       
     1340        return $status
     1341}
     1342
     1343
     1344
     1345proc action_dependents { action portlist opts } {
     1346        require_portlist portlist
     1347        foreachport $portlist {
     1348                registry::open_dep_map
     1349                set deplist [registry::list_dependents $portname]
     1350
     1351                if { [llength $deplist] > 0 } {
     1352                        set dl [list]
     1353                        # Check the deps first
     1354                        foreach dep $deplist {
     1355                                set depport [lindex $dep 2]
     1356                                ui_msg "$depport depends on $portname"
     1357                                # xxx: Should look at making registry::installed return 0 or
     1358                                # something instead  of erroring.
     1359                                if { ![catch {set installed [registry::installed $depport]} res] } {
     1360                                        if { [llength [registry::installed $depport]] > 0 } {
     1361                                                lappend dl $depport
     1362                                        }
     1363                                }
     1364                        }
     1365                } else {
     1366                        ui_msg "$portname has no dependents!"
     1367                }
     1368        }
     1369}
     1370
     1371
     1372proc action_uninstall { action portlist opts } {
     1373        set status 0
     1374        if {[info exists global_options(port_uninstall_old)]} {
     1375                # if -u then uninstall all inactive ports
     1376                # (union these to any other ports user has in the port list)
     1377                set portlist [opUnion $portlist [get_inactive_ports]]
     1378        } else {
     1379                # Otherwise the user had better have supplied a portlist, or we'll default to the existing directory
     1380                require_portlist portlist
     1381        }
     1382
     1383        foreachport $portlist {
     1384                if { [catch {portuninstall::uninstall $portname [composite_version $portversion [array get variations]] [array get options]} result] } {
     1385                        global errorInfo
     1386                        ui_debug "$errorInfo"
     1387                        break_softcontinue "port uninstall failed: $result" 1 status
     1388                }
     1389        }
     1390       
     1391        return 0
     1392}
     1393
     1394
     1395proc action_installed { action portlist opts } {
     1396        set status 0
     1397        if { [llength $portlist] } {
     1398                set ilist {}
     1399                foreachport $portlist {
     1400                        set composite_version [composite_version $portversion [array get variations]]
     1401                        if { [catch {set ilist [concat $ilist [registry::installed $portname $composite_version]]} result] } {
     1402                                if {[string match "* not registered as installed." $result]} {
     1403                                        puts "Port $portname is not installed."
     1404                                } else {
     1405                                        global errorInfo
     1406                                        ui_debug "$errorInfo"
     1407                                        break_softcontinue "port installed failed: $result" 1 status
     1408                                }
     1409                        }
     1410                }
     1411        } else {
     1412                if { [catch {set ilist [registry::installed]} result] } {
     1413                        if {$result == "Registry error: No ports registered as installed."} {
     1414                                set ilist {}
     1415                                puts "No ports are installed!"
     1416                        } else {
     1417                                global errorInfo
     1418                                ui_debug "$errorInfo"
     1419                                ui_error "port installed failed: $result"
     1420                                set status 1
     1421                        }
     1422                }
     1423        }
     1424        if { [llength $ilist] > 0 } {
     1425                puts "The following ports are currently installed:"
     1426                foreach i $ilist {
     1427                        set iname [lindex $i 0]
     1428                        set iversion [lindex $i 1]
     1429                        set irevision [lindex $i 2]
     1430                        set ivariants [lindex $i 3]
     1431                        set iactive [lindex $i 4]
     1432                        if { $iactive == 0 } {
     1433                                puts "  $iname @${iversion}_${irevision}${ivariants}"
     1434                        } elseif { $iactive == 1 } {
     1435                                puts "  $iname @${iversion}_${irevision}${ivariants} (active)"
     1436                        }
     1437                }
     1438        } else {
     1439                puts "No ports are installed."
     1440        }
     1441       
     1442        return $status
     1443}
     1444
     1445
     1446proc action_outdated { action portlist opts } {
     1447        set status 0
     1448        # If port names were supplied, limit ourselves to those port, else check all installed ports
     1449        if { [llength $portlist] } {
     1450                set ilist {}
     1451                foreach portspec $portlist {
     1452                        array set port $portspec
     1453                        set portname $port(name)
     1454                        set composite_version [composite_version $port(version) $port(variants)]
     1455                        if { [catch {set ilist [concat $ilist [registry::installed $portname $composite_version]]} result] } {
     1456                                if {![string match "* not registered as installed." $result]} {
     1457                                        global errorInfo
     1458                                        ui_debug "$errorInfo"
     1459                                        break_softcontinue "port outdated failed: $result" 1 status
     1460                                }
     1461                        }
     1462                }
     1463        } else {
     1464                if { [catch {set ilist [registry::installed]} result] } {
     1465                        global errorInfo
     1466                        ui_debug "$errorInfo"
     1467                        ui_error "port outdated failed: $result"
     1468                        set status 1
     1469                }
     1470        }
     1471
     1472        if { [llength $ilist] > 0 } {
     1473                puts "The following installed ports are outdated:"
     1474       
     1475                foreach i $ilist {
     1476
     1477                        # Get information about the installed port
     1478                        set portname                    [lindex $i 0]
     1479                        set installed_version   [lindex $i 1]
     1480                        set installed_revision  [lindex $i 2]
     1481                        set installed_compound  "${installed_version}_${installed_revision}"
     1482
     1483                        set is_active                   [lindex $i 4]
     1484                        if { $is_active == 0 } {
     1485                                continue
     1486                        }
     1487                        set installed_epoch             [lindex $i 5]
     1488
     1489                        # Get info about the port from the index
     1490                        if {[catch {set res [dportsearch $portname no exact]} result]} {
     1491                                global errorInfo
     1492                                ui_debug "$errorInfo"
     1493                                break_softcontinue "search for portname $portname failed: $result" 1 status
     1494                        }
     1495                        if {[llength $res] < 2} {
     1496                                if {[ui_isset ports_debug]} {
     1497                                        puts "$portname ($installed_compound is installed; the port was not found in the port index)"
     1498                                }
     1499                                continue
     1500                        }
     1501                        array set portinfo [lindex $res 1]
     1502                       
     1503                        # Get information about latest available version and revision
     1504                        set latest_version $portinfo(version)
     1505                        set latest_revision             0
     1506                        if {[info exists portinfo(revision)] && $portinfo(revision) > 0} {
     1507                                set latest_revision     $portinfo(revision)
     1508                        }
     1509                        set latest_compound             "${latest_version}_${latest_revision}"
     1510                        set latest_epoch                0
     1511                        if {[info exists portinfo(epoch)]} {
     1512                                set latest_epoch        $portinfo(epoch)
     1513                        }
     1514                       
     1515                        # Compare versions, first checking epoch, then the compound version string
     1516                        set comp_result [expr $installed_epoch - $latest_epoch]
     1517                        if { $comp_result == 0 } {
     1518                                set comp_result [rpm-vercomp $installed_compound $latest_compound]
     1519                        }
     1520                       
     1521                        # Report outdated (or, for verbose, predated) versions
     1522                        if { $comp_result != 0 } {
     1523                                                       
     1524                                # Form a relation between the versions
     1525                                set flag ""
     1526                                if { $comp_result > 0 } {
     1527                                        set relation ">"
     1528                                        set flag "!"
     1529                                } else {
     1530                                        set relation "<"
     1531                                }
     1532                               
     1533                                # Emit information
     1534                                if {$comp_result < 0 || [ui_isset ports_verbose]} {
     1535                                        puts [format "%-30s %-24s %1s" $portname "$installed_compound $relation $latest_compound" $flag]
     1536                                }
     1537                               
     1538                        }
     1539                }
     1540        } else {
     1541                puts "No installed ports are outdated."
     1542        }
     1543       
     1544        return $status
     1545}
     1546
     1547
     1548proc action_contents { action portlist opts } {
     1549        set status 0
     1550        require_portlist portlist
     1551        foreachport $portlist {
     1552                set files [registry::port_registered $portname]
     1553                if { $files != 0 } {
     1554                        if { [llength $files] > 0 } {
     1555                                puts "Port $portname contains:"
     1556                                foreach file $files {
     1557                                        puts "  $file"
     1558                                }
     1559                        } else {
     1560                                puts "Port $portname does not contain any file or is not active."
     1561                        }
     1562                } else {
     1563                        puts "Port $portname is not installed."
     1564                }
     1565        }
     1566       
     1567        return $status
     1568}
     1569
     1570
     1571proc action_deps { action portlist opts } {
     1572        set status 0
     1573        require_portlist portlist
     1574        foreachport $portlist {
     1575                # Get info about the port
     1576                if {[catch {dportsearch $portname no exact} result]} {
     1577                        global errorInfo
     1578                        ui_debug "$errorInfo"
     1579                        break_softcontinue "search for portname $portname failed: $result" 1 status
     1580                }
     1581
     1582                if {$result == ""} {
     1583                        break_softcontinue "No port $portname found." 1 status
     1584                }
     1585
     1586                array set portinfo [lindex $result 1]
     1587
     1588                set depstypes {depends_build depends_lib depends_run}
     1589                set depstypes_descr {"build" "library" "runtime"}
     1590
     1591                set nodeps true
     1592                foreach depstype $depstypes depsdecr $depstypes_descr {
     1593                        if {[info exists portinfo($depstype)] &&
     1594                                $portinfo($depstype) != ""} {
     1595                                puts "$portname has $depsdecr dependencies on:"
     1596                                foreach i $portinfo($depstype) {
     1597                                        puts "\t[lindex [split [lindex $i 0] :] end]"
     1598                                }
     1599                                set nodeps false
     1600                        }
     1601                }
     1602               
     1603                # no dependencies found
     1604                if {$nodeps == "true"} {
     1605                        puts "$portname has no dependencies"
     1606                }
     1607        }
     1608       
     1609        return $status
     1610}
     1611
     1612
     1613proc action_variants { action portlist opts } {
     1614        set status 0
     1615        require_portlist portlist
     1616        foreachport $portlist {
     1617                # search for port
     1618                if {[catch {dportsearch $portname no exact} result]} {
     1619                        global errorInfo
     1620                        ui_debug "$errorInfo"
     1621                        break_softcontinue "search for portname $portname failed: $result" 1 status
     1622                }
     1623       
     1624                if {$result == ""} {
     1625                        puts "No port $portname found."
     1626                }
     1627       
     1628                array set portinfo [lindex $result 1]
     1629       
     1630                # if this fails the port doesn't have any variants
     1631                if {![info exists portinfo(variants)]} {
     1632                        puts "$portname has no variants"
     1633                } else {
     1634                        # print out all the variants
     1635                        puts "$portname has the variants:"
     1636                        for {set i 0} {$i < [llength $portinfo(variants)]} {incr i} {
     1637                                puts "\t[lindex $portinfo(variants) $i]"
     1638                        }
     1639                }
     1640        }
     1641       
     1642        return $status
     1643}
     1644
     1645
     1646proc action_search { action portlist opts } {
     1647        set status 0
     1648        if {![llength portlist]} {
     1649                ui_error "You must specify a search pattern"
     1650                return 1
     1651        }
     1652       
     1653        foreachport $portlist {
     1654                set portfound 0
     1655                if {[catch {set res [dportsearch $portname no]} result]} {
     1656                        global errorInfo
     1657                        ui_debug "$errorInfo"
     1658                        break_softcontinue "search for portname $portname failed: $result" 1 status
     1659                }
     1660                foreach {name array} $res {
     1661                        array set portinfo $array
     1662
     1663                        # XXX is this the right place to verify an entry?
     1664                        if {![info exists portinfo(name)]} {
     1665                                puts "Invalid port entry, missing portname"
     1666                                continue
     1667                        }
     1668                        if {![info exists portinfo(description)]} {
     1669                                puts "Invalid port entry for $portinfo(name), missing description"
     1670                                continue
     1671                        }
     1672                        if {![info exists portinfo(version)]} {
     1673                                puts "Invalid port entry for $portinfo(name), missing version"
     1674                                continue
     1675                        }
     1676                        if {![info exists portinfo(portdir)]} {
     1677                                set output [format "%-30s %-12s %s" $portinfo(name) $portinfo(version) $portinfo(description)]
     1678                        } else {
     1679                                set output [format "%-30s %-14s %-12s %s" $portinfo(name) $portinfo(portdir) $portinfo(version) $portinfo(description)]
     1680                        }
     1681                        set portfound 1
     1682                        puts $output
     1683                        unset portinfo
     1684                }
     1685                if { !$portfound } {
     1686                        ui_msg "No match for $portname found"
     1687                }
     1688        }
     1689       
     1690        return $status
     1691}
     1692
     1693
     1694proc action_list { action portlist opts } {
     1695        set status 0
     1696
     1697        # Default to list all ports if no portnames are supplied
     1698        if {![llength $portlist]} {
     1699                add_to_portlist portlist [list name "-all-"]
     1700        }
     1701       
     1702        foreachport $portlist {
     1703                if {$portname == "-all-"} {
     1704                        set search_string ".+"
     1705                } else {
     1706                        set search_string [regex_pat_sanitize $portname]
     1707                }
     1708               
     1709                if {[catch {set res [dportsearch ^$search_string\$ no]} result]} {
     1710                        global errorInfo
     1711                        ui_debug "$errorInfo"
     1712                        break_softcontinue "search for portname $search_string failed: $result" 1 status
     1713                }
     1714
     1715                foreach {name array} $res {
     1716                        array set portinfo $array
     1717                        set outdir ""
     1718                        if {[info exists portinfo(portdir)]} {
     1719                                set outdir $portinfo(portdir)
     1720                        }
     1721                        puts [format "%-30s @%-14s %s" $portinfo(name) $portinfo(version) $outdir]
     1722                }
     1723        }
     1724       
     1725        return $status
     1726}
     1727
     1728
     1729proc action_echo { action portlist opts } {
     1730        # Simply echo back the port specs given to this command
     1731        foreachport $portlist {
     1732                set opts {}
     1733                foreach { key value } [array get options] {
     1734                        lappend opts "$key=$value"
     1735                }
     1736               
     1737                set composite_version [composite_version $portversion [array get variations] 1]
     1738                if { $composite_version != "" } {
     1739                        set ver_field "@$composite_version"
     1740                } else {
     1741                        set ver_field ""
     1742                }
     1743                puts [format "%-30s %s %s" $portname $ver_field  [join $opts " "]]
     1744        }
     1745       
     1746        return 0
     1747}
     1748
     1749
     1750proc action_portcmds { action portlist opts } {
     1751        # Operations on the port's directory and Portfile
     1752        global env, boot_env
     1753        global current_portdir
     1754       
     1755        set status 0
     1756        require_portlist portlist
     1757        foreachport $portlist {
     1758                # If we have a url, use that, since it's most specific
     1759                # otherwise try to map the portname to a url
     1760                if {$porturl == ""} {
     1761                        # Verify the portname, getting portinfo to map to a porturl
     1762                        if {[catch {set res [dportsearch $portname no exact]} result]} {
     1763                                global errorInfo
     1764                                ui_debug "$errorInfo"
     1765                                break_softcontinue "search for portname $portname failed: $result" 1 status
     1766                        }
     1767                        if {[llength $res] < 2} {
     1768                                break_softcontinue "Port $portname not found" 1 status
     1769                        }
     1770                        array set portinfo [lindex $res 1]
     1771                        set porturl $portinfo(porturl)
     1772                }
     1773               
     1774                set portdir [file normalize [darwinports::getportdir $porturl]]
     1775                set porturl "file://${portdir}";        # Rebuild url so it's fully qualified
     1776                set portfile "${portdir}/Portfile"
     1777               
     1778                if {[file readable $portfile]} {
     1779                        switch -- $action {
     1780                                cat     {
     1781                                        # Copy the portfile to standard output
     1782                                        set f [open $portfile RDONLY]
     1783                                        while { ![eof $f] } {
     1784                                                puts [read $f 4096]
     1785                                        }
     1786                                        close $f
     1787                                }
     1788                               
     1789                                ed - edit {
     1790                                        # Edit the port's portfile with the user's editor
     1791                                       
     1792                                        # Restore our entire environment from start time.
     1793                                        # We need it to evaluate the editor, and the editor
     1794                                        # may want stuff from it as well, like TERM.
     1795                                        array unset env_save; array set env_save [array get env]
     1796                                        array unset env *; array set env [array get boot_env]
     1797                                       
     1798                                        # Find an editor to edit the portfile
     1799                                        set editor ""
     1800                                        foreach ed { VISUAL EDITOR } {
     1801                                                if {[info exists env($ed)]} {
     1802                                                        set editor $env($ed)
     1803                                                        break
     1804                                                }
     1805                                        }
     1806                                       
     1807                                        # Invoke the editor
     1808                                        if { $editor == "" } {
     1809                                                break_softcontinue "No EDITOR is specified in your environment" 1 status
     1810                                        } else {
     1811                                                if {[catch {eval exec >/dev/stdout </dev/stdin $editor $portfile} result]} {
     1812                                                        global errorInfo
     1813                                                        ui_debug "$errorInfo"
     1814                                                        break_softcontinue "unable to invoke editor $editor: $result" 1 status
     1815                                                }
     1816                                        }
     1817                                       
     1818                                        # Restore internal dp environment
     1819                                        array unset env *; array set env [array get env_save]
     1820                                }
     1821                               
     1822                                dir {
     1823                                        # output the path to the port's directory
     1824                                        puts $portdir
     1825                                }
     1826                               
     1827                                cd {
     1828                                        # Change to the port's directory, making it the default
     1829                                        # port for any future commands
     1830                                        set current_portdir $portdir
     1831                                }
     1832
     1833                                url {
     1834                                        # output the url of the port's directory, suitable to feed back in later as a port descriptor
     1835                                        puts $porturl
     1836                                }
     1837
     1838                                file {
     1839                                        # output the path to the port's portfile
     1840                                        puts $portfile
     1841                                }
     1842                        }
     1843                } else {
     1844                        break_softcontinue "Could not read $portfile" 1 status
     1845                }
     1846        }
     1847       
     1848        return $status
     1849}
     1850
     1851
     1852proc action_sync { action portlist opts } {
     1853        set status 0
     1854        if {[catch {dportsync} result]} {
     1855                global errorInfo
     1856                ui_debug "$errorInfo"
     1857                ui_msg "port sync failed: $result"
     1858                set status 1
     1859        }
     1860       
     1861        return $status
     1862}
     1863
     1864
     1865proc action_target { action portlist opts } {
     1866        set status 0
     1867        require_portlist portlist
     1868        foreachport $portlist {
     1869                set target $action
     1870
     1871                # If we have a url, use that, since it's most specific
     1872                # otherwise try to map the portname to a url
     1873                if {$porturl == ""} {
     1874                        # Verify the portname, getting portinfo to map to a porturl
     1875                        if {[catch {set res [dportsearch $portname no exact]} result]} {
     1876                                global errorInfo
     1877                                ui_debug "$errorInfo"
     1878                                break_softcontinue "search for portname $portname failed: $result" 1 status
     1879                        }
     1880                        if {[llength $res] < 2} {
     1881                                break_softcontinue "Port $portname not found" 1 status
     1882                        }
     1883                        array set portinfo [lindex $res 1]
     1884                        set porturl $portinfo(porturl)
     1885                }
     1886               
     1887                # If this is the install target, add any global_variations to the variations
     1888                # specified for the port
     1889                if { $target == "install" } {
     1890                        foreach { variation value } [array get global_variations] {
     1891                                if { ![info exists variations($variation)] } {
     1892                                        set variations($variation) $value
     1893                                }
     1894                        }
     1895                }
     1896
     1897                # If version was specified, save it as a version glob for use
     1898                # in port actions (e.g. clean).
     1899                if {[string length $portversion]} {
     1900                        set options(ports_version_glob) $portversion
     1901                }
     1902                if {[catch {set workername [dportopen $porturl [array get options] [array get variations]]} result]} {
     1903                        global errorInfo
     1904                        ui_debug "$errorInfo"
     1905                        break_softcontinue "Unable to open port: $result" 1 status
     1906                }
     1907                if {[catch {set result [dportexec $workername $target]} result]} {
     1908                        global errorInfo
     1909                        dportclose $workername
     1910                        ui_debug "$errorInfo"
     1911                        break_softcontinue "Unable to execute port: $result" 1 status
     1912                }
     1913
     1914                dportclose $workername
     1915               
     1916                # Process any error that wasn't thrown and handled already
     1917                if {$result} {
     1918                        break_softcontinue "Status $result encountered during processing." 1 status
     1919                }
     1920        }
     1921       
     1922        return $status
     1923}
     1924
     1925
     1926proc action_exit { action portlist opts } {
     1927        # Return a semaphore telling the main loop to quit
     1928        return -999
     1929}
     1930
     1931
     1932##########################################
     1933# Command Parsing
     1934##########################################
     1935proc moreargs {} {
     1936        global cmd_argn cmd_argc
     1937        return [expr {$cmd_argn < $cmd_argc}]
     1938}
     1939
     1940
     1941proc lookahead {} {
     1942        global cmd_argn cmd_argc cmd_argv
     1943        if {$cmd_argn < $cmd_argc} {
     1944                return [lindex $cmd_argv $cmd_argn]
     1945        } else {
     1946                return _EOF_
     1947        }
     1948}
     1949
     1950
     1951proc advance {} {
     1952        global cmd_argn
     1953        incr cmd_argn
     1954}
     1955
     1956
     1957proc match s {
     1958        if {[lookahead] == $s} {
     1959                advance
     1960                return 1
     1961        }
     1962        return 0
     1963}
     1964
     1965
     1966global action_array
     1967array set action_array {
     1968        usage           action_usage
     1969        help            action_help
     1970
     1971        echo            action_echo
     1972       
     1973        info            action_info
     1974        location        action_location
     1975        provides        action_provides
     1976       
     1977        activate        action_activate
     1978        deactivate      action_deactivate
     1979       
     1980        selfupdate      action_selfupdate
     1981        upgrade         action_upgrade
     1982       
     1983        version         action_version
     1984        compact         action_compact
     1985        uncompact       action_uncompact
     1986       
     1987        uninstall       action_uninstall
     1988       
     1989        installed       action_installed
     1990        outdated        action_outdated
     1991        contents        action_contents
     1992        dependents      action_dependents
     1993        deps            action_deps
     1994        variants        action_variants
     1995       
     1996        search          action_search
     1997        list            action_list
     1998       
     1999        ed                      action_portcmds
     2000        edit            action_portcmds
     2001        cat                     action_portcmds
     2002        dir                     action_portcmds
     2003        cd                      action_portcmds
     2004        url                     action_portcmds
     2005        file            action_portcmds
     2006       
     2007        depends         action_target
     2008        fetch           action_target
     2009        checksum        action_target
     2010        extract         action_target
     2011        patch           action_target
     2012        configure       action_target
     2013        build           action_target
     2014        destroot        action_target
     2015        install         action_target
     2016        clean           action_target
     2017        test            action_target
     2018        submit          action_target
     2019        trace           action_target
     2020        livecheck       action_target
     2021
     2022        archive         action_target
     2023        unarchive       action_target
     2024        dmg                     action_target
     2025        dpkg            action_target
     2026        mpkg            action_target
     2027        pkg                     action_target
     2028        rpmpackage      action_target
     2029
     2030        quit            action_exit
     2031        exit            action_exit
     2032}
     2033
     2034
     2035proc find_action_proc { action } {
     2036        global action_array
     2037       
     2038        set action_proc ""
     2039        if { [info exists action_array($action)] } {
     2040                set action_proc $action_array($action)
     2041        }
     2042       
     2043        return $action_proc
     2044}
     2045
     2046
     2047# Parse global options
     2048#
     2049# Note that this is called several times:
     2050#       (1) Initially, to parse options that will be constant across all commands
     2051#               (options that come prior to any command, frozen into global_options_base)
     2052#       (2) Following each command (to parse options that will be unique to that command
     2053#               (the global_options array is reset to global_options_base prior to each command)
     2054#
     2055proc parse_options { action_name ui_options_name global_options_name } {
     2056        upvar $action_name action
     2057        upvar $ui_options_name ui_options
     2058        upvar $global_options_name global_options
     2059       
     2060        while {[moreargs]} {
     2061                set arg [lookahead]
     2062               
     2063                if {[string index $arg 0] != "-"} {
     2064                        break
     2065                } elseif {[string index $arg 1] == "-"} {
     2066                        # Process long arguments
     2067                        switch -- $arg {
     2068                                --                      { # This is the options terminator; do no further option processing
     2069                                                          advance; break
     2070                                                        }
     2071                                --version       { ui_warn "(please use \"$cmdname version\" to get version information)"; set action "version" }
     2072                                default         {
     2073                                                          set key [string range $arg 2 end]
     2074                                                          set global_options(ports_${action}_${key}) yes
     2075                                                        }
     2076                        }
     2077                } else {
     2078                        # Process short arg(s)
     2079                        set opts [string range $arg 1 end]
     2080                        foreach c [split $opts {}] {
     2081                                switch -- $c {
     2082                                        v {     set ui_options(ports_verbose) yes                       }
     2083                                        d { set ui_options(ports_debug) yes
     2084                                                # debug implies verbose
     2085                                                set ui_options(ports_verbose) yes
     2086                                          }
     2087                                        q { set ui_options(ports_quiet) yes
     2088                                                set ui_options(ports_verbose) no
     2089                                                set ui_options(ports_debug) no
     2090                                          }
     2091                                        i { # Always go to interactive mode
     2092                                                lappend ui_options(ports_commandfiles) -        }
     2093                                        p { # Ignore errors while processing within a command
     2094                                                set ui_options(ports_processall) yes            }
     2095                                        x { # Exit with error from any command while in batch/interactive mode
     2096                                                set ui_options(ports_exit) yes                          }
     2097                                       
     2098                                        f { set global_options(ports_force) yes                 }
     2099                                        o { set global_options(ports_ignore_older) yes  }
     2100                                        n { set global_options(ports_nodeps) yes                }
     2101                                        u { set global_options(port_uninstall_old) yes  }
     2102                                        R { set global_options(ports_do_dependents) yes }
     2103                                        s { set global_options(ports_source_only) yes   }
     2104                                        b { set global_options(ports_binary_only) yes   }
     2105                                        c { set global_options(ports_autoclean) yes             }
     2106                                        k { set global_options(ports_autoclean) no              }
     2107                                        t { set global_options(ports_trace) yes                 }
     2108                                        F { # Name a command file to process
     2109                                                advance
     2110                                                if {[moreargs]} {
     2111                                                        lappend ui_options(ports_commandfiles) [lookahead]
     2112                                                }
     2113                                          }
     2114                                        D { advance
     2115                                                if {[moreargs]} {
     2116                                                        cd [lookahead]
     2117                                                }
     2118                                                break
     2119                                          }
     2120                                        default {
     2121                                                print_usage; exit 1
     2122                                          }
     2123                                }
     2124                        }
     2125                }
     2126               
     2127                advance
     2128        }
     2129}
     2130
     2131
     2132proc process_cmd { argv } {
     2133        global cmd_argc cmd_argv cmd_argn
     2134        global global_options global_options_base
     2135        global current_portdir
     2136        set cmd_argv $argv
     2137        set cmd_argc [llength $argv]
     2138        set cmd_argn 0
     2139
     2140        set action_status 0
     2141
     2142        # Process an action if there is one
     2143        while {$action_status == 0 && [moreargs]} {
     2144                set action [lookahead]
     2145                advance
     2146               
     2147                # Handle command separator
     2148                if { $action == ";" } {
     2149                        continue
     2150                }
     2151               
     2152                # Handle a comment
     2153                if { [string index $action 0] == "#" } {
     2154                        while { [moreargs] } { advance }
     2155                        break
     2156                }
     2157               
     2158                # Always start out processing an action in current_portdir
     2159                cd $current_portdir
     2160               
     2161                # Reset global_options from base before each action, as we munge it just below...
     2162                array set global_options $global_options_base
     2163               
     2164                # Parse options that will be unique to this action
     2165                # (to avoid abiguity with -variants and a default port, either -- must be
     2166                # used to terminate option processing, or the pseudo-port current must be specified).
     2167                parse_options action ui_options global_options
     2168               
     2169                # Parse port specifications into portlist
     2170                set portlist {}
     2171                if {![portExpr portlist]} {
     2172                        ui_error "Improper expression syntax while processing parameters"
     2173                        set action_status 1
     2174                        break
     2175                }
     2176
     2177                # Find an action to execute
     2178                set action_proc [find_action_proc $action]
     2179                if { $action_proc != "" } {
     2180                        set action_status [$action_proc $action $portlist [array get global_options]]
     2181                } else {
     2182                        puts "Unrecognized action \"$action\""
     2183                        set action_status 1
     2184                }
     2185               
     2186                # semaphore to exit
     2187                if {$action_status == -999} break
     2188
     2189                # If we're not in exit mode then ignore the status from the command
     2190                if { ![ui_isset ports_exit] } {
     2191                        set action_status 0
     2192                }
     2193        }
     2194       
     2195        return $action_status
     2196}
     2197
     2198
     2199proc complete_portname { text state } {
     2200        global action_array
     2201        global complete_choices complete_position
     2202       
     2203        if {$state == 0} {
     2204                set complete_position 0
     2205                set complete_choices {}
     2206
     2207                # Build a list of ports with text as their prefix
     2208                if {[catch {set res [dportsearch "${text}*" false glob]} result]} {
     2209                        global errorInfo
     2210                        ui_debug "$errorInfo"
     2211                        fatal "search for portname $pattern failed: $result"
     2212                }
     2213                foreach {name info} $res {
     2214                        lappend complete_choices $name
     2215                }
     2216        }
     2217       
     2218        set word [lindex $complete_choices $complete_position]
     2219        incr complete_position
     2220       
     2221        return $word
     2222}
     2223
     2224
     2225proc complete_action { text state } {   
     2226        global action_array
     2227        global complete_choices complete_position
     2228       
     2229        if {$state == 0} {
     2230                set complete_position 0
     2231                set complete_choices [array names action_array "[string tolower $text]*"]
     2232        }
     2233       
     2234        set word [lindex $complete_choices $complete_position]
     2235        incr complete_position
     2236       
     2237        return $word
     2238}
     2239
     2240
     2241proc attempt_completion { text word start end } {
     2242        # If the word starts with '~', or contains '.' or '/', then use the build-in
     2243        # completion to complete the word
     2244        if { [regexp {^~|[/.]} $word] } {
     2245                return ""
     2246        }
     2247
     2248        # Decide how to do completion based on where we are in the string
     2249        set prefix [string range $text 0 [expr $start - 1]]
     2250       
     2251        # If only whitespace characters preceed us, or if the
     2252        # previous non-whitespace character was a ;, then we're
     2253        # an action (the first word of a command)
     2254        if { [regexp {(^\s*$)|(;\s*$)} $prefix] } {
     2255                return complete_action
     2256        }
     2257       
     2258        # Otherwise, do completion on portname
     2259        return complete_portname
     2260}
     2261
     2262
     2263proc get_next_cmdline { in out use_readline prompt linename } {
     2264        upvar $linename line
     2265       
     2266        set line ""
     2267        while { $line == "" } {
     2268       
     2269                if {$use_readline} {
     2270                        set len [readline read -attempted_completion attempt_completion line $prompt]
     2271                } else {
     2272                        puts -nonewline $out $prompt
     2273                        set len [gets $in line]
     2274                }
     2275               
     2276                if { $len < 0 } {
     2277                        return -1
     2278                }
     2279               
     2280                set line [string trim $line]
     2281               
     2282                if { $use_readline && $line != "" } {
     2283                        rl_history add $line
     2284                }
     2285        }
     2286       
     2287        return [llength $line]
     2288}
     2289
     2290
     2291proc process_command_file { in } {
     2292        global current_portdir
     2293
     2294        # Initialize readline
     2295        set isstdin [string match $in "stdin"]
     2296        set name "port"
     2297        set use_readline [expr $isstdin && [readline init $name]]
     2298        set history_file [file normalize "~/.${name}_history"]
     2299       
     2300        # Read readline history
     2301        if {$use_readline} {
     2302                rl_history read $history_file
     2303                rl_history stifle 100
     2304        }
     2305       
     2306        # Be noisy, if appropriate
     2307        set noisy [expr $isstdin && ![ui_isset ports_quiet]]
     2308        if { $noisy } {
     2309                puts "DarwinPorts [darwinports::version]"
     2310                puts "Entering interactive mode... (\"help\" for help)"
     2311        }
     2312       
     2313        # Main command loop
     2314        set exit_status 0
     2315        while { $exit_status == 0 } {
     2316       
     2317                # Calculate our prompt
     2318                if { $noisy } {
     2319                        set shortdir [eval file join [lrange [file split $current_portdir] end-1 end]]
     2320                        set prompt "\[$shortdir\] > "
     2321                } else {
     2322                        set prompt ""
     2323                }
     2324               
     2325                # Get a command line
     2326                if { [get_next_cmdline $in stdout $use_readline $prompt line] <= 0  } {
     2327                        puts ""
     2328                        break
     2329                }
     2330               
     2331                # Process the command
     2332                set exit_status [process_cmd $line]
     2333               
     2334                # Check for semaphore to exit
     2335                if {$exit_status == -999} break
     2336               
     2337                # Ignore status unless we're in error-exit mode
     2338                if { ![ui_isset ports_exit] } {
     2339                        set exit_status 0
     2340                }
     2341        }
     2342       
     2343        # Save readine history
     2344        if {$use_readline} {
     2345                rl_history write $history_file
     2346        }
     2347       
     2348        # Say goodbye
     2349        if { $noisy } {
     2350                puts "Goodbye"
     2351        }
     2352       
     2353        return $exit_status
     2354}
     2355
     2356
     2357proc process_command_files { filelist } {
     2358        set exit_status 0
     2359       
     2360        # For each file in the command list, process commands
     2361        # in the file
     2362        foreach file $filelist {
     2363                if {$file == "-"} {
     2364                        set in stdin
     2365                } else {
     2366                       
     2367                        if {[catch {set in [open $file]} result]} {
     2368                                fatal "Failed to open command file; $result"
     2369                        }
     2370                       
     2371                }
     2372               
     2373                set exit_status [process_command_file $in]
     2374               
     2375                if {$in != "stdin"} {
     2376                        close $in
     2377                }
     2378
     2379                # Check for semaphore to exit
     2380                if {$exit_status == -999} {
     2381                        set exit_status 0
     2382                        break
     2383                }
     2384               
     2385                # Ignore status unless we're in error-exit mode
     2386                if { ![ui_isset ports_exit] } {
     2387                        set exit_status 0
     2388                }
     2389        }
     2390       
     2391        return $exit_status
     2392}
     2393
    10862394
    10872395##########################################
     
    10892397##########################################
    10902398
    1091 # Parse global options
    1092 while {[moreargs]} {
    1093         set arg [lookahead]
    1094        
    1095         if {[string index $arg 0] != "-"} {
    1096                 break
    1097         } elseif {[string index $arg 1] == "-"} {
    1098                 # Process long arguments
    1099                 switch -- $arg {
    1100                         --version       { ui_warn "(please use \"$cmdname version\" to get version information)"; set action "version" }
    1101                         default         { print_usage; exit 1 }
    1102                 }
    1103         } else {
    1104                 # Process short arg(s)
    1105                 set opts [string range $arg 1 end]
    1106                 foreach c [split $opts {}] {
    1107                         switch -- $c {
    1108                                 v {     set ui_options(ports_verbose) yes               }
    1109                                 d { set ui_options(ports_debug) yes
    1110                                         # debug implies verbose
    1111                                         set ui_options(ports_verbose) yes
    1112                                   }
    1113                                 q { set ui_options(ports_quiet) yes
    1114                                         set ui_options(ports_verbose) no
    1115                                         set ui_options(ports_debug) no
    1116                                   }
    1117                                 f { set global_options(ports_force) yes                 }
    1118                                 o { set global_options(ports_ignore_older) yes  }
    1119                                 n { set global_options(ports_nodeps) yes                }
    1120                                 R { set global_options(ports_do_dependents) yes }
    1121                                 u { set global_options(port_uninstall_old) yes  }
    1122                                 s { set global_options(ports_source_only) yes   }
    1123                                 b { set global_options(ports_binary_only) yes   }
    1124                                 c { set global_options(ports_autoclean) yes             }
    1125                                 k { set global_options(ports_autoclean) no              }
    1126                                 t { set global_options(ports_trace) yes                 }
    1127                                 D { advance
    1128                                         cd [lookahead]
    1129                                         break
    1130                                   }
    1131                                 default {
    1132                                         print_usage; exit 1
    1133                                   }
    1134                         }
    1135                 }
    1136         }
    1137        
     2399# globals
     2400array set ui_options            {}
     2401array set global_options        {}
     2402array set global_variations     {}
     2403
     2404# Save off a copy of the environment before dportinit monkeys with it
     2405global env boot_env
     2406array set boot_env [array get env]
     2407
     2408global argv0
     2409global cmdname
     2410set cmdname [file tail $argv0]
     2411
     2412# Setp cmd_argv to match argv
     2413global argc argv
     2414global cmd_argc cmd_argv cmd_argn
     2415set cmd_argv $argv
     2416set cmd_argc $argc
     2417set cmd_argn 0
     2418
     2419# If we've been invoked as portf, then the first argument is assumed
     2420# to be the name of a command file (i.e., there is an implicit -F
     2421# before any arguments).
     2422if {[moreargs] && $cmdname == "portf"} {
     2423        lappend ui_options(ports_commandfiles) [lookahead]
    11382424        advance
    11392425}
    11402426
     2427# Parse global options that will affect all subsequent commands
     2428parse_options default_action ui_options global_options
     2429
     2430# Get arguments remaining after option processing
     2431set remaining_args [lrange $cmd_argv $cmd_argn end]
     2432
    11412433# Initialize dport
    1142 # This must be done following parse of global options, as these are
     2434# This must be done following parse of global options, as some options are
    11432435# evaluated by dportinit.
    11442436if {[catch {dportinit ui_options global_options global_variations} result]} {
     
    11482440}
    11492441
    1150 # Process an action if there is one
    1151 if {[moreargs]} {
    1152         set action [lookahead]
    1153         advance
    1154        
    1155         # Parse action options
    1156         while {[moreargs]} {
    1157                 set arg [lookahead]
    1158                
    1159                 if {[string index $arg 0] != "-"} {
    1160                         break
    1161                 } elseif {[string index $arg 1] == "-"} {
    1162                         # Process long options
    1163                         set key [string range $arg 2 end]
    1164                         set global_options(ports_${action}_${key}) yes
    1165                 } else {
    1166                         # Process short options
    1167                         # There are none for now
    1168                         print_usage; exit 1
    1169                 }
    1170                
    1171                 advance
    1172         }
    1173        
    1174         # Parse port specifications into portlist
    1175         if {![portExpr portlist]} {
    1176                 fatal "Improper expression syntax while processing parameters"
    1177         }
    1178 }
    1179 
    1180 # If there's no action, just print the usage and be done
    1181 if {$action == ""} {
    1182         print_usage
    1183         exit 1
    1184 }
    1185 
    1186 # Perform the action
    1187 switch -- $action {
    1188 
    1189         help {
    1190                 print_help
    1191         }
    1192 
    1193         info {
    1194                 require_portlist
    1195                 foreachport $portlist {
    1196                         # Get information about the named port
    1197                         if {[catch {dportsearch $portname no exact} result]} {
    1198                                 global errorInfo
    1199                                 ui_debug "$errorInfo"
    1200                                 fatal_softcontinue "search for portname $portname failed: $result"
    1201                         }
    1202                
    1203                         if {$result == ""} {
    1204                                 puts "No port $portname found."
    1205                         } else {
    1206                                 set found [expr [llength $result] / 2]
    1207                                 if {$found > 1} {
    1208                                         ui_warn "Found $found port $portname definitions, displaying first one."
    1209                                 }
    1210                                 array set portinfo [lindex $result 1]
    1211        
    1212                                 puts -nonewline "$portinfo(name) $portinfo(version)"
    1213                                 if {[info exists portinfo(revision)] && $portinfo(revision) > 0} {
    1214                                         puts -nonewline ", Revision $portinfo(revision)"
    1215                                 }
    1216                                 puts -nonewline ", $portinfo(portdir)"
    1217                                 if {[info exists portinfo(variants)]} {
    1218                                         puts -nonewline " (Variants: "
    1219                                         for {set i 0} {$i < [llength $portinfo(variants)]} {incr i} {
    1220                                                 if {$i > 0} { puts -nonewline ", " }
    1221                                                 puts -nonewline "[lindex $portinfo(variants) $i]"
    1222                                         }
    1223                                         puts -nonewline ")"
    1224                                 }
    1225                                 puts ""
    1226                                 if {[info exists portinfo(homepage)]} {
    1227                                         puts "$portinfo(homepage)"
    1228                                 }
    1229                
    1230                                 if {[info exists portinfo(long_description)]} {
    1231                                         puts "\n$portinfo(long_description)\n"
    1232                                 }
    1233        
    1234                                 # find build dependencies
    1235                                 if {[info exists portinfo(depends_build)]} {
    1236                                         puts -nonewline "Build Dependencies: "
    1237                                         for {set i 0} {$i < [llength $portinfo(depends_build)]} {incr i} {
    1238                                                 if {$i > 0} { puts -nonewline ", " }
    1239                                                 puts -nonewline "[lindex [split [lindex $portinfo(depends_build) $i] :] end]"
    1240                                         }
    1241                                         set nodeps false
    1242                                         puts ""
    1243                                 }
    1244                
    1245                                 # find library dependencies
    1246                                 if {[info exists portinfo(depends_lib)]} {
    1247                                         puts -nonewline "Library Dependencies: "
    1248                                         for {set i 0} {$i < [llength $portinfo(depends_lib)]} {incr i} {
    1249                                                 if {$i > 0} { puts -nonewline ", " }
    1250                                                 puts -nonewline "[lindex [split [lindex $portinfo(depends_lib) $i] :] end]"
    1251                                         }
    1252                                         set nodeps false
    1253                                         puts ""
    1254                                 }
    1255                
    1256                                 # find runtime dependencies
    1257                                 if {[info exists portinfo(depends_run)]} {
    1258                                         puts -nonewline "Runtime Dependencies: "
    1259                                         for {set i 0} {$i < [llength $portinfo(depends_run)]} {incr i} {
    1260                                                 if {$i > 0} { puts -nonewline ", " }
    1261                                                 puts -nonewline "[lindex [split [lindex $portinfo(depends_run) $i] :] end]"
    1262                                         }
    1263                                         set nodeps false
    1264                                         puts ""
    1265                                 }
    1266                                 if {[info exists portinfo(platforms)]} { puts "Platforms: $portinfo(platforms)"}
    1267                                 if {[info exists portinfo(maintainers)]} { puts "Maintainers: $portinfo(maintainers)"}
    1268                         }
    1269                 }
    1270         }
    1271        
    1272         location {
    1273                 require_portlist
    1274                 foreachport $portlist {
    1275                         if { [catch {set ilist [registry_installed $portname [composite_version $portversion [array get variations]]]} result] } {
    1276                                 global errorInfo
    1277                                 ui_debug "$errorInfo"
    1278                                 fatal_softcontinue "port location failed: $result"
    1279                         } else {
    1280                                 set version [lindex $ilist 1]
    1281                                 set revision [lindex $ilist 2]
    1282                                 set     variants [lindex $ilist 3]
    1283                         }
    1284        
    1285                         set ref [registry::open_entry $portname $version $revision $variants]
    1286                         if { [string equal [registry::property_retrieve $ref installtype] "image"] } {
    1287                                 set imagedir [registry::property_retrieve $ref imagedir]
    1288                                 puts "Port $portname ${version}_${revision}${variants} is installed as an image in:"
    1289                                 puts $imagedir
    1290                         } else {
    1291                                 fatal_softcontinue "Port $portname is not installed as an image."
    1292                         }
    1293                 }
    1294         }
    1295        
    1296         provides {
    1297                 # In this case, portname is going to be used for the filename... since
    1298                 # that is the first argument we expect... perhaps there is a better way
    1299                 # to do this?
    1300                 if { ![llength $portlist] } {
    1301                         fatal "Please specify a filename to check which port provides that file."
    1302                 }
    1303                 foreachport $portlist {
    1304                         set file [compat filenormalize $portname]
    1305                         if {[file exists $file]} {
    1306                                 if {![file isdirectory $file]} {
    1307                                         set port [registry::file_registered $file]
    1308                                         if { $port != 0 } {
    1309                                                 puts "$file is provided by: $port"
    1310                                         } else {
    1311                                                 puts "$file is not provided by a DarwinPorts port."
    1312                                         }
    1313                                 } else {
    1314                                         puts "$file is a directory."
    1315                                 }
    1316                         } else {
    1317                                 puts "$file does not exist."
    1318                         }
    1319                 }
    1320         }
    1321        
    1322         activate {
    1323                 require_portlist
    1324                 foreachport $portlist {
    1325                         if { [catch {portimage::activate $portname [composite_version $portversion [array get variations]] [array get options]} result] } {
    1326                                 global errorInfo
    1327                                 ui_debug "$errorInfo"
    1328                                 fatal_softcontinue "port activate failed: $result"
    1329                         }
    1330                 }
    1331         }
    1332        
    1333         deactivate {
    1334                 require_portlist
    1335                 foreachport $portlist {
    1336                         if { [catch {portimage::deactivate $portname [composite_version $portversion [array get variations]] [array get options]} result] } {
    1337                                 global errorInfo
    1338                                 ui_debug "$errorInfo"
    1339                                 fatal_softcontinue "port deactivate failed: $result"
    1340                         }
    1341                 }
    1342         }
    1343        
    1344         selfupdate {
    1345                 if { [catch {darwinports::selfupdate [array get global_options]} result ] } {
    1346                         global errorInfo
    1347                         ui_debug "$errorInfo"
    1348                         fatal "selfupdate failed: $result"
    1349                 }
    1350         }
    1351 
    1352         dependents {
    1353                 require_portlist
    1354 
    1355                 foreachport $portlist {
    1356                         registry::open_dep_map
    1357                 set deplist [registry::list_dependents $portname]
    1358 
    1359                 if { [llength $deplist] > 0 } {
    1360                         set dl [list]
    1361                         # Check the deps first
    1362                         foreach dep $deplist {
    1363                                 set depport [lindex $dep 2]
    1364                                 ui_msg "$depport depends on $portname"
    1365                                 # xxx: Should look at making registry::installed return 0 or
    1366                                 # something instead  of erroring.
    1367                                 if { ![catch {set installed [registry::installed $depport]} res] } {
    1368                                         if { [llength [registry::installed $depport]] > 0 } {
    1369                                                 lappend dl $depport
    1370                                         }
    1371                                         }
    1372                                 }
    1373                 } else {
    1374                                 ui_msg "$portname has no dependents!"
    1375                         }
    1376                 }
    1377         }
    1378 
    1379         upgrade {
    1380         # Otherwise if the user has supplied no ports we'll use the current port
    1381                 require_portlist
    1382                
    1383                 foreachport $portlist {
    1384                         # Merge global variations into the variations specified for this port
    1385                         foreach { variation value } [array get global_variations] {
    1386                                 if { ![info exists variations($variation)] } {
    1387                                         set variations($variation) $value
    1388                                 }
    1389                         }
    1390                        
    1391                         darwinports::upgrade $portname "port:$portname" [array get variations] [array get options]
    1392                 }
    1393     }
    1394 
    1395         version {
    1396                 puts "Version: [darwinports::version]"
    1397         }
    1398 
    1399         compact {
    1400                 require_portlist
    1401                 foreachport $portlist {
    1402                         if { [catch {portimage::compact $portname [composite_version $portversion [array get variations]]} result] } {
    1403                                 global errorInfo
    1404                                 ui_debug "$errorInfo"
    1405                                 fatal_softcontinue "port compact failed: $result"
    1406                         }
    1407                 }
    1408         }
    1409        
    1410         uncompact {
    1411                 require_portlist
    1412                 foreachport $portlist {
    1413                         if { [catch {portimage::uncompact $portname [composite_version $portversion [array get variations]]} result] } {
    1414                                 global errorInfo
    1415                                 ui_debug "$errorInfo"
    1416                                 fatal_softcontinue "port uncompact failed: $result"
    1417                         }
    1418                 }
    1419         }
    1420        
    1421         uninstall {
    1422                 if {[info exists global_options(port_uninstall_old)]} {
    1423                         # if -u then uninstall all inactive ports
    1424                         # (union these to any other ports user has in the port list)
    1425                         set portlist [opUnion $portlist [get_inactive_ports]]
    1426                 } else {
    1427                         # Otherwise the user had better have supplied a portlist, or we'll default to the existing directory
    1428                         require_portlist
    1429                 }
    1430 
    1431                 foreachport $portlist {
    1432                         if { [catch {portuninstall::uninstall $portname [composite_version $portversion [array get variations]] [array get options]} result] } {
    1433                                 global errorInfo
    1434                                 ui_debug "$errorInfo"
    1435                                 fatal_softcontinue "port uninstall failed: $result"
    1436                         }
    1437                 }
    1438         }
    1439        
    1440         installed {
    1441         if { [llength $portlist] } {
    1442                         set ilist {}
    1443                         foreachport $portlist {
    1444                         set composite_version [composite_version $portversion [array get variations]]
    1445                                 if { [catch {set ilist [concat $ilist [registry::installed $portname $composite_version]]} result] } {
    1446                                         if {[string match "* not registered as installed." $result]} {
    1447                                                 puts "Port $portname is not installed."
    1448                                         } else {
    1449                                                 global errorInfo
    1450                                                 ui_debug "$errorInfo"
    1451                                                 fatal_softcontinue "port installed failed: $result"
    1452                                         }
    1453                                 }
    1454                         }
    1455         } else {
    1456             if { [catch {set ilist [registry::installed]} result] } {
    1457                 if {$result == "Registry error: No ports registered as installed."} {
    1458                     puts "No ports are installed!"
    1459                                         set ilist {}
    1460                 } else {
    1461                                         global errorInfo
    1462                                         ui_debug "$errorInfo"
    1463                     fatal "port installed failed: $result"
    1464                 }
    1465             }
    1466         }
    1467         if { [llength $ilist] > 0 } {
    1468             puts "The following ports are currently installed:"
    1469             foreach i $ilist {
    1470                 set iname [lindex $i 0]
    1471                 set iversion [lindex $i 1]
    1472                 set irevision [lindex $i 2]
    1473                 set ivariants [lindex $i 3]
    1474                 set iactive [lindex $i 4]
    1475                 if { $iactive == 0 } {
    1476                     puts "  $iname @${iversion}_${irevision}${ivariants}"
    1477                 } elseif { $iactive == 1 } {
    1478                     puts "  $iname @${iversion}_${irevision}${ivariants} (active)"
    1479                 }
    1480             }
    1481         } else {
    1482             exit 1
    1483         }
    1484     }
    1485 
    1486         outdated {
    1487                 # If port names were supplied, limit ourselves to those port, else check all installed ports
    1488        if { [llength $portlist] } {
    1489                         set ilist {}
    1490                 foreach portspec $portlist {
    1491                         array set port $portspec
    1492                         set portname $port(name)
    1493                         set composite_version [composite_version $port(version) $port(variants)]
    1494                                 if { [catch {set ilist [concat $ilist [registry::installed $portname $composite_version]]} result] } {
    1495                                         if {![string match "* not registered as installed." $result]} {
    1496                                                 global errorInfo
    1497                                                 ui_debug "$errorInfo"
    1498                                                 fatal_softcontinue "port outdated failed: $result"
    1499                                         }
    1500                                 }
    1501                         }
    1502                 } else {
    1503                         if { [catch {set ilist [registry::installed]} result] } {
    1504                                 global errorInfo
    1505                                 ui_debug "$errorInfo"
    1506                                 fatal "port outdated failed: $result"
    1507                         }
    1508                 }
    1509        
    1510                 if { [llength $ilist] > 0 } {
    1511                         puts "The following installed ports are outdated:"
    1512                
    1513                         foreach i $ilist {
    1514 
    1515                                 # Get information about the installed port
    1516                                 set portname                    [lindex $i 0]
    1517                                 set installed_version   [lindex $i 1]
    1518                                 set installed_revision  [lindex $i 2]
    1519                                 set installed_compound  "${installed_version}_${installed_revision}"
    1520 
    1521                                 set is_active                   [lindex $i 4]
    1522                                 if { $is_active == 0 } {
    1523                                         continue
    1524                                 }
    1525                                 set installed_epoch             [lindex $i 5]
    1526 
    1527                                 # Get info about the port from the index
    1528                                 if {[catch {set res [dportsearch $portname no exact]} result]} {
    1529                                         global errorInfo
    1530                                         ui_debug "$errorInfo"
    1531                                         fatal_softcontinue "search for portname $portname failed: $result"
    1532                                 }
    1533                                 if {[llength $res] < 2} {
    1534                                         if {[ui_isset ports_debug]} {
    1535                                                 puts "$portname ($installed_compound is installed; the port was not found in the port index)"
    1536                                         }
    1537                                         continue
    1538                                 }
    1539                                 array set portinfo [lindex $res 1]
    1540                                
    1541                                 # Get information about latest available version and revision
    1542                                 set latest_version $portinfo(version)
    1543                                 set latest_revision             0
    1544                                 if {[info exists portinfo(revision)] && $portinfo(revision) > 0} {
    1545                                         set latest_revision     $portinfo(revision)
    1546                                 }
    1547                                 set latest_compound             "${latest_version}_${latest_revision}"
    1548                                 set latest_epoch                0
    1549                                 if {[info exists portinfo(epoch)]} {
    1550                                         set latest_epoch        $portinfo(epoch)
    1551                                 }
    1552                                
    1553                                 # Compare versions, first checking epoch, then the compound version string
    1554                                 set comp_result [expr $installed_epoch - $latest_epoch]
    1555                                 if { $comp_result == 0 } {
    1556                                         set comp_result [rpm-vercomp $installed_compound $latest_compound]
    1557                                 }
    1558                                
    1559                                 # Report outdated (or, for verbose, predated) versions
    1560                                 if { $comp_result != 0 } {
    1561                                                                
    1562                                         # Form a relation between the versions
    1563                                         set flag ""
    1564                                         if { $comp_result > 0 } {
    1565                                                 set relation ">"
    1566                                                 set flag "!"
    1567                                         } else {
    1568                                                 set relation "<"
    1569                                         }
    1570                                        
    1571                                         # Emit information
    1572                                         if {$comp_result < 0 || [ui_isset ports_verbose]} {
    1573                                                 puts [format "%-30s %-24s %1s" $portname "$installed_compound $relation $latest_compound" $flag]
    1574                                         }
    1575                                        
    1576                                 }
    1577                         }
    1578                 } else {
    1579                         exit 1
    1580                 }
    1581         }
    1582 
    1583         contents {
    1584                 require_portlist
    1585                 foreachport $portlist {
    1586                         set files [registry::port_registered $portname]
    1587                         if { $files != 0 } {
    1588                                 if { [llength $files] > 0 } {
    1589                                         puts "Port $portname contains:"
    1590                                         foreach file $files {
    1591                                                 puts "  $file"
    1592                                         }
    1593                                 } else {
    1594                                         puts "Port $portname does not contain any file or is not active."
    1595                                 }
    1596                         } else {
    1597                                 puts "Port $portname is not installed."
    1598                         }
    1599                 }
    1600         }
    1601        
    1602         deps {
    1603                 require_portlist
    1604                 foreachport $portlist {
    1605                         # Get info about the port
    1606                         if {[catch {dportsearch $portname no exact} result]} {
    1607                                 global errorInfo
    1608                                 ui_debug "$errorInfo"
    1609                                 fatal_softcontinue "search for portname $portname failed: $result"
    1610                         }
    1611        
    1612                         if {$result == ""} {
    1613                                 fatal "No port $portname found."
    1614                         }
    1615        
    1616                         array set portinfo [lindex $result 1]
    1617        
    1618                         set depstypes {depends_build depends_lib depends_run}
    1619                         set depstypes_descr {"build" "library" "runtime"}
    1620        
    1621                         set nodeps true
    1622                         foreach depstype $depstypes depsdecr $depstypes_descr {
    1623                                 if {[info exists portinfo($depstype)] &&
    1624                                         $portinfo($depstype) != ""} {
    1625                                         puts "$portname has $depsdecr dependencies on:"
    1626                                         foreach i $portinfo($depstype) {
    1627                                                 puts "\t[lindex [split [lindex $i 0] :] end]"
    1628                                         }
    1629                                         set nodeps false
    1630                                 }
    1631                         }
    1632                        
    1633                         # no dependencies found
    1634                         if {$nodeps == "true"} {
    1635                                 puts "$portname has no dependencies"
    1636                         }
    1637                 }
    1638         }
    1639        
    1640         variants {
    1641                 require_portlist
    1642                 foreachport $portlist {
    1643                         # search for port
    1644                         if {[catch {dportsearch $portname no exact} result]} {
    1645                                 global errorInfo
    1646                                 ui_debug "$errorInfo"
    1647                                 fatal_softcontinue "search for portname $portname failed: $result"
    1648                         }
    1649                
    1650                         if {$result == ""} {
    1651                                 puts "No port $portname found."
    1652                         }
    1653                
    1654                         array set portinfo [lindex $result 1]
    1655                
    1656                         # if this fails the port doesn't have any variants
    1657                         if {![info exists portinfo(variants)]} {
    1658                                 puts "$portname has no variants"
    1659                         } else {
    1660                                 # print out all the variants
    1661                                 puts "$portname has the variants:"
    1662                                 for {set i 0} {$i < [llength $portinfo(variants)]} {incr i} {
    1663                                         puts "\t[lindex $portinfo(variants) $i]"
    1664                                 }
    1665                         }
    1666                 }
    1667         }
    1668        
    1669         search {
    1670                 if {![llength portlist]} {
    1671                         fatal "You must specify a search pattern"
    1672                 }
    1673                
    1674                 foreachport $portlist {
    1675                         if {[catch {set res [dportsearch $portname no]} result]} {
    1676                                 global errorInfo
    1677                                 ui_debug "$errorInfo"
    1678                                 fatal_softcontinue "search for portname $portname failed: $result"
    1679                         }
    1680                         foreach {name array} $res {
    1681                                 array set portinfo $array
    1682        
    1683                                 # XXX is this the right place to verify an entry?
    1684                                 if {![info exists portinfo(name)]} {
    1685                                         puts "Invalid port entry, missing portname"
    1686                                         continue
    1687                                 }
    1688                                 if {![info exists portinfo(description)]} {
    1689                                         puts "Invalid port entry for $portinfo(name), missing description"
    1690                                         continue
    1691                                 }
    1692                                 if {![info exists portinfo(version)]} {
    1693                                         puts "Invalid port entry for $portinfo(name), missing version"
    1694                                         continue
    1695                                 }
    1696                                 if {![info exists portinfo(portdir)]} {
    1697                                         set output [format "%-30s @%-12s %s" $portinfo(name) $portinfo(version) $portinfo(description)]
    1698                                 } else {
    1699                                         set output [format "%-30s %-14s @%-12s %s" $portinfo(name) $portinfo(portdir) $portinfo(version) $portinfo(description)]
    1700                                 }
    1701                                 set portfound 1
    1702                                 puts $output
    1703                                 unset portinfo
    1704                         }
    1705                         if {![info exists portfound] || $portfound == 0} {
    1706                                 fatal "No match for $portname found"
    1707                         }
    1708                 }
    1709         }
    1710        
    1711         list {
    1712                 # Default to list all ports if no portnames are supplied
    1713                 if {![llength $portlist]} {
    1714                         add_to_portlist portlist [list name "-all-"]
    1715                 }
    1716                
    1717                 foreachport $portlist {
    1718                         if {$portname == "-all-"} {
    1719                                 set search_string ".+"
    1720                         } else {
    1721                                 set search_string [regex_pat_sanitize $portname]
    1722                         }
    1723                        
    1724                         if {[catch {set res [dportsearch ^$search_string\$ no]} result]} {
    1725                                 global errorInfo
    1726                                 ui_debug "$errorInfo"
    1727                                 fatal_softcontinue "search for portname $search_string failed: $result"
    1728                         }
    1729 
    1730                         foreach {name array} $res {
    1731                                 array set portinfo $array
    1732                                 set outdir ""
    1733                                 if {[info exists portinfo(portdir)]} {
    1734                                         set outdir $portinfo(portdir)
    1735                                 }
    1736                                 puts [format "%-30s @%-14s %s" $portinfo(name) $portinfo(version) $outdir]
    1737                         }
    1738                 }
    1739         }
    1740        
    1741         echo {
    1742                 # Simply echo back the port specs given to this command
    1743                 foreachport $portlist {
    1744                         set opts {}
    1745                         foreach { key value } [array get options] {
    1746                                 lappend opts "$key=$value"
    1747                         }
    1748                        
    1749                         set composite_version [composite_version $portversion [array get variations] 1]
    1750                         if { $composite_version != "" } {
    1751                                 set ver_field "@$composite_version"
    1752                         } else {
    1753                                 set ver_field ""
    1754                         }
    1755                         puts [format "%-30s %s %s" $portname $ver_field  [join $opts " "]]
    1756                 }
    1757         }
    1758        
    1759         ed - edit -
    1760         cat -
    1761         dir -
    1762         url -
    1763         file {
    1764                 # Operations on the port's directory and Portfile
    1765                 require_portlist
    1766                 foreachport $portlist {
    1767                         # If we have a url, use that, since it's most specific
    1768                         # otherwise try to map the portname to a url
    1769                         if {$porturl == ""} {
    1770                                 # Verify the portname, getting portinfo to map to a porturl
    1771                                 if {[catch {set res [dportsearch $portname no exact]} result]} {
    1772                                         global errorInfo
    1773                                         ui_debug "$errorInfo"
    1774                                         fatal_softcontinue "search for portname $portname failed: $result"
    1775                                 }
    1776                                 if {[llength $res] < 2} {
    1777                                         fatal_softcontinue "Port $portname not found"
    1778                                 }
    1779                                 array set portinfo [lindex $res 1]
    1780                                 set porturl $portinfo(porturl)
    1781                         }
    1782                        
    1783                         set portdir [file normalize [darwinports::getportdir $porturl]]
    1784                         set porturl "file://${portdir}";        # Rebuild url so it's fully qualified
    1785                         set portfile "${portdir}/Portfile"
    1786                        
    1787                         if {[file readable $portfile]} {
    1788                                 switch -- $action {
    1789                                         cat     {
    1790                                                 # Copy the portfile to standard output
    1791                                                 set f [open $portfile RDONLY]
    1792                                                 while { ![eof $f] } {
    1793                                                         puts [read $f 4096]
    1794                                                 }
    1795                                                 close $f
    1796                                         }
    1797                                        
    1798                                         ed - edit {
    1799                                                 # Edit the port's portfile with the user's editor
    1800                                                
    1801                                                 # Restore our entire environment from start time.
    1802                                                 # We need it to evaluate the editor, and the editor
    1803                                                 # may want stuff from it as well, like TERM.
    1804                                                 array unset env_save; array set env_save [array get env]
    1805                                                 array unset env *; array set env [array get boot_env]
    1806                                                
    1807                                                 # Find an editor to edit the portfile
    1808                                                 set editor ""
    1809                                                 foreach ed { VISUAL EDITOR } {
    1810                                                         if {[info exists env($ed)]} {
    1811                                                                 set editor $env($ed)
    1812                                                                 break
    1813                                                         }
    1814                                                 }
    1815                                                
    1816                                                 # Invoke the editor
    1817                                                 if { $editor == "" } {
    1818                                                         fatal "No EDITOR is specified in your environment"
    1819                                                 } else {
    1820                                                         if {[catch {eval exec >/dev/stdout </dev/stdin $editor $portfile} result]} {
    1821                                                                 global errorInfo
    1822                                                                 ui_debug "$errorInfo"
    1823                                                                 fatal "unable to invoke editor $editor: $result"
    1824                                                         }
    1825                                                 }
    1826                                                
    1827                                                 # Restore internal dp environment
    1828                                                 array unset env *; array set env [array get env_save]
    1829                                         }
    1830                                        
    1831                                         dir {
    1832                                                 # output the path to the port's directory
    1833                                                 puts $portdir
    1834                                         }
    1835 
    1836                                         url {
    1837                                                 # output the url of the port's directory, suitable to feed back in later as a port descriptor
    1838                                                 puts $porturl
    1839                                         }
    1840 
    1841                                         file {
    1842                                                 # output the path to the port's portfile
    1843                                                 puts $portfile
    1844                                         }
    1845                                 }
    1846                         } else {
    1847                                 fatal_softcontinue "Could not read $portfile"
    1848                         }
    1849                 }
    1850         }
    1851        
    1852         sync {
    1853                 if {[catch {dportsync} result]} {
    1854                         global errorInfo
    1855                         ui_debug "$errorInfo"
    1856                         fatal "port sync failed: $result"
    1857                 }
    1858         }
    1859        
    1860         default {
    1861                 require_portlist
    1862                 foreachport $portlist {
    1863                         set target $action
    1864 
    1865                         # If we have a url, use that, since it's most specific
    1866                         # otherwise try to map the portname to a url
    1867                         if {$porturl == ""} {
    1868                                 # Verify the portname, getting portinfo to map to a porturl
    1869                                 if {[catch {set res [dportsearch $portname no exact]} result]} {
    1870                                         global errorInfo
    1871                                         ui_debug "$errorInfo"
    1872                                         fatal_softcontinue "search for portname $portname failed: $result"
    1873                                 }
    1874                                 if {[llength $res] < 2} {
    1875                                         fatal_softcontinue "Port $portname not found"
    1876                                 }
    1877                                 array set portinfo [lindex $res 1]
    1878                                 set porturl $portinfo(porturl)
    1879                         }
    1880                        
    1881                         # If this is the install target, add any global_variations to the variations
    1882                         # specified for the port
    1883                         if { $target == "install" } {
    1884                                 foreach { variation value } [array get global_variations] {
    1885                                         if { ![info exists variations($variation)] } {
    1886                                                 set variations($variation) $value
    1887                                         }
    1888                                 }
    1889                         }
    1890 
    1891                         # If version was specified, save it as a version glob for use
    1892                         # in port actions (e.g. clean).
    1893                         if {[string length $portversion]} {
    1894                                 set options(ports_version_glob) $portversion
    1895                         }
    1896                         if {[catch {set workername [dportopen $porturl [array get options] [array get variations]]} result]} {
    1897                                 global errorInfo
    1898                                 ui_debug "$errorInfo"
    1899                                 fatal_softcontinue "Unable to open port: $result"
    1900                         }
    1901                         if {[catch {set result [dportexec $workername $target]} result]} {
    1902                                 global errorInfo
    1903                                 dportclose $workername
    1904                                 ui_debug "$errorInfo"
    1905                                 fatal_softcontinue "Unable to execute port: $result"
    1906                         }
    1907 
    1908                         dportclose $workername
    1909                        
    1910                         # Process any error that wasn't thrown and handled already
    1911                         if {$result} {
    1912                                 fatal_softcontinue "Status $result encountered during processing."
    1913                         }
    1914                 }
    1915         }
    1916 }
    1917 
    1918 
     2442# If we have no arguments remaining after option processing then force
     2443# interactive mode
     2444if { [llength $remaining_args] == 0 && ![info exists ui_options(ports_commandfiles)] } {
     2445        lappend ui_options(ports_commandfiles) -
     2446}
     2447
     2448# Set up some global state for our code
     2449global current_portdir
     2450set current_portdir [pwd]
     2451
     2452# Freeze global_options into global_options_base; global_options
     2453# will be reset to global_options_base prior to processing each command.
     2454global global_options_base
     2455set global_options_base [array get global_options]
     2456
     2457# First process any remaining args as action(s)
     2458set exit_status 0
     2459if { [llength $remaining_args] > 0 } {
     2460
     2461        # If there are remaining arguments, process those as a command
     2462       
     2463        # Exit immediately, by default, unless we're going to be processing command files
     2464        if {![info exists ui_options(ports_commandfiles)]} {
     2465                set ui_options(ports_exit) yes
     2466        }
     2467        set exit_status [process_cmd $remaining_args]
     2468}
     2469
     2470# Process any prescribed command files, including standard input
     2471if { $exit_status == 0 && [info exists ui_options(ports_commandfiles)] } {
     2472        set exit_status [process_command_files $ui_options(ports_commandfiles)]
     2473}
     2474
     2475# Return with exit_status
     2476exit $exit_status
Note: See TracChangeset for help on using the changeset viewer.