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 }