github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/local/index.go (about) 1 package local 2 3 import ( 4 "errors" 5 "fmt" 6 "io/fs" 7 "os" 8 "path/filepath" 9 "strings" 10 11 "github.com/treeverse/lakefs/pkg/fileutil" 12 "github.com/treeverse/lakefs/pkg/uri" 13 "gopkg.in/yaml.v3" 14 ) 15 16 const ( 17 IndexFileName = ".lakefs_ref.yaml" 18 IgnoreMarker = "ignored by lakectl local" 19 IndexFileMode = 0o644 20 ) 21 22 // Index defines the structure of the lakefs local reference file 23 // consisting of the information linking local directory with lakefs path 24 type Index struct { 25 root string `yaml:"-"` 26 PathURI string `yaml:"src"` 27 AtHead string `yaml:"at_head"` 28 ActiveOperation string `yaml:"active_operation"` 29 } 30 31 func (l *Index) LocalPath() string { 32 return l.root 33 } 34 35 func (l *Index) GetCurrentURI() (*uri.URI, error) { 36 return uri.Parse(l.PathURI) 37 } 38 39 func WriteIndex(path string, remote *uri.URI, atHead string, operation string) (*Index, error) { 40 idx := &Index{ 41 PathURI: remote.String(), 42 AtHead: atHead, 43 ActiveOperation: operation, 44 } 45 data, err := yaml.Marshal(idx) 46 if err != nil { 47 return nil, err 48 } 49 idxPath := filepath.Join(path, IndexFileName) 50 return idx, os.WriteFile(idxPath, data, IndexFileMode) 51 } 52 53 func IndexExists(baseAbs string) (bool, error) { 54 refPath := filepath.Join(baseAbs, IndexFileName) 55 _, err := os.Stat(refPath) 56 switch { 57 case err == nil: 58 return true, nil 59 case errors.Is(err, os.ErrNotExist): 60 return false, nil 61 default: 62 return false, err 63 } 64 } 65 66 func ReadIndex(path string) (*Index, error) { 67 idxPath, err := fileutil.FindInParents(path, IndexFileName) 68 if err != nil { 69 return nil, err 70 } 71 if idxPath == "" { 72 return nil, fmt.Errorf("could not find lakefs reference file in path %s or parents: %w", path, fs.ErrNotExist) 73 } 74 data, err := os.ReadFile(idxPath) 75 if err != nil { 76 return nil, err 77 } 78 idx := &Index{ 79 root: filepath.Dir(idxPath), 80 } 81 err = yaml.Unmarshal(data, idx) 82 if err != nil { 83 return nil, err 84 } 85 return idx, nil 86 } 87 88 // FindIndices searches the specified root directory for index files, returning their relative directory paths while skipping hidden folders. 89 func FindIndices(root string) ([]string, error) { 90 locs := make([]string, 0) 91 err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error { 92 if err != nil { 93 return err 94 } 95 // don't traverse hidden folders like '.git', etc. 96 if d.IsDir() && strings.HasPrefix(d.Name(), ".") { 97 return filepath.SkipDir 98 } 99 // if we found an index, no need to further traverse 100 if filepath.Base(path) == IndexFileName { 101 // add the relative location of the directory containing the index 102 rel, err := filepath.Rel(root, filepath.Dir(path)) 103 if err != nil { 104 return err 105 } 106 locs = append(locs, rel) 107 return filepath.SkipDir // no need to traverse further! 108 } 109 return nil 110 }) 111 if err != nil { 112 return nil, err 113 } 114 return locs, nil 115 }