diff --git a/doc/port-info.1 b/doc/port-info.1 index 26a23ec636..940c0ed7a0 100644 --- a/doc/port-info.1 +++ b/doc/port-info.1 @@ -29,14 +29,15 @@ port-info \- Return information about the given ports\&. [\-\-depends_extract] [\-\-depends_build] [\-\-depends_lib] [\-\-depends_run] [\-\-description] [\-\-epoch] [\-\-fullname] [\-\-heading] [\-\-homepage] [\-\-index] [\-\-license] [\-\-line] [\-\-long_description] [\-\-maintainer|\-\-maintainers] - [\-\-name] [\-\-patchfiles] [\-\-platform|\-\-platforms] [\-\-portdir] [\-\-pretty] + [\-\-name] [\-\-patchfiles] [\-\-platform|\-\-platforms] [\-\-portdir] + [\-\-portgroup|\-\-portgroups] [\-\-pretty] [\-\-replaced_by] [\-\-revision] [\-\-subports] [\-\-variant|\-\-variants] [\-\-version] [[\fIportname\fR | \fIpseudo\-portname\fR | \fIport\-expressions\fR | \fIport\-url\fR]] .fi .SH "DESCRIPTION" .sp -\fBport info\fR prints information about the given ports\&. Specifying at least one of the options limits the output to the corresponding field\&. If no fields are specified, a useful default set consisting of name, epoch, version, revision, categories, replaced_by, variants, description, homepage, dependencies, platforms, license, and maintainers is shown\&. +\fBport info\fR prints information about the given ports\&. Specifying at least one of the options limits the output to the corresponding field\&. If no fields are specified, a useful default set consisting of name, epoch, version, revision, categories, replaced_by, variants, description, homepage, dependencies, portgroups, platforms, license, and maintainers is shown\&. .SH "OPTIONS" .sp The following options do not select fields for the output but change how the information is obtained or formatted: @@ -137,6 +138,11 @@ List the platforms supported by a port\&. This field exists for historical reaso Print the path to a port\(cqs directory relative to the port tree root\&. .RE .PP +\fB\-\-portgroup\fR, \fB\-\-portgroups\fR +.RS 4 +List the PortGroups used by a port, including their versions\&. +.RE +.PP \fB\-\-replaced_by\fR .RS 4 List the name of the port that replaces a port, if any\&. diff --git a/doc/port-info.1.txt b/doc/port-info.1.txt index 3b29e71918..b00563436b 100644 --- a/doc/port-info.1.txt +++ b/doc/port-info.1.txt @@ -14,7 +14,8 @@ SYNOPSIS [--depends_extract] [--depends_build] [--depends_lib] [--depends_run] [--description] [--epoch] [--fullname] [--heading] [--homepage] [--index] [--license] [--line] [--long_description] [--maintainer|--maintainers] - [--name] [--patchfiles] [--platform|--platforms] [--portdir] [--pretty] + [--name] [--patchfiles] [--platform|--platforms] [--portdir] + [--portgroup|--portgroups] [--pretty] [--replaced_by] [--revision] [--subports] [--variant|--variants] [--version] [['portname' | 'pseudo-portname' | 'port-expressions' | 'port-url']] @@ -25,7 +26,7 @@ DESCRIPTION the options limits the output to the corresponding field. If no fields are specified, a useful default set consisting of name, epoch, version, revision, categories, replaced_by, variants, description, homepage, dependencies, -platforms, license, and maintainers is shown. +portgroups, platforms, license, and maintainers is shown. OPTIONS ------- @@ -93,6 +94,9 @@ The rest of the options affect which fields will be given in the output: *--portdir*:: Print the path to a port's directory relative to the port tree root. +*--portgroup*, *--portgroups*:: + List the PortGroups used by a port, including their versions. + *--replaced_by*:: List the name of the port that replaces a port, if any. diff --git a/doc/port-search.1 b/doc/port-search.1 index cbdd85281c..16292b5ee1 100644 --- a/doc/port-search.1 +++ b/doc/port-search.1 @@ -134,6 +134,17 @@ in the name, but not the description\&. Test the search string against the path of the directory that contains the port\&. .RE .PP +\fB\-\-portgroup\fR, \fB\-\-portgroups\fR +.RS 4 +Search for ports that use a given PortGroup\&. For example, +\fBport search \-\-portgroup python\fR +will print all ports using the python PortGroup\&. There is also a pseudo\-portname selector +\fBportgroup:python\fR +available for use with +\fBport-echo\fR(1) +and other commands\&. +.RE +.PP \fB\-\-variant\fR, \fB\-\-variants\fR .RS 4 Search for variant names\&. diff --git a/doc/port-search.1.txt b/doc/port-search.1.txt index 997206fd4b..ffb05d8294 100644 --- a/doc/port-search.1.txt +++ b/doc/port-search.1.txt @@ -98,6 +98,12 @@ Field selection Test the search string against the path of the directory that contains the port. +*--portgroup*, *--portgroups*:: + Search for ports that use a given PortGroup. For example, *port search + --portgroup python* will print all ports using the python PortGroup. There + is also a pseudo-portname selector *portgroup:python* available for use + with man:port-echo[1] and other commands. + *--variant*, *--variants*:: Search for variant names. diff --git a/doc/port.1 b/doc/port.1 index b7c63cebfa..618afa40b0 100644 --- a/doc/port.1 +++ b/doc/port.1 @@ -314,6 +314,95 @@ or .sp -1 .IP \(bu 2.3 .\} +\fIdepends_lib\fR +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +\fIdepends_build\fR +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +\fIdepends_run\fR +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +\fIdepends_fetch\fR +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +\fIdepends_extract\fR +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +\fIdepends_patch\fR +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +\fIdepends_test\fR +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +\fIdepends\fR +(shorthand for all depends_* selectors) +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} \fIlicense\fR .RE .sp @@ -325,9 +414,46 @@ or .sp -1 .IP \(bu 2.3 .\} +\fIreplaced_by\fR +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} \fIportdir\fR .RE .sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +\fIportgroup\fR +or +\fIportgroups\fR +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +\fIsubport\fR +or +\fIsubports\fR +.RE +.sp Other pseudo\-portname selectors match ports which have a particular relationship to another port\&. These will match ports that are direct or recursive dependencies or dependents of the given portname: .sp .RS 4 @@ -385,6 +511,17 @@ Other pseudo\-portname selectors match ports which have a particular relationshi \fIrdependentof\fR .RE .sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +\fIsubportof\fR +.RE +.sp Search strings that will expand to a set of matching ports can be constructed based on the "\fIpseudo\-portname selector\fR":regex combination used\&. \fIportnames\fR containing valid UNIX glob patterns will also expand to the set of matching ports\&. Any action passed to port will be invoked on each of them\&. .sp For example: @@ -451,7 +588,7 @@ Debug mode, generate debugging messages, implies \-v \-T .RS 4 Timestamp mode, prepend an ISO 8601 timestamp (e\&.g\&. -2026\-03\-18T09:42:01\-0400) to every line of output\&. +\fI2026\-03\-18T09:42:01\-0400\fR) to every line of output\&. .RE .PP \-q diff --git a/doc/port.1.txt b/doc/port.1.txt index a29a861db4..16a3ffd903 100644 --- a/doc/port.1.txt +++ b/doc/port.1.txt @@ -73,8 +73,19 @@ matches the given regular expression. Usage is: selector:regex - 'description' - 'long_description' - 'homepage' + - 'depends_lib' + - 'depends_build' + - 'depends_run' + - 'depends_fetch' + - 'depends_extract' + - 'depends_patch' + - 'depends_test' + - 'depends' (shorthand for all depends_* selectors) - 'license' + - 'replaced_by' - 'portdir' + - 'portgroup' or 'portgroups' + - 'subport' or 'subports' Other pseudo-portname selectors match ports which have a particular relationship to another port. These will match ports that are direct or @@ -86,6 +97,7 @@ recursive dependencies or dependents of the given portname: - 'rdepends' - 'dependentof' - 'rdependentof' + - 'subportof' Search strings that will expand to a set of matching ports can be constructed based on the "'pseudo-portname selector'":regex combination used. 'portnames' diff --git a/src/macports1.0/tests/macports.test b/src/macports1.0/tests/macports.test index 0ba6cbc3d7..f3bc8bd2e3 100644 --- a/src/macports1.0/tests/macports.test +++ b/src/macports1.0/tests/macports.test @@ -940,7 +940,69 @@ test GetVCSUpdateCmd-none { # test updatevcs # test mportsync -# test mportsearch + +test mportsearch_portgroups { + Test mportsearch with portgroups field. +} -setup { + # Create a temporary source directory with a crafted PortIndex + set tmpdir [makeDirectory mportsearch_test_source $pwd/tmpdir] + set portinfo1 {description {A test port} portgroups {{python 1.0} {github 1.0}} homepage https://example.com epoch 0 platforms darwin name testport1 maintainers nomaintainer license MIT long_description {A test port} categories devel version 1.0 revision 0 portdir test/testport1} + set portinfo2 {description {Another test port} portgroups {{golang 1.0}} homepage https://example.com epoch 0 platforms darwin name testport2 maintainers nomaintainer license BSD long_description {Another test port} categories net version 2.0 revision 0 portdir test/testport2} + set portinfo3 {description {Port without portgroups} homepage https://example.com epoch 0 platforms darwin name testport3 maintainers nomaintainer license GPL-2 long_description {Port without portgroups} categories sysutils version 3.0 revision 0 portdir test/testport3} + + set fd [open $tmpdir/PortIndex w] + puts $fd "testport1 [expr {[string length $portinfo1] + 1}]" + puts $fd $portinfo1 + puts $fd "testport2 [expr {[string length $portinfo2] + 1}]" + puts $fd $portinfo2 + puts $fd "testport3 [expr {[string length $portinfo3] + 1}]" + puts $fd $portinfo3 + close $fd + + # Save original sources and set up test source + set save_sources $macports::sources + set save_prefix_map $macports::porturl_prefix_map + set macports::sources [list "file://${tmpdir}"] + dict set macports::porturl_prefix_map "file://${tmpdir}" "file://${tmpdir}" +} -body { + # Search for ports using the python portgroup + set results [mportsearch "*python*" no glob portgroups] + if {[llength $results] != 2} { + return "FAIL: expected 2 results (name + info), got [llength $results]" + } + if {[lindex $results 0] ne "testport1"} { + return "FAIL: expected testport1, got [lindex $results 0]" + } + + # Search for ports using the golang portgroup + set results [mportsearch "*golang*" no glob portgroups] + if {[llength $results] != 2} { + return "FAIL: expected 2 results for golang, got [llength $results]" + } + if {[lindex $results 0] ne "testport2"} { + return "FAIL: expected testport2, got [lindex $results 0]" + } + + # Search for ports using the github portgroup (should match testport1) + set results [mportsearch "*github*" no glob portgroups] + if {[llength $results] != 2} { + return "FAIL: expected 2 results for github, got [llength $results]" + } + + # Search for a portgroup that doesn't exist + set results [mportsearch "*nonexistent*" no glob portgroups] + if {[llength $results] != 0} { + return "FAIL: expected 0 results for nonexistent, got [llength $results]" + } + + return "mportsearch portgroups successful." +} -cleanup { + set macports::sources $save_sources + set macports::porturl_prefix_map $save_prefix_map + file delete -force $tmpdir +} -result "mportsearch portgroups successful." + + # test mportlookup # test mportlistall # test _mports_load_quickindex diff --git a/src/port/port.tcl b/src/port/port.tcl index 282107c9d9..6ffdb6e4b9 100755 --- a/src/port/port.tcl +++ b/src/port/port.tcl @@ -140,6 +140,9 @@ proc map_friendly_field_names { field } { category { set field "categories" } + portgroup { + set field "portgroups" + } } return $field @@ -1160,6 +1163,8 @@ proc element { resname } { ^(revision):(.*) - ^(subport):(.*) - ^(subports):(.*) - + ^(portgroup):(.*) - + ^(portgroups):(.*) - ^(license):(.*) { # Handle special port selectors advance @@ -1751,6 +1756,7 @@ proc action_info { action portlist opts } { platforms {", " ", " ","} variants {", " ", " ","} conflicts {", " ", " ","} + portgroups {", " ", " ","} subports {", " ", " ","} patchfiles {", " ", " ","} }] @@ -1774,6 +1780,7 @@ proc action_info { action portlist opts } { maintainers Maintainers license License conflicts "Conflicts with" + portgroups "Port Groups" replaced_by "Replaced by" subports "Sub-ports" patchfiles "Patchfiles" @@ -1797,6 +1804,7 @@ proc action_info { action portlist opts } { platforms 22 license 22 conflicts 22 + portgroups 22 maintainers 22 subports 22 patchfiles 22 @@ -1889,6 +1897,7 @@ proc action_info { action portlist opts } { ports_info_depends_lib ports_info_depends_run ports_info_depends_test ports_info_conflicts + ports_info_portgroups ports_info_platforms ports_info_license ports_info_maintainers } @@ -1948,6 +1957,15 @@ proc action_info { action portlist opts } { } } + # Format portgroups: strip filepath, keep only name and version + if {$ropt eq "portgroups"} { + set infresult [list] + foreach pg $inf { + lappend infresult [lrange $pg 0 1] + } + set inf $infresult + } + # Add "(" "or" ")" "and" for human-readable output if {$pretty_print && $ropt eq "license"} { set infresult [list] @@ -4276,6 +4294,7 @@ set cmd_opts_array [dict create {*}{ depends description epoch fullname heading homepage index license line long_description maintainer maintainers name patchfiles platform platforms portdir + portgroup portgroups pretty replaced_by revision subports variant variants version} contents {size {units 1}} deps {index no-build no-test} @@ -4286,7 +4305,8 @@ set cmd_opts_array [dict create {*}{ depends_build depends_lib depends_run depends_test depends description epoch exact glob homepage line long_description maintainer maintainers name platform - platforms portdir regex revision variant variants version} + platforms portdir portgroup portgroups + regex revision variant variants version} selfupdate {migrate no-sync nosync rsync} space {{units 1} total} activate {no-exec} diff --git a/src/port/portindex.tcl b/src/port/portindex.tcl index bdf6eb7e78..9703da623e 100644 --- a/src/port/portindex.tcl +++ b/src/port/portindex.tcl @@ -67,6 +67,15 @@ proc _index_from_portinfo {portinfo {is_subport no}} { dict set keep_portinfo subports [dict get $portinfo subports] } + # strip filepath from portgroups entries, keeping only {name version} + if {[dict exists $keep_portinfo portgroups]} { + set stripped [list] + foreach pg [dict get $keep_portinfo portgroups] { + lappend stripped [lrange $pg 0 1] + } + dict set keep_portinfo portgroups $stripped + } + set len [expr {[string length $keep_portinfo] + 1}] return [list [dict get $portinfo name] $len $keep_portinfo] } @@ -442,7 +451,7 @@ set keepkeys [dict create] foreach key {categories depends_fetch depends_extract depends_patch \ depends_build depends_lib depends_run depends_test \ description epoch homepage long_description maintainers \ - name platforms revision variants version portdir \ + name platforms portgroups revision variants version portdir \ replaced_by license installs_libs conflicts known_fail} { dict set keepkeys $key 1 }