github.com/weiwenhao/getter@v1.30.1/source.go (about) 1 package getter 2 3 import ( 4 "fmt" 5 "path/filepath" 6 "strings" 7 ) 8 9 // SourceDirSubdir takes a source URL and returns a tuple of the URL without 10 // the subdir and the subdir. 11 // 12 // ex: 13 // dom.com/path/?q=p => dom.com/path/?q=p, "" 14 // proto://dom.com/path//*?q=p => proto://dom.com/path?q=p, "*" 15 // proto://dom.com/path//path2?q=p => proto://dom.com/path?q=p, "path2" 16 // 17 func SourceDirSubdir(src string) (string, string) { 18 19 // URL might contains another url in query parameters 20 stop := len(src) 21 if idx := strings.Index(src, "?"); idx > -1 { 22 stop = idx 23 } 24 25 // Calculate an offset to avoid accidentally marking the scheme 26 // as the dir. 27 var offset int 28 if idx := strings.Index(src[:stop], "://"); idx > -1 { 29 offset = idx + 3 30 } 31 32 // First see if we even have an explicit subdir 33 idx := strings.Index(src[offset:stop], "//") 34 if idx == -1 { 35 return src, "" 36 } 37 38 idx += offset 39 subdir := src[idx+2:] 40 src = src[:idx] 41 42 // Next, check if we have query parameters and push them onto the 43 // URL. 44 if idx = strings.Index(subdir, "?"); idx > -1 { 45 query := subdir[idx:] 46 subdir = subdir[:idx] 47 src += query 48 } 49 50 return src, subdir 51 } 52 53 // SubdirGlob returns the actual subdir with globbing processed. 54 // 55 // dst should be a destination directory that is already populated (the 56 // download is complete) and subDir should be the set subDir. If subDir 57 // is an empty string, this returns an empty string. 58 // 59 // The returned path is the full absolute path. 60 func SubdirGlob(dst, subDir string) (string, error) { 61 matches, err := filepath.Glob(filepath.Join(dst, subDir)) 62 if err != nil { 63 return "", err 64 } 65 66 if len(matches) == 0 { 67 return "", fmt.Errorf("subdir %q not found", subDir) 68 } 69 70 if len(matches) > 1 { 71 return "", fmt.Errorf("subdir %q matches multiple paths", subDir) 72 } 73 74 return matches[0], nil 75 }