go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cipkg/core/derivations.go (about) 1 // Copyright 2023 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package core 16 17 import ( 18 "crypto/sha256" 19 "encoding/base32" 20 "hash" 21 "strings" 22 23 "go.chromium.org/luci/common/proto" 24 ) 25 26 // GetDerivationID calculates a unique ID from derivation's content and can 27 // represent its corresponding output content. The DerivationID is safe for 28 // filesystem path and other common applications. 29 func GetDerivationID(drv *Derivation) (string, error) { 30 h := sha256.New() 31 if err := hashDerivation(h, drv); err != nil { 32 return "", err 33 } 34 35 // - "name-hash" for usual derivations. 36 // - "name+hash" for derivations with fixed output. 37 infix := "-" 38 if drv.FixedOutput != "" { 39 infix = "+" 40 } 41 42 // We want to keep the hash as short as possible to avoid reaching the path 43 // length limit on windows. 44 // Using base32 instead of base64 because filesystem is not promised to be 45 // case-sensitive. 46 enc := base32.HexEncoding.WithPadding(base32.NoPadding) 47 return drv.Name + infix + strings.ToLower(enc.EncodeToString(h.Sum(nil)[:16])), nil 48 } 49 50 func hashDerivation(h hash.Hash, drv *Derivation) error { 51 if len(drv.FixedOutput) != 0 { 52 _, err := h.Write([]byte(drv.FixedOutput)) 53 return err 54 } 55 return proto.StableHash(h, drv) 56 }