func()

in registry/datastore/repository.go [909:1001]


func (s *repositoryStore) appendTagsDetailReferrers(ctx context.Context, r *models.Repository, tags []*models.TagDetail, artifactTypes []string) error {
	if len(tags) == 0 {
		return nil
	}

	sbjDigests := make([]string, 0, len(tags))
	for _, tag := range tags {
		nd, err := NewDigest(tag.Digest)
		if err != nil {
			return err
		}
		sbjDigests = append(sbjDigests, nd.HexDecode())
	}

	q := `SELECT
			encode(m.digest, 'hex') AS digest,
			COALESCE(at.media_type, cmt.media_type) AS artifact_type,
			encode(ms.digest, 'hex') AS subject_digest
		FROM
			manifests AS m
			JOIN manifests AS ms ON m.top_level_namespace_id = ms.top_level_namespace_id
				AND m.subject_id = ms.id
			LEFT JOIN media_types AS at ON at.id = m.artifact_media_type_id
			LEFT JOIN media_types AS cmt ON cmt.id = m.configuration_media_type_id
		WHERE
			m.top_level_namespace_id = $1
			AND m.repository_id = $2
			AND m.subject_id IN (
				SELECT
					id
				FROM
					manifests
				WHERE
					top_level_namespace_id = $1
					AND repository_id = $2
					AND digest = ANY ($3))`

	var rows *sql.Rows
	var err error

	if len(artifactTypes) > 0 {
		ats, errInner := s.mediaTypeIDs(ctx, artifactTypes)
		if errInner != nil {
			return errInner
		}
		q += " AND (m.artifact_media_type_id = ANY ($4) OR m.configuration_media_type_id = ANY ($4))"
		rows, err = s.db.QueryContext(ctx, q, r.NamespaceID, r.ID, sbjDigests, ats) // nolint: staticcheck // err is checked below
	} else {
		rows, err = s.db.QueryContext(ctx, q, r.NamespaceID, r.ID, sbjDigests)
	}
	if err != nil {
		return err
	}
	defer rows.Close()

	refMap := make(map[string][]models.TagReferrerDetail)
	var (
		dgst, sbjDgst Digest
		at, sbjStr    string
	)
	for rows.Next() {
		if err = rows.Scan(&dgst, &at, &sbjDgst); err != nil {
			return fmt.Errorf("scanning referrer: %w", err)
		}

		d, err := dgst.Parse()
		if err != nil {
			return err
		}
		sbj, err := sbjDgst.Parse()
		if err != nil {
			return err
		}
		sbjStr = sbj.String()

		if refMap[sbjStr] == nil {
			refMap[sbjStr] = make([]models.TagReferrerDetail, 0)
		}
		refMap[sbjStr] = append(refMap[sbjStr], models.TagReferrerDetail{
			Digest:       d.String(),
			ArtifactType: at,
		})
	}
	if err := rows.Err(); err != nil {
		return fmt.Errorf("scanning referrers: %w", err)
	}

	for _, tag := range tags {
		tag.Referrers = refMap[tag.Digest.String()]
	}

	return nil
}