github.com/driusan/dgit@v0.0.0-20221118233547-f39f0c15edbb/git/hashobject.go (about) 1 package git 2 3 import ( 4 "bytes" 5 "crypto/sha1" 6 "fmt" 7 "io" 8 "io/ioutil" 9 "os" 10 "strings" 11 ) 12 13 func HashReaderWithSize(t string, sz int64, r io.Reader) (Sha1, error) { 14 h := sha1.New() 15 fmt.Fprintf(h, "%s %d\000", t, sz) 16 17 if sz < 0 { 18 return Sha1{}, fmt.Errorf("Invalid size: %v", sz) 19 } 20 n, err := io.Copy(h, r) 21 if err != nil { 22 return Sha1{}, err 23 } 24 if n != sz { 25 return Sha1{}, fmt.Errorf("Unexpected reader size (got %v != want %v)", n, sz) 26 } 27 return Sha1FromSlice(h.Sum(nil)) 28 } 29 30 // Hashes the data of r with object type t, and returns 31 // the hash, and the data that was read from r. 32 func HashReader(t string, r io.Reader) (Sha1, []byte, error) { 33 // Need to read the whole reader in order to find the size 34 data, err := ioutil.ReadAll(r) 35 if err != nil { 36 return Sha1{}, nil, err 37 } 38 39 h := sha1.New() 40 fmt.Fprintf(h, "%s %d\000%s", t, len(data), data) 41 s, err := Sha1FromSlice(h.Sum(nil)) 42 return s, data, err 43 } 44 45 func HashSlice(t string, data []byte) (Sha1, []byte, error) { 46 r := bytes.NewReader(data) 47 return HashReader(t, r) 48 } 49 50 func HashFile(t, filename string) (Sha1, []byte, error) { 51 if File(filename).IsSymlink() { 52 l, err := os.Readlink(filename) 53 if err != nil { 54 return Sha1{}, nil, err 55 } 56 return HashReader(t, strings.NewReader(l)) 57 } else { 58 r, err := os.Open(filename) 59 if err != nil { 60 return Sha1{}, nil, err 61 } 62 defer r.Close() 63 return HashReader(t, r) 64 } 65 }