Phase 7: OCI delete path for manifests and blobs
Manifest delete (DELETE /v2/<name>/manifests/<digest>): rejects tag references with 405 UNSUPPORTED per OCI spec, cascades to tags and manifest_blobs via ON DELETE CASCADE, returns 202 Accepted. Blob delete (DELETE /v2/<name>/blobs/<digest>): removes manifest_blobs associations only — blob row and file are preserved for GC to handle, since other repos may reference the same content-addressed blob. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -207,6 +207,34 @@ func (f *fakeDB) DeleteUpload(uuid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeDB) DeleteManifest(repoID int64, digest string) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
key := manifestKey{repoID, digest}
|
||||
if _, ok := f.manifests[key]; !ok {
|
||||
return db.ErrManifestNotFound
|
||||
}
|
||||
delete(f.manifests, key)
|
||||
// Also remove any tag entries pointing to this digest.
|
||||
for k, m := range f.manifests {
|
||||
if k.repoID == repoID && m.Digest == digest {
|
||||
delete(f.manifests, k)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeDB) DeleteBlobFromRepo(repoID int64, digest string) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
digests, ok := f.blobs[repoID]
|
||||
if !ok || !digests[digest] {
|
||||
return db.ErrBlobNotFound
|
||||
}
|
||||
delete(digests, digest)
|
||||
return nil
|
||||
}
|
||||
|
||||
// addRepo adds a repo to the fakeDB and returns its ID.
|
||||
func (f *fakeDB) addRepo(name string, id int64) {
|
||||
f.repos[name] = id
|
||||
|
||||
Reference in New Issue
Block a user