fetch.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package manifest
  2. import (
  3. "fmt"
  4. "net/http"
  5. "net/url"
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. )
  10. func validateTagName(man *Manifest2822, repoName, tagName string) error {
  11. if tagName != "" && (man.GetTag(tagName) == nil && len(man.GetSharedTag(tagName)) == 0) {
  12. return fmt.Errorf("tag not found in manifest for %q: %q", repoName, tagName)
  13. }
  14. return nil
  15. }
  16. // "library" is the default "library directory"
  17. // returns the parsed version of (in order):
  18. // if "repo" is a URL, the remote contents of that URL
  19. // if "repo" is a relative path like "./repo", that file
  20. // the file "library/repo"
  21. // (repoName, tagName, man, err)
  22. func Fetch(library, repo string) (string, string, *Manifest2822, error) {
  23. repoName := filepath.Base(repo)
  24. tagName := ""
  25. if tagIndex := strings.IndexRune(repoName, ':'); tagIndex > 0 {
  26. tagName = repoName[tagIndex+1:]
  27. repoName = repoName[:tagIndex]
  28. repo = strings.TrimSuffix(repo, ":"+tagName)
  29. }
  30. u, err := url.Parse(repo)
  31. if err == nil && u.IsAbs() && (u.Scheme == "http" || u.Scheme == "https") {
  32. // must be remote URL!
  33. resp, err := http.Get(repo)
  34. if err != nil {
  35. return repoName, tagName, nil, err
  36. }
  37. defer resp.Body.Close()
  38. man, err := Parse(resp.Body)
  39. if err != nil {
  40. return repoName, tagName, man, err
  41. }
  42. return repoName, tagName, man, validateTagName(man, repoName, tagName)
  43. }
  44. // try file paths
  45. filePaths := []string{}
  46. if filepath.IsAbs(repo) || strings.IndexRune(repo, filepath.Separator) >= 0 || strings.IndexRune(repo, '/') >= 0 {
  47. filePaths = append(filePaths, repo)
  48. }
  49. if !filepath.IsAbs(repo) {
  50. filePaths = append(filePaths, filepath.Join(library, repo))
  51. }
  52. for _, fileName := range filePaths {
  53. f, err := os.Open(fileName)
  54. if err != nil && !os.IsNotExist(err) {
  55. return repoName, tagName, nil, err
  56. }
  57. if err == nil {
  58. defer f.Close()
  59. man, err := Parse(f)
  60. if err != nil {
  61. return repoName, tagName, man, err
  62. }
  63. return repoName, tagName, man, validateTagName(man, repoName, tagName)
  64. }
  65. }
  66. return repoName, tagName, nil, fmt.Errorf("unable to find a manifest named %q (in %q or as a remote URL)", repo, library)
  67. }