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:
2026-03-19 20:23:47 -07:00
parent dddc66f31b
commit c01e7ffa30
9 changed files with 623 additions and 7 deletions

View File

@@ -113,8 +113,10 @@ func (h *Handler) dispatch(w http.ResponseWriter, r *http.Request) {
h.handleManifestHead(w, r, info.name, info.reference)
case http.MethodPut:
h.handleManifestPut(w, r, info.name, info.reference)
case http.MethodDelete:
h.handleManifestDelete(w, r, info.name, info.reference)
default:
w.Header().Set("Allow", "GET, HEAD, PUT")
w.Header().Set("Allow", "GET, HEAD, PUT, DELETE")
writeOCIError(w, "UNSUPPORTED", http.StatusMethodNotAllowed, "method not allowed")
}
case "blobs":
@@ -123,8 +125,10 @@ func (h *Handler) dispatch(w http.ResponseWriter, r *http.Request) {
h.handleBlobGet(w, r, info.name, info.reference)
case http.MethodHead:
h.handleBlobHead(w, r, info.name, info.reference)
case http.MethodDelete:
h.handleBlobDelete(w, r, info.name, info.reference)
default:
w.Header().Set("Allow", "GET, HEAD")
w.Header().Set("Allow", "GET, HEAD, DELETE")
writeOCIError(w, "UNSUPPORTED", http.StatusMethodNotAllowed, "method not allowed")
}
case "uploads":