func dryRunPurge()

in cmd/acr/purge.go [340:441]


func dryRunPurge(ctx context.Context, acrClient api.AcrCLIClientInterface, loginURL string, repoName string, ago string, filter string, untagged bool, keep int, regexMatchTimeout int64) (int, int, error) {
	deletedTagsCount := 0
	deletedManifestsCount := 0
	// In order to keep track if a manifest would get deleted a map is defined that as a key has the manifest
	// digest and as the value the number of tags (referencing said manifests) that were deleted.
	deletedTags := map[string]int{}
	fmt.Printf("Tags for this repository would be deleted: %s\n", repoName)
	agoDuration, err := parseDuration(ago)
	if err != nil {
		return -1, -1, err
	}
	timeToCompare := time.Now().UTC()
	timeToCompare = timeToCompare.Add(agoDuration)
	regex, err := common.BuildRegexFilter(filter, regexMatchTimeout)
	if err != nil {
		return -1, -1, err
	}

	lastTag := ""
	skippedTagsCount := 0
	// The loop to get the deleted tags follows the same logic as the one in the purgeTags function
	for {
		tagsToDelete, newLastTag, newSkippedTagsCount, err := getTagsToDelete(ctx, acrClient, repoName, regex, timeToCompare, lastTag, keep, skippedTagsCount)
		if err != nil {
			return -1, -1, err
		}
		lastTag = newLastTag
		skippedTagsCount = newSkippedTagsCount
		if tagsToDelete != nil {
			for _, tag := range *tagsToDelete {
				// For every tag that would be deleted first check if it exists in the map, if it doesn't add a new key
				// with value 1 and if it does just add 1 to the existent value.
				deletedTags[*tag.Digest]++
				fmt.Printf("%s/%s:%s\n", loginURL, repoName, *tag.Name)
				deletedTagsCount++
			}
		}
		if len(lastTag) == 0 {
			break
		}
	}
	if untagged {
		fmt.Printf("Manifests for this repository would be deleted: %s\n", repoName)
		// The tagsCount contains a map that for every digest contains how many tags are referencing it.
		tagsCount, err := countTagsByManifest(ctx, acrClient, repoName)
		if err != nil {
			return -1, -1, err
		}
		lastManifestDigest := ""
		resultManifests, err := acrClient.GetAcrManifests(ctx, repoName, "", lastManifestDigest)
		if err != nil {
			if resultManifests != nil && resultManifests.Response.Response != nil && resultManifests.StatusCode == http.StatusNotFound {
				fmt.Printf("%s repository not found\n", repoName)
				return 0, 0, nil
			}
			return -1, -1, err
		}
		// This set will do the check: if a key is present, then the corresponding manifest
		// should not be deleted because it is referenced by a multiarch manifest
		// or otherwise references a subject
		doNotDelete := set.New[string]()
		candidatesToDelete := []acr.ManifestAttributesBase{}
		for resultManifests != nil && resultManifests.ManifestsAttributes != nil {
			manifests := *resultManifests.ManifestsAttributes
			for _, manifest := range manifests {
				if tagsCount[*manifest.Digest] != deletedTags[*manifest.Digest] {
					// If the number of the tags associated with the manifest is  not equal to
					// the number of tags to be deleted, the said manifest will still have
					// tags remaining and we will consider if it has any dependant manifests
					err = common.AddDependentManifestsToIgnoreList(ctx, manifest, doNotDelete, acrClient, repoName)
					if err != nil {
						return -1, -1, err
					}
				} else {
					// Otherwise the manifest have no tag left after purgeTags.
					// we will need to find if the manifest has subject. If so,
					// we will mark the manifest to not be deleted.
					candidatesToDelete, err = common.UpdateForManifestWithoutSubjectToDelete(ctx, manifest, doNotDelete, candidatesToDelete, acrClient, repoName)
					if err != nil {
						return -1, -1, err
					}
				}
			}
			// Get the last manifest digest from the last manifest from manifests.
			lastManifestDigest = *manifests[len(manifests)-1].Digest
			// Use this new digest to find next batch of manifests.
			resultManifests, err = acrClient.GetAcrManifests(ctx, repoName, "", lastManifestDigest)
			if err != nil {
				return -1, -1, err
			}
		}
		// Just print manifests that would be deleted.
		for i := 0; i < len(candidatesToDelete); i++ {
			if !doNotDelete.Contains(*candidatesToDelete[i].Digest) {
				fmt.Printf("%s/%s@%s\n", loginURL, repoName, *candidatesToDelete[i].Digest)
				deletedManifestsCount++
			}
		}
	}

	return deletedTagsCount, deletedManifestsCount, nil
}