github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/lfs/filesystem_client.go (about) 1 // Copyright 2023 The GitBundle Inc. All rights reserved. 2 // Copyright 2017 The Gitea Authors. All rights reserved. 3 // Use of this source code is governed by a MIT-style 4 // license that can be found in the LICENSE file. 5 6 package lfs 7 8 import ( 9 "context" 10 "io" 11 "net/url" 12 "os" 13 "path/filepath" 14 15 "github.com/gitbundle/modules/util" 16 ) 17 18 // FilesystemClient is used to read LFS data from a filesystem path 19 type FilesystemClient struct { 20 lfsdir string 21 } 22 23 // BatchSize returns the preferred size of batchs to process 24 func (c *FilesystemClient) BatchSize() int { 25 return 1 26 } 27 28 func newFilesystemClient(endpoint *url.URL) *FilesystemClient { 29 path, _ := util.FileURLToPath(endpoint) 30 31 lfsdir := filepath.Join(path, "lfs", "objects") 32 33 client := &FilesystemClient{lfsdir} 34 35 return client 36 } 37 38 func (c *FilesystemClient) objectPath(oid string) string { 39 return filepath.Join(c.lfsdir, oid[0:2], oid[2:4], oid) 40 } 41 42 // Download reads the specific LFS object from the target path 43 func (c *FilesystemClient) Download(ctx context.Context, objects []Pointer, callback DownloadCallback) error { 44 for _, object := range objects { 45 p := Pointer{object.Oid, object.Size} 46 47 objectPath := c.objectPath(p.Oid) 48 49 f, err := os.Open(objectPath) 50 if err != nil { 51 return err 52 } 53 54 if err := callback(p, f, nil); err != nil { 55 return err 56 } 57 } 58 return nil 59 } 60 61 // Upload writes the specific LFS object to the target path 62 func (c *FilesystemClient) Upload(ctx context.Context, objects []Pointer, callback UploadCallback) error { 63 for _, object := range objects { 64 p := Pointer{object.Oid, object.Size} 65 66 objectPath := c.objectPath(p.Oid) 67 68 if err := os.MkdirAll(filepath.Dir(objectPath), os.ModePerm); err != nil { 69 return err 70 } 71 72 content, err := callback(p, nil) 73 if err != nil { 74 return err 75 } 76 77 err = func() error { 78 defer content.Close() 79 80 f, err := os.Create(objectPath) 81 if err != nil { 82 return err 83 } 84 85 _, err = io.Copy(f, content) 86 87 return err 88 }() 89 if err != nil { 90 return err 91 } 92 } 93 return nil 94 }