github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libgit/submodule_file.go (about)

     1  // Copyright 2019 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  package libgit
     6  
     7  import (
     8  	"io"
     9  	"time"
    10  
    11  	"github.com/pkg/errors"
    12  	billy "gopkg.in/src-d/go-billy.v4"
    13  	"gopkg.in/src-d/go-git.v4/plumbing"
    14  )
    15  
    16  type submoduleFile struct {
    17  	name  string
    18  	mtime time.Time
    19  	data  []byte
    20  
    21  	// TODO: proper locking for `nextRead` if we ever use it outside
    22  	// of autogit (which always uses `ReadAt`).
    23  	nextRead int
    24  }
    25  
    26  const (
    27  	submodulePrefix = "git submodule at commit "
    28  )
    29  
    30  var _ billy.File = (*submoduleFile)(nil)
    31  
    32  func newSubmoduleFile(
    33  	h plumbing.Hash, name string, mtime time.Time) *submoduleFile {
    34  	data := []byte(submodulePrefix + h.String() + "\n")
    35  	return &submoduleFile{
    36  		name:  name,
    37  		mtime: mtime,
    38  		data:  data,
    39  	}
    40  }
    41  
    42  func (sf *submoduleFile) Len() int {
    43  	return len(sf.data)
    44  }
    45  
    46  func (sf *submoduleFile) Name() string {
    47  	return sf.name
    48  }
    49  
    50  func (sf *submoduleFile) Write(_ []byte) (n int, err error) {
    51  	return 0, errors.New("diff files can't be written")
    52  }
    53  
    54  func (sf *submoduleFile) Read(p []byte) (n int, err error) {
    55  	if sf.nextRead >= sf.Len() {
    56  		return 0, io.EOF
    57  	}
    58  	n = copy(p, sf.data[sf.nextRead:])
    59  	sf.nextRead += n
    60  	return n, nil
    61  }
    62  
    63  func (sf *submoduleFile) ReadAt(p []byte, off int64) (n int, err error) {
    64  	if off >= int64(sf.Len()) {
    65  		return 0, io.EOF
    66  	}
    67  
    68  	n = copy(p, sf.data[off:])
    69  	return n, nil
    70  }
    71  
    72  func (sf *submoduleFile) Seek(offset int64, whence int) (int64, error) {
    73  	newOffset := offset
    74  	switch whence {
    75  	case io.SeekStart:
    76  	case io.SeekCurrent:
    77  		newOffset = int64(sf.nextRead) + offset
    78  	case io.SeekEnd:
    79  		newOffset = int64(sf.Len()) + offset
    80  	}
    81  	if newOffset < 0 {
    82  		return 0, errors.Errorf("Cannot seek to offset %d", newOffset)
    83  	}
    84  
    85  	sf.nextRead = int(newOffset)
    86  	return newOffset, nil
    87  }
    88  
    89  func (sf *submoduleFile) Close() error {
    90  	return nil
    91  }
    92  
    93  func (sf *submoduleFile) Lock() error {
    94  	return errors.New("diff files can't be locked")
    95  }
    96  
    97  func (sf *submoduleFile) Unlock() error {
    98  	return errors.New("diff files can't be unlocked")
    99  }
   100  
   101  func (sf *submoduleFile) Truncate(size int64) error {
   102  	return errors.New("diff files can't be truncated")
   103  }
   104  
   105  func (sf *submoduleFile) GetInfo() *submoduleFileInfo {
   106  	return &submoduleFileInfo{
   107  		name:  sf.Name(),
   108  		size:  int64(sf.Len()),
   109  		mtime: sf.mtime,
   110  		sf:    sf,
   111  	}
   112  }