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  }