Fix bug where GC attempts to delete manifests that are shared by multiple tag manifests

Also adds a test for this case

All of this will be moot once we get rid of tag manifests, but for now, its causing exceptions
This commit is contained in:
Joseph Schorr 2018-08-28 23:19:57 -04:00
parent cd513f7482
commit ce61ec6668
2 changed files with 93 additions and 10 deletions

View file

@ -367,15 +367,21 @@ def _delete_tags(repo, query_modifier=None):
.where(TagManifestToManifest.tag_manifest << tag_manifests_to_delete,
TagManifestToManifest.broken == False))
manifest_ids_to_delete = [tmt.manifest_id for tmt in tmt_query]
manifest_ids_to_possibly_delete = [tmt.manifest_id for tmt in tmt_query]
manifest_ids_to_delete = set(manifest_ids_to_possibly_delete)
# Filter out any manifests referenced by other tag manifests.
if manifest_ids_to_possibly_delete:
ref_query = (TagManifestToManifest
.select()
.where(TagManifestToManifest.manifest << manifest_ids_to_possibly_delete,
~(TagManifestToManifest.tag_manifest << tag_manifest_ids_to_delete)))
still_referenced_manifests = set([tmt.manifest_id for tmt in ref_query])
manifest_ids_to_delete = list(manifest_ids_to_delete - still_referenced_manifests)
num_deleted_manifests = 0
if len(tag_manifest_ids_to_delete) > 0:
# Delete tag manifest -> manifest mapping entries.
(TagManifestToManifest
.delete()
.where(TagManifestToManifest.tag_manifest << tag_manifest_ids_to_delete)
.execute())
# Find the set of IDs for all the labels to delete.
manifest_labels_query = (TagManifestLabel
.select()
@ -383,6 +389,22 @@ def _delete_tags(repo, query_modifier=None):
TagManifestLabel.annotated << tag_manifest_ids_to_delete))
label_ids = [manifest_label.label_id for manifest_label in manifest_labels_query]
# Filter out any labels still referenced by manifests.
if label_ids:
ref_query = (ManifestLabel
.select()
.where(ManifestLabel.repository == repo,
ManifestLabel.label << label_ids,
~(ManifestLabel.manifest << (manifest_ids_to_delete or [-1]))))
label_ids = set(label_ids) - set([manifest_label.label_id for manifest_label in ref_query])
label_ids = list(label_ids)
# Delete tag manifest -> manifest mapping entries.
(TagManifestToManifest
.delete()
.where(TagManifestToManifest.tag_manifest << tag_manifest_ids_to_delete)
.execute())
# Delete all the mapping entries for labels.
(TagManifestLabelMap
.delete()