| package getter |
| |
| import ( |
| "fmt" |
| "os" |
| "path/filepath" |
| "runtime" |
| ) |
| |
| // FileDetector implements Detector to detect file paths. |
| type FileDetector struct{} |
| |
| func (d *FileDetector) Detect(src, pwd string) (string, bool, error) { |
| if len(src) == 0 { |
| return "", false, nil |
| } |
| |
| if !filepath.IsAbs(src) { |
| if pwd == "" { |
| return "", true, fmt.Errorf( |
| "relative paths require a module with a pwd") |
| } |
| |
| // Stat the pwd to determine if its a symbolic link. If it is, |
| // then the pwd becomes the original directory. Otherwise, |
| // `filepath.Join` below does some weird stuff. |
| // |
| // We just ignore if the pwd doesn't exist. That error will be |
| // caught later when we try to use the URL. |
| if fi, err := os.Lstat(pwd); !os.IsNotExist(err) { |
| if err != nil { |
| return "", true, err |
| } |
| if fi.Mode()&os.ModeSymlink != 0 { |
| pwd, err = filepath.EvalSymlinks(pwd) |
| if err != nil { |
| return "", true, err |
| } |
| |
| // The symlink itself might be a relative path, so we have to |
| // resolve this to have a correctly rooted URL. |
| pwd, err = filepath.Abs(pwd) |
| if err != nil { |
| return "", true, err |
| } |
| } |
| } |
| |
| src = filepath.Join(pwd, src) |
| } |
| |
| return fmtFileURL(src), true, nil |
| } |
| |
| func fmtFileURL(path string) string { |
| if runtime.GOOS == "windows" { |
| // Make sure we're using "/" on Windows. URLs are "/"-based. |
| path = filepath.ToSlash(path) |
| return fmt.Sprintf("file://%s", path) |
| } |
| |
| // Make sure that we don't start with "/" since we add that below. |
| if path[0] == '/' { |
| path = path[1:] |
| } |
| return fmt.Sprintf("file:///%s", path) |
| } |