github.com/Benchkram/bob@v0.0.0-20220321080157-7c8f3876e225/bobtask/hash_in.go (about) 1 package bobtask 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "errors" 7 "fmt" 8 "os" 9 "sort" 10 "strings" 11 12 "github.com/Benchkram/bob/bobtask/hash" 13 "github.com/Benchkram/bob/pkg/filehash" 14 "gopkg.in/yaml.v2" 15 ) 16 17 // HashIn computes a hash containing inputs, environment and the task description. 18 func (t *Task) HashIn() (taskHash hash.In, _ error) { 19 if t.hashIn != nil { 20 return *t.hashIn, nil 21 } 22 23 aggregatedHashes := bytes.NewBuffer([]byte{}) 24 25 // Hash input files 26 for _, f := range t.inputs { 27 h, err := filehash.Hash(f) 28 if err != nil { 29 if errors.Is(err, os.ErrPermission) { 30 t.addToSkippedInputs(f) 31 continue 32 } else { 33 return taskHash, fmt.Errorf("failed to hash file %q: %w", f, err) 34 } 35 } 36 37 _, err = aggregatedHashes.Write(h) 38 if err != nil { 39 return taskHash, fmt.Errorf("failed to write file hash to aggregated hash %q: %w", f, err) 40 } 41 } 42 43 // Hash the public task description 44 description, err := yaml.Marshal(t) 45 if err != nil { 46 return taskHash, fmt.Errorf("failed to marshal task: %w", err) 47 } 48 descriptionHash, err := filehash.HashBytes(bytes.NewBuffer(description)) 49 if err != nil { 50 return taskHash, fmt.Errorf("failed to write description hash: %w", err) 51 } 52 _, err = aggregatedHashes.Write(descriptionHash) 53 if err != nil { 54 return taskHash, fmt.Errorf("failed to write task description to aggregated hash: %w", err) 55 } 56 57 // Hash the environment 58 sort.Strings(t.env) 59 environment := strings.Join(t.env, ",") 60 environmentHash, err := filehash.HashBytes(bytes.NewBufferString(environment)) 61 if err != nil { 62 return taskHash, fmt.Errorf("failed to write description hash: %w", err) 63 } 64 _, err = aggregatedHashes.Write(environmentHash) 65 if err != nil { 66 return taskHash, fmt.Errorf("failed to write task environment to aggregated hash: %w", err) 67 } 68 69 // Summarize 70 h, err := filehash.HashBytes(aggregatedHashes) 71 if err != nil { 72 return taskHash, fmt.Errorf("failed to write aggregated hash: %w", err) 73 } 74 75 hashIn := hash.In(hex.EncodeToString(h)) 76 77 // store hash for reuse 78 t.hashIn = &hashIn 79 80 return hashIn, nil 81 }