func (m *Schema1) fixManifestLayers() error {
	// m.initialize() has verified that len(m.FSLayers) == len(m.History)
	for _, compat := range m.ExtractedV1Compatibility {
		if err := validateV1ID(compat.ID); err != nil {
			return err
		}
	}
	if m.ExtractedV1Compatibility[len(m.ExtractedV1Compatibility)-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 m.ExtractedV1Compatibility {
		// skip IDs that appear after each other, we handle those later
		if _, exists := idmap[img.ID]; img.ID != lastID && exists {
			return errors.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(m.ExtractedV1Compatibility) - 2; i >= 0; i-- {
		if m.ExtractedV1Compatibility[i].ID == m.ExtractedV1Compatibility[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:]...)
			m.ExtractedV1Compatibility = append(m.ExtractedV1Compatibility[:i], m.ExtractedV1Compatibility[i+1:]...)
		} else if m.ExtractedV1Compatibility[i].Parent != m.ExtractedV1Compatibility[i+1].ID {
			return errors.Errorf("Invalid parent ID. Expected %v, got %v", m.ExtractedV1Compatibility[i+1].ID, m.ExtractedV1Compatibility[i].Parent)
		}
	}
	return nil
}
func (m *Schema1) fixManifestLayers() error {
	
	for _, compat := range m.ExtractedV1Compatibility {
		if err := validateV1ID(compat.ID); err != nil {
			return err
		}
	}
	if m.ExtractedV1Compatibility[len(m.ExtractedV1Compatibility)-1].Parent != "" {
		return errors.New("Invalid parent ID in the base layer of the image")
	}
	
	idmap := make(map[string]struct{})
	var lastID string
	for _, img := range m.ExtractedV1Compatibility {
		
		if _, exists := idmap[img.ID]; img.ID != lastID && exists {
			return errors.Errorf("ID %+v appears multiple times in manifest", img.ID)
		}
		lastID = img.ID
		idmap[lastID] = struct{}{}
	}
	
	for i := len(m.ExtractedV1Compatibility) - 2; i >= 0; i-- {
		if m.ExtractedV1Compatibility[i].ID == m.ExtractedV1Compatibility[i+1].ID { 
			m.FSLayers = append(m.FSLayers[:i], m.FSLayers[i+1:]...)
			m.History = append(m.History[:i], m.History[i+1:]...)
			m.ExtractedV1Compatibility = append(m.ExtractedV1Compatibility[:i], m.ExtractedV1Compatibility[i+1:]...)
		} else if m.ExtractedV1Compatibility[i].Parent != m.ExtractedV1Compatibility[i+1].ID {
			return errors.Errorf("Invalid parent ID. Expected %v, got %v", m.ExtractedV1Compatibility[i+1].ID, m.ExtractedV1Compatibility[i].Parent)
		}
	}
	return nil
}
func ( m * Schema1 ) fixManifestLayers ( ) error { // m.initialize() has verified that len(m.FSLayers) == len(m.History) for _ , compat := range m . ExtractedV1Compatibility { if err := validateV1ID ( compat . ID ) ; err != nil { return err } } if m . ExtractedV1Compatibility [ len ( m . ExtractedV1Compatibility ) - 1 ] . Parent != " " { return errors . New ( " " ) } // check general duplicates to error instead of a deadlock idmap := make ( map [ string ] struct { } ) var lastID string for _ , img := range m . ExtractedV1Compatibility { // skip IDs that appear after each other, we handle those later if _ , exists := idmap [ img . ID ] ; img . ID != lastID && exists { return errors . Errorf ( " " , img . ID ) } lastID = img . ID idmap [ lastID ] = struct { } { } } // backwards loop so that we keep the remaining indexes after removing items for i := len ( m . ExtractedV1Compatibility ) - 2 ; i >= 0 ; i -- { if m . ExtractedV1Compatibility [ i ] . ID == m . ExtractedV1Compatibility [ 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 : ] ... ) m . ExtractedV1Compatibility = append ( m . ExtractedV1Compatibility [ : i ] , m . ExtractedV1Compatibility [ i + 1 : ] ... ) } else if m . ExtractedV1Compatibility [ i ] . Parent != m . ExtractedV1Compatibility [ i + 1 ] . ID { return errors . Errorf ( " " , m . ExtractedV1Compatibility [ i + 1 ] . ID , m . ExtractedV1Compatibility [ i ] . Parent ) } } return nil }
// fixManifestLayers, after validating the supplied manifest
// (to use correctly-formatted IDs, and to not have non-consecutive ID collisions in m.History),
// modifies manifest to only have one entry for each layer ID in m.History (deleting the older duplicates,
// both from m.History and m.FSLayers).
// Note that even after this succeeds, m.FSLayers may contain duplicate entries
// (for Dockerfile operations which change the configuration but not the filesystem).
fixManifestLayers after validating the supplied manifest ( to use correctly - formatted IDs and to not have non - consecutive ID collisions in m . History ) modifies manifest to only have one entry for each layer ID in m . History ( deleting the older duplicates both from m . History and m . FSLayers ) . Note that even after this succeeds m . FSLayers may contain duplicate entries ( for Dockerfile operations which change the configuration but not the filesystem ) .