func ApplyFilterAndGetFilteredList()

in internal/cssc/cssc.go [184:284]


func ApplyFilterAndGetFilteredList(ctx context.Context, acrClient api.AcrCLIClientInterface, filter Filter) ([]FilteredRepository, []FilteredRepository, error) {

	var filteredRepos []FilteredRepository
	var artifactsNotFound []FilteredRepository

	// Default is incremental tag regex, only if tag convention is specified as floating, use floating tag regex
	patchTagRegex := incrementalTagRegex
	if filter.TagConvention == Floating {
		patchTagRegex = floatingTagRegex
	}

	uniqueFilteredRepos := make(map[string]bool)
	for _, filterRepo := range filter.Repositories {
		// Create a tag map for each repository, where the key will be the base tag and the value will be the list of tags matching the tag convention from the filter
		tagMap := make(map[string][]string)
		if filterRepo.Enabled != nil && !*filterRepo.Enabled {
			continue
		}
		if filterRepo.Repository == "" || filterRepo.Tags == nil || len(filterRepo.Tags) == 0 {
			continue
		}

		tagList, err := tag.ListTags(ctx, acrClient, filterRepo.Repository)
		if err != nil {
			var listTagsErr *tag.ListTagsError
			if errors.As(err, &listTagsErr) {
				for _, tag := range filterRepo.Tags {
					artifactsNotFound = append(artifactsNotFound, FilteredRepository{
						Repository: filterRepo.Repository,
						Tag:        tag,
					})
				}
				continue
			}
			return nil, nil, errors.Wrap(err, "Some unexpected error occurred while listing tags for repository-"+filterRepo.Repository)
		}

		if len(filterRepo.Tags) == 1 && filterRepo.Tags[0] == "*" { // If the repo has * as tags defined in the filter, then all tags are considered for that repo
			for _, tag := range tagList {
				matches := patchTagRegex.FindStringSubmatch(*tag.Name)
				if matches != nil {
					baseTag := matches[1]
					tagMap[baseTag] = append(tagMap[baseTag], *tag.Name)
				} else if !endsWithIncrementalOrFloatingPattern(*tag.Name) {
					tagMap[*tag.Name] = append(tagMap[*tag.Name], *tag.Name)
				}
			}
		} else {
			for _, ftag := range filterRepo.Tags { // If the repo has specific tags defined in the filter, then only those tags are considered
				// If tag from filter is not found in the tag list obtained for the repository, then add it to artifactsNotFound and continue with the next tag
				if !containsTag(tagList, ftag) {
					artifactsNotFound = append(artifactsNotFound, FilteredRepository{
						Repository: filterRepo.Repository,
						Tag:        ftag,
					})
					continue
				}
				// This is needed to evaluate all versions of patch tags when original tag is specified in the filter
				var re *regexp.Regexp
				if filter.TagConvention == Floating {
					re = regexp.MustCompile(`^` + ftag + `(-patched\d*)?$`)
				} else {
					re = regexp.MustCompile(`^` + ftag + `(-[1-9]\d{0,2})?$`)
				}
				for _, tag := range tagList {
					if re.MatchString(*tag.Name) {
						matches := patchTagRegex.FindStringSubmatch(*tag.Name)
						if matches != nil {
							baseTag := matches[1]
							tagMap[baseTag] = append(tagMap[baseTag], *tag.Name)
						} else if !endsWithIncrementalOrFloatingPattern(*tag.Name) {
							tagMap[*tag.Name] = append(tagMap[*tag.Name], *tag.Name)
						}
					}
				}
			}
		}

		// Iterate over the tagMap to generate the FilteredRepository list
		for baseTag, tags := range tagMap {
			sort.Slice(tags, func(i, j int) bool {
				return compareTags(tags[i], tags[j])
			})
			latestTag := tags[len(tags)-1]

			if latestTag == baseTag {
				latestTag = "N/A"
			}
			key := fmt.Sprintf("%s-%s-%s", filterRepo.Repository, baseTag, latestTag)
			if !uniqueFilteredRepos[key] {
				uniqueFilteredRepos[key] = true
				filteredRepos = append(filteredRepos, FilteredRepository{
					Repository: filterRepo.Repository,
					Tag:        baseTag,
					PatchTag:   latestTag,
				})
			}
		}
	}
	return filteredRepos, artifactsNotFound, nil
}