// Copyright 2016 The Linux Foundation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package identity provides implementations of subtle calculations pertaining // to image and layer identity. The primary item present here is the ChainID // calculation used in identifying the result of subsequent layer applications. // // Helpers are also provided here to ease transition to the // github.com/opencontainers/go-digest package, but that package may be used // directly. package identity import "github.com/opencontainers/go-digest" // ChainID takes a slice of digests and returns the ChainID corresponding to // the last entry. Typically, these are a list of layer DiffIDs, with the // result providing the ChainID identifying the result of sequential // application of the preceding layers. func ChainID(dgsts []digest.Digest) digest.Digest { chainIDs := make([]digest.Digest, len(dgsts)) copy(chainIDs, dgsts) ChainIDs(chainIDs) if len(chainIDs) == 0 { return "" } return chainIDs[len(chainIDs)-1] } // ChainIDs calculates the recursively applied chain id for each identifier in // the slice. The result is written direcly back into the slice such that the // ChainID for each item will be in the respective position. // // By definition of ChainID, the zeroth element will always be the same before // and after the call. // // As an example, given the chain of ids `[A, B, C]`, the result `[A, // ChainID(A|B), ChainID(A|B|C)]` will be written back to the slice. // // The input is provided as a return value for convenience. // // Typically, these are a list of layer DiffIDs, with the // result providing the ChainID for each the result of each layer application // sequentially. func ChainIDs(dgsts []digest.Digest) []digest.Digest { if len(dgsts) < 2 { return dgsts } parent := digest.FromBytes([]byte(dgsts[0] + " " + dgsts[1])) next := dgsts[1:] next[0] = parent ChainIDs(next) return dgsts }