internal/span: handle empty paths correctly

Change-Id: I3f411c5e27bcada26a756485a3b9de3514ac7955
Reviewed-on: https://go-review.googlesource.com/c/tools/+/181677
Run-TryBot: Ian Cottrell <iancottrell@google.com>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Ian Cottrell 2019-06-11 11:17:26 -04:00
parent ff694a2184
commit 25a4f13759
2 changed files with 46 additions and 18 deletions

View File

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"net/url" "net/url"
"os" "os"
"path"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
@ -30,6 +31,9 @@ func (uri URI) Filename() string {
} }
func filename(uri URI) (string, error) { func filename(uri URI) (string, error) {
if uri == "" {
return "", nil
}
u, err := url.ParseRequestURI(string(uri)) u, err := url.ParseRequestURI(string(uri))
if err != nil { if err != nil {
return "", err return "", err
@ -56,28 +60,49 @@ func NewURI(s string) URI {
} }
func CompareURI(a, b URI) int { func CompareURI(a, b URI) int {
if a == b { if equalURI(a, b) {
return 0 return 0
} }
if a < b {
return -1
}
return 1
}
func equalURI(a, b URI) bool {
if a == b {
return true
}
// If we have the same URI basename, we may still have the same file URIs. // If we have the same URI basename, we may still have the same file URIs.
fa := a.Filename() if !strings.EqualFold(path.Base(string(a)), path.Base(string(b))) {
fb := b.Filename() return false
if strings.EqualFold(filepath.Base(fa), filepath.Base(fb)) { }
fa, err := filename(a)
if err != nil {
return false
}
fb, err := filename(b)
if err != nil {
return false
}
// Stat the files to check if they are equal. // Stat the files to check if they are equal.
if infoa, err := os.Stat(fa); err == nil { infoa, err := os.Stat(filepath.FromSlash(fa))
if infob, err := os.Stat(fb); err == nil { if err != nil {
if os.SameFile(infoa, infob) { return false
return 0
} }
infob, err := os.Stat(filepath.FromSlash(fb))
if err != nil {
return false
} }
} return os.SameFile(infoa, infob)
}
return strings.Compare(fa, fb)
} }
// FileURI returns a span URI for the supplied file path. // FileURI returns a span URI for the supplied file path.
// It will always have the file scheme. // It will always have the file scheme.
func FileURI(path string) URI { func FileURI(path string) URI {
if path == "" {
return ""
}
// Handle standard library paths that contain the literal "$GOROOT". // Handle standard library paths that contain the literal "$GOROOT".
// TODO(rstambler): The go/packages API should allow one to determine a user's $GOROOT. // TODO(rstambler): The go/packages API should allow one to determine a user's $GOROOT.
const prefix = "$GOROOT" const prefix = "$GOROOT"

View File

@ -17,6 +17,7 @@ import (
// functions filepath.ToSlash and filepath.FromSlash do not need testing. // functions filepath.ToSlash and filepath.FromSlash do not need testing.
func TestURI(t *testing.T) { func TestURI(t *testing.T) {
for _, test := range []string{ for _, test := range []string{
``,
`C:/Windows/System32`, `C:/Windows/System32`,
`C:/Go/src/bob.go`, `C:/Go/src/bob.go`,
`c:/Go/src/bob.go`, `c:/Go/src/bob.go`,
@ -25,16 +26,18 @@ func TestURI(t *testing.T) {
} { } {
testPath := filepath.FromSlash(test) testPath := filepath.FromSlash(test)
expectPath := testPath expectPath := testPath
if test[0] == '/' { if len(test) > 0 && test[0] == '/' {
if abs, err := filepath.Abs(expectPath); err == nil { if abs, err := filepath.Abs(expectPath); err == nil {
expectPath = abs expectPath = abs
} }
} }
expectURI := filepath.ToSlash(expectPath) expectURI := filepath.ToSlash(expectPath)
if len(expectURI) > 0 {
if expectURI[0] != '/' { if expectURI[0] != '/' {
expectURI = "/" + expectURI expectURI = "/" + expectURI
} }
expectURI = "file://" + expectURI expectURI = "file://" + expectURI
}
uri := span.FileURI(testPath) uri := span.FileURI(testPath)
if expectURI != string(uri) { if expectURI != string(uri) {
t.Errorf("ToURI: expected %s, got %s", expectURI, uri) t.Errorf("ToURI: expected %s, got %s", expectURI, uri)