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