func (olu OciLayoutUtils) GetImageTagsWithTimestamp(repo string) ([]TagInfo, error) {
	tagsInfo := make([]TagInfo, 0)
	manifests, err := olu.GetImageManifests(repo)
	if err != nil {
		olu.Log.Error().Err(err).Msg("unable to read image manifests")
		return tagsInfo, err
	}
	for _, manifest := range manifests {
		digest := manifest.Digest
		v, ok := manifest.Annotations[ispec.AnnotationRefName]
		if ok {
			imageBlobManifest, err := olu.GetImageBlobManifest(repo, digest)
			if err != nil {
				olu.Log.Error().Err(err).Msg("unable to read image blob manifest")
				return tagsInfo, err
			}
			imageInfo, err := olu.GetImageInfo(repo, imageBlobManifest.Config.Digest)
			if err != nil {
				olu.Log.Error().Err(err).Msg("unable to read image info")
				return tagsInfo, err
			}
			var timeStamp time.Time
			if len(imageInfo.History) != 0 {
				timeStamp = *imageInfo.History[0].Created
			} else {
				timeStamp = time.Time{}
			}
			tagsInfo = append(tagsInfo, TagInfo{Name: v, Timestamp: timeStamp, Digest: digest.String()})
		}
	}
	return tagsInfo, nil
}
GetImageTagsWithTimestamp returns a list of image tags with timestamp available in the specified repository.
package common
import (
	"encoding/json"
	"path"
	"strings"
	"time"
	goerrors "errors"
	"github.com/anuvu/zot/errors"
	"github.com/anuvu/zot/pkg/log"
	"github.com/anuvu/zot/pkg/storage"
	v1 "github.com/google/go-containerregistry/pkg/v1"
	"github.com/google/go-containerregistry/pkg/v1/types"
	godigest "github.com/opencontainers/go-digest"
	ispec "github.com/opencontainers/image-spec/specs-go/v1"
)
type OciLayoutUtils struct {
	Log             log.Logger
	StoreController storage.StoreController
}
func NewOciLayoutUtils(storeController storage.StoreController, log log.Logger) *OciLayoutUtils {
	return &OciLayoutUtils{Log: log, StoreController: storeController}
}
func (olu OciLayoutUtils) GetImageManifests(image string) ([]ispec.Descriptor, error) {
	imageStore := olu.StoreController.GetImageStore(image)
	buf, err := imageStore.GetIndexContent(image)
	if err != nil {
		if goerrors.Is(errors.ErrRepoNotFound, err) {
			olu.Log.Error().Err(err).Msg("index.json doesn't exist")
			return nil, errors.ErrRepoNotFound
		}
		olu.Log.Error().Err(err).Msg("unable to open index.json")
		return nil, errors.ErrRepoNotFound
	}
	var index ispec.Index
	if err := json.Unmarshal(buf, &index); err != nil {
		olu.Log.Error().Err(err).Str("dir", path.Join(imageStore.RootDir(), image)).Msg("invalid JSON")
		return nil, errors.ErrRepoNotFound
	}
	return index.Manifests, nil
}
func (olu OciLayoutUtils) GetImageBlobManifest(imageDir string, digest godigest.Digest) (v1.Manifest, error) {
	var blobIndex v1.Manifest
	imageStore := olu.StoreController.GetImageStore(imageDir)
	blobBuf, err := imageStore.GetBlobContent(imageDir, digest.String())
	if err != nil {
		olu.Log.Error().Err(err).Msg("unable to open image metadata file")
		return blobIndex, err
	}
	if err := json.Unmarshal(blobBuf, &blobIndex); err != nil {
		olu.Log.Error().Err(err).Msg("unable to marshal blob index")
		return blobIndex, err
	}
	return blobIndex, nil
}
func (olu OciLayoutUtils) GetImageInfo(imageDir string, hash v1.Hash) (ispec.Image, error) {
	var imageInfo ispec.Image
	imageStore := olu.StoreController.GetImageStore(imageDir)
	blobBuf, err := imageStore.GetBlobContent(imageDir, hash.String())
	if err != nil {
		olu.Log.Error().Err(err).Msg("unable to open image layers file")
		return imageInfo, err
	}
	if err := json.Unmarshal(blobBuf, &imageInfo); err != nil {
		olu.Log.Error().Err(err).Msg("unable to marshal blob index")
		return imageInfo, err
	}
	return imageInfo, err
}
func (olu OciLayoutUtils) IsValidImageFormat(image string) (bool, error) {
	imageDir, inputTag := GetImageDirAndTag(image)
	manifests, err := olu.GetImageManifests(imageDir)
	if err != nil {
		return false, err
	}
	for _, m := range manifests {
		tag, ok := m.Annotations[ispec.AnnotationRefName]
		if ok && inputTag != "" && tag != inputTag {
			continue
		}
		blobManifest, err := olu.GetImageBlobManifest(imageDir, m.Digest)
		if err != nil {
			return false, err
		}
		imageLayers := blobManifest.Layers
		for _, imageLayer := range imageLayers {
			switch imageLayer.MediaType {
			case types.OCILayer, types.DockerLayer:
				return true, nil
			default:
				olu.Log.Debug().Msg("image media type not supported for scanning")
				return false, errors.ErrScanNotSupported
			}
		}
	}
	return false, nil
}