Skip to content

Commit

Permalink
cmd/go: make net/... match net too
Browse files Browse the repository at this point in the history
Otherwise there's no good way to get both, and it comes up often.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5794064
  • Loading branch information
rsc committed Mar 12, 2012
1 parent 0af08d8 commit b70925d
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 21 deletions.
5 changes: 2 additions & 3 deletions src/cmd/go/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,9 +508,8 @@ An import path is a pattern if it includes one or more "..." wildcards,
each of which can match any string, including the empty string and
strings containing slashes. Such a pattern expands to all package
directories found in the GOPATH trees with names matching the
patterns. For example, encoding/... expands to all packages
in subdirectories of the encoding tree, while net... expands to
net and all its subdirectories.
patterns. As a special case, x/... matches x as well as x's subdirectories.
For example, net/... expands to net and packages in its subdirectories.
An import path can also name a package to be downloaded from
a remote repository. Run 'go help remote' for details.
Expand Down
5 changes: 2 additions & 3 deletions src/cmd/go/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ An import path is a pattern if it includes one or more "..." wildcards,
each of which can match any string, including the empty string and
strings containing slashes. Such a pattern expands to all package
directories found in the GOPATH trees with names matching the
patterns. For example, encoding/... expands to all packages
in subdirectories of the encoding tree, while net... expands to
net and all its subdirectories.
patterns. As a special case, x/... matches x as well as x's subdirectories.
For example, net/... expands to net and packages in its subdirectories.
An import path can also name a package to be downloaded from
a remote repository. Run 'go help remote' for details.
Expand Down
56 changes: 41 additions & 15 deletions src/cmd/go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,9 @@ func help(args []string) {
os.Exit(2) // failed at 'go help cmd'
}

// importPaths returns the import paths to use for the given command line.
func importPaths(args []string) []string {
// importPathsNoDotExpansion returns the import paths to use for the given
// command line, but it does no ... expansion.
func importPathsNoDotExpansion(args []string) []string {
if len(args) == 0 {
return []string{"."}
}
Expand All @@ -270,13 +271,26 @@ func importPaths(args []string) []string {
} else {
a = path.Clean(a)
}

if build.IsLocalImport(a) && strings.Contains(a, "...") {
out = append(out, allPackagesInFS(a)...)
if a == "all" || a == "std" {
out = append(out, allPackages(a)...)
continue
}
if a == "all" || a == "std" || strings.Contains(a, "...") {
out = append(out, allPackages(a)...)
out = append(out, a)
}
return out
}

// importPaths returns the import paths to use for the given command line.
func importPaths(args []string) []string {
args = importPathsNoDotExpansion(args)
var out []string
for _, a := range args {
if strings.Contains(a, "...") {
if build.IsLocalImport(a) {
out = append(out, allPackagesInFS(a)...)
} else {
out = append(out, allPackages(a)...)
}
continue
}
out = append(out, a)
Expand Down Expand Up @@ -345,6 +359,10 @@ func runOut(dir string, cmdargs ...interface{}) []byte {
func matchPattern(pattern string) func(name string) bool {
re := regexp.QuoteMeta(pattern)
re = strings.Replace(re, `\.\.\.`, `.*`, -1)
// Special case: foo/... matches foo too.
if strings.HasSuffix(re, `/.*`) {
re = re[:len(re)-len(`/.*`)] + `(/.*)?`
}
reg := regexp.MustCompile(`^` + re + `$`)
return func(name string) bool {
return reg.MatchString(name)
Expand All @@ -356,6 +374,14 @@ func matchPattern(pattern string) func(name string) bool {
// The pattern is either "all" (all packages), "std" (standard packages)
// or a path including "...".
func allPackages(pattern string) []string {
pkgs := matchPackages(pattern)
if len(pkgs) == 0 {
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
}
return pkgs
}

func matchPackages(pattern string) []string {
match := func(string) bool { return true }
if pattern != "all" && pattern != "std" {
match = matchPattern(pattern)
Expand Down Expand Up @@ -432,17 +458,21 @@ func allPackages(pattern string) []string {
return nil
})
}

if len(pkgs) == 0 {
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
}
return pkgs
}

// allPackagesInFS is like allPackages but is passed a pattern
// beginning ./ or ../, meaning it should scan the tree rooted
// at the given directory. There are ... in the pattern too.
func allPackagesInFS(pattern string) []string {
pkgs := matchPackagesInFS(pattern)
if len(pkgs) == 0 {
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
}
return pkgs
}

func matchPackagesInFS(pattern string) []string {
// Find directory to begin the scan.
// Could be smarter but this one optimization
// is enough for now, since ... is usually at the
Expand Down Expand Up @@ -482,10 +512,6 @@ func allPackagesInFS(pattern string) []string {
pkgs = append(pkgs, name)
return nil
})

if len(pkgs) == 0 {
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
}
return pkgs
}

Expand Down
36 changes: 36 additions & 0 deletions src/cmd/go/match_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import "testing"

var matchTests = []struct {
pattern string
path string
match bool
}{
{"...", "foo", true},
{"net", "net", true},
{"net", "net/http", false},
{"net/http", "net", false},
{"net/http", "net/http", true},
{"net...", "netchan", true},
{"net...", "net", true},
{"net...", "net/http", true},
{"net...", "not/http", false},
{"net/...", "netchan", false},
{"net/...", "net", true},
{"net/...", "net/http", true},
{"net/...", "not/http", false},
}

func TestMatchPattern(t *testing.T) {
for _, tt := range matchTests {
match := matchPattern(tt.pattern)(tt.path)
if match != tt.match {
t.Errorf("matchPattern(%q)(%q) = %v, want %v", tt.pattern, tt.path, match, tt.match)
}
}
}

0 comments on commit b70925d

Please sign in to comment.