func()

in registry/handlers/repositories.go [506:612]


func (h *repositoryTagsHandler) HandleGetTags(w http.ResponseWriter, r *http.Request) {
	filters, err := filterParamsFromRequest(r)
	if err != nil {
		h.Errors = append(h.Errors, err)
		return
	}

	var opts []datastore.RepositoryStoreOption
	if h.GetRepoCache() != nil {
		opts = append(opts, datastore.WithRepositoryCache(h.GetRepoCache()))
	}
	rStore := datastore.NewRepositoryStore(h.db.Primary(), opts...)
	p := h.Repository.Named().Name()
	repo, err := rStore.FindByPath(h.Context, p)
	if err != nil {
		h.Errors = append(h.Errors, errcode.FromUnknownError(err))
		return
	}
	if repo == nil {
		h.Errors = append(h.Errors, v2.ErrorCodeNameUnknown.WithDetail(map[string]string{"name": p}))
		return
	}

	tagsList, err := rStore.TagsDetailPaginated(h.Context, repo, filters)
	if err != nil {
		h.Errors = append(h.Errors, errcode.FromUnknownError(err))
		return
	}

	// Add a link header if there are more entries to retrieve
	// NOTE(prozlach): with exact-match filter we get only one or no entries,
	// so pagination is not needed.
	if len(tagsList) > 0 && filters.ExactName == "" {
		filters.LastEntry = tagsList[len(tagsList)-1].Name
		filters.PublishedAt = timeToStringMicroPrecision(tagsList[len(tagsList)-1].PublishedAt)
		publishedLast := filters.PublishedAt
		hasTagsAfter, err := rStore.HasTagsAfterName(h.Context, repo, filters)
		if err != nil {
			h.Errors = append(h.Errors, errcode.FromUnknownError(err))
			return
		}

		if !hasTagsAfter {
			filters.LastEntry = ""
			publishedLast = ""
		}

		filters.BeforeEntry = tagsList[0].Name
		filters.PublishedAt = timeToStringMicroPrecision(tagsList[0].PublishedAt)
		publishedBefore := filters.PublishedAt
		hasTagsBefore, err := rStore.HasTagsBeforeName(h.Context, repo, filters)
		if err != nil {
			h.Errors = append(h.Errors, errcode.FromUnknownError(err))
			return
		}

		if !hasTagsBefore {
			filters.BeforeEntry = ""
			publishedBefore = ""
		}

		urlStr, err := createLinkEntry(r.URL.String(), filters, publishedBefore, publishedLast)
		if err != nil {
			h.Errors = append(h.Errors, errcode.FromUnknownError(err))
			return
		}
		if urlStr != "" {
			w.Header().Set("Link", urlStr)
		}
	}

	w.Header().Set("Content-Type", "application/json")

	resp := make([]RepositoryTagResponse, 0, len(tagsList))
	for _, t := range tagsList {
		d := RepositoryTagResponse{
			Name:        t.Name,
			Digest:      t.Digest.String(),
			MediaType:   t.MediaType,
			Size:        t.Size,
			CreatedAt:   timeToString(t.CreatedAt),
			PublishedAt: timeToString(t.PublishedAt),
		}
		if t.ConfigDigest.Valid {
			d.ConfigDigest = t.ConfigDigest.Digest.String()
		}
		if t.UpdatedAt.Valid {
			d.UpdatedAt = timeToString(t.UpdatedAt.Time)
		}
		if t.Referrers != nil {
			d.Referrers = make([]RepositoryTagReferrerResponse, 0, len(t.Referrers))
			for _, td := range t.Referrers {
				d.Referrers = append(d.Referrers, RepositoryTagReferrerResponse{
					Digest:       td.Digest,
					ArtifactType: td.ArtifactType,
				})
			}
		}
		resp = append(resp, d)
	}

	enc := json.NewEncoder(w)
	if err := enc.Encode(resp); err != nil {
		h.Errors = append(h.Errors, errcode.FromUnknownError(err))
		return
	}
}