| // 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 | |
| } |