2014-09-15 01:17:29 +02:00
|
|
|
package module
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net/url"
|
2014-09-27 18:29:12 +02:00
|
|
|
"path/filepath"
|
2014-09-15 01:17:29 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// Detector defines the interface that an invalid URL or a URL with a blank
|
|
|
|
// scheme is passed through in order to determine if its shorthand for
|
|
|
|
// something else well-known.
|
|
|
|
type Detector interface {
|
|
|
|
// Detect will detect whether the string matches a known pattern to
|
|
|
|
// turn it into a proper URL.
|
|
|
|
Detect(string, string) (string, bool, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Detectors is the list of detectors that are tried on an invalid URL.
|
|
|
|
// This is also the order they're tried (index 0 is first).
|
|
|
|
var Detectors []Detector
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
Detectors = []Detector{
|
2014-09-16 19:52:08 +02:00
|
|
|
new(GitHubDetector),
|
2014-09-16 20:55:14 +02:00
|
|
|
new(BitBucketDetector),
|
2014-09-15 01:17:29 +02:00
|
|
|
new(FileDetector),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Detect turns a source string into another source string if it is
|
|
|
|
// detected to be of a known pattern.
|
|
|
|
//
|
|
|
|
// This is safe to be called with an already valid source string: Detect
|
|
|
|
// will just return it.
|
|
|
|
func Detect(src string, pwd string) (string, error) {
|
2014-09-16 08:48:56 +02:00
|
|
|
getForce, getSrc := getForcedGetter(src)
|
|
|
|
|
2014-09-27 18:29:12 +02:00
|
|
|
// Separate out the subdir if there is one, we don't pass that to detect
|
|
|
|
getSrc, subDir := getDirSubdir(getSrc)
|
|
|
|
|
2015-01-28 10:40:19 +01:00
|
|
|
u, err := urlParse(getSrc)
|
2014-09-15 01:17:29 +02:00
|
|
|
if err == nil && u.Scheme != "" {
|
|
|
|
// Valid URL
|
2015-01-28 10:40:19 +01:00
|
|
|
return u.String(), nil
|
2014-09-15 01:17:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, d := range Detectors {
|
2014-09-16 08:48:56 +02:00
|
|
|
result, ok, err := d.Detect(getSrc, pwd)
|
2014-09-15 01:17:29 +02:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2014-09-16 08:48:56 +02:00
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2014-09-16 19:54:23 +02:00
|
|
|
var detectForce string
|
|
|
|
detectForce, result = getForcedGetter(result)
|
2014-09-27 18:29:12 +02:00
|
|
|
result, detectSubdir := getDirSubdir(result)
|
|
|
|
|
|
|
|
// If we have a subdir from the detection, then prepend it to our
|
|
|
|
// requested subdir.
|
|
|
|
if detectSubdir != "" {
|
|
|
|
if subDir != "" {
|
|
|
|
subDir = filepath.Join(detectSubdir, subDir)
|
|
|
|
} else {
|
|
|
|
subDir = detectSubdir
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if subDir != "" {
|
|
|
|
u, err := url.Parse(result)
|
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("Error parsing URL: %s", err)
|
|
|
|
}
|
|
|
|
u.Path += "//" + subDir
|
|
|
|
result = u.String()
|
|
|
|
}
|
2014-09-16 19:54:23 +02:00
|
|
|
|
|
|
|
// Preserve the forced getter if it exists. We try to use the
|
|
|
|
// original set force first, followed by any force set by the
|
|
|
|
// detector.
|
2014-09-16 08:48:56 +02:00
|
|
|
if getForce != "" {
|
|
|
|
result = fmt.Sprintf("%s::%s", getForce, result)
|
2014-09-16 19:54:23 +02:00
|
|
|
} else if detectForce != "" {
|
|
|
|
result = fmt.Sprintf("%s::%s", detectForce, result)
|
2014-09-15 01:17:29 +02:00
|
|
|
}
|
2014-09-16 08:48:56 +02:00
|
|
|
|
|
|
|
return result, nil
|
2014-09-15 01:17:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return "", fmt.Errorf("invalid source string: %s", src)
|
|
|
|
}
|