// fixManifestLayers removes repeated layers from the manifest and checks the // correctness of the parent chain. func fixManifestLayers(m *manifest.Manifest) error { images := make([]*image.Image, len(m.FSLayers)) for i := range m.FSLayers { img, err := image.NewImgJSON([]byte(m.History[i].V1Compatibility)) if err != nil { return err } images[i] = img if err := image.ValidateID(img.ID); err != nil { return err } } if images[len(images)-1].Parent != "" { return errors.New("Invalid parent ID in the base layer of the image.") } // check general duplicates to error instead of a deadlock idmap := make(map[string]struct{}) var lastID string for _, img := range images { // skip IDs that appear after each other, we handle those later if _, exists := idmap[img.ID]; img.ID != lastID && exists { return fmt.Errorf("ID %+v appears multiple times in manifest", img.ID) } lastID = img.ID idmap[lastID] = struct{}{} } // backwards loop so that we keep the remaining indexes after removing items for i := len(images) - 2; i >= 0; i-- { if images[i].ID == images[i+1].ID { // repeated ID. remove and continue m.FSLayers = append(m.FSLayers[:i], m.FSLayers[i+1:]...) m.History = append(m.History[:i], m.History[i+1:]...) } else if images[i].Parent != images[i+1].ID { return fmt.Errorf("Invalid parent ID. Expected %v, got %v.", images[i+1].ID, images[i].Parent) } } return nil }