code.gitea.io/gitea@v1.19.3/modules/lfs/filesystem_client.go (about)

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