github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/gateway/path/resolver.go (about) 1 package path 2 3 import ( 4 "errors" 5 "fmt" 6 "regexp" 7 "strings" 8 9 "github.com/treeverse/lakefs/pkg/graveler" 10 11 "github.com/treeverse/lakefs/pkg/block" 12 ) 13 14 const ( 15 Separator = "/" 16 17 rePath = "(?P<path>.*)" 18 reReference = `(?P<ref>[^/]+)` 19 ) 20 21 var ( 22 EncodedPathRe = regexp.MustCompile(fmt.Sprintf("^/?%s/%s", reReference, rePath)) 23 EncodedPathReferenceRe = regexp.MustCompile(fmt.Sprintf("^/?%s$", reReference)) 24 25 ErrPathMalformed = errors.New("encoded path is malformed") 26 ) 27 28 type Ref struct { 29 Branch string 30 CommitID graveler.CommitID 31 } 32 33 type ResolvedPath struct { 34 Ref string 35 Path string 36 WithPath bool 37 } 38 39 type ResolvedAbsolutePath struct { 40 Repo string 41 Reference string 42 Path string 43 } 44 45 func ResolveAbsolutePath(encodedPath string) (ResolvedAbsolutePath, error) { 46 const encodedPartsCount = 3 47 encodedPath = strings.TrimLeft(encodedPath, "/") 48 parts := strings.SplitN(encodedPath, "/", encodedPartsCount) 49 if len(parts) != encodedPartsCount { 50 return ResolvedAbsolutePath{}, ErrPathMalformed 51 } 52 return ResolvedAbsolutePath{ 53 Repo: parts[0], 54 Reference: parts[1], 55 Path: parts[2], 56 }, nil 57 } 58 59 func ResolvePath(encodedPath string) (ResolvedPath, error) { 60 r := ResolvedPath{} 61 if len(encodedPath) == 0 { 62 return r, nil // empty path. 63 } 64 // try reference with path or just reference regexp 65 for _, re := range []*regexp.Regexp{EncodedPathRe, EncodedPathReferenceRe} { 66 match := re.FindStringSubmatch(encodedPath) 67 if len(match) == 0 { 68 continue 69 } 70 for i, name := range re.SubexpNames() { 71 switch name { 72 case "ref": 73 r.Ref = match[i] 74 case "path": 75 r.Path = match[i] 76 r.WithPath = true 77 } 78 } 79 return r, nil 80 } 81 return r, ErrPathMalformed 82 } 83 84 func WithRef(path, ref string) string { 85 return block.JoinPathParts([]string{ref, path}) 86 }