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  }