| package storage |
| |
| import ( |
| "context" |
| "path" |
| |
| dcontext "github.com/docker/distribution/context" |
| "github.com/docker/distribution/registry/storage/driver" |
| "github.com/opencontainers/go-digest" |
| ) |
| |
| // vacuum contains functions for cleaning up repositories and blobs |
| // These functions will only reliably work on strongly consistent |
| // storage systems. |
| // https://en.wikipedia.org/wiki/Consistency_model |
| |
| // NewVacuum creates a new Vacuum |
| func NewVacuum(ctx context.Context, driver driver.StorageDriver) Vacuum { |
| return Vacuum{ |
| ctx: ctx, |
| driver: driver, |
| } |
| } |
| |
| // Vacuum removes content from the filesystem |
| type Vacuum struct { |
| driver driver.StorageDriver |
| ctx context.Context |
| } |
| |
| // RemoveBlob removes a blob from the filesystem |
| func (v Vacuum) RemoveBlob(dgst string) error { |
| d, err := digest.Parse(dgst) |
| if err != nil { |
| return err |
| } |
| |
| blobPath, err := pathFor(blobPathSpec{digest: d}) |
| if err != nil { |
| return err |
| } |
| |
| dcontext.GetLogger(v.ctx).Infof("Deleting blob: %s", blobPath) |
| |
| err = v.driver.Delete(v.ctx, blobPath) |
| if err != nil { |
| return err |
| } |
| |
| return nil |
| } |
| |
| // RemoveManifest removes a manifest from the filesystem |
| func (v Vacuum) RemoveManifest(name string, dgst digest.Digest, tags []string) error { |
| // remove a tag manifest reference, in case of not found continue to next one |
| for _, tag := range tags { |
| |
| tagsPath, err := pathFor(manifestTagIndexEntryPathSpec{name: name, revision: dgst, tag: tag}) |
| if err != nil { |
| return err |
| } |
| |
| _, err = v.driver.Stat(v.ctx, tagsPath) |
| if err != nil { |
| switch err := err.(type) { |
| case driver.PathNotFoundError: |
| continue |
| default: |
| return err |
| } |
| } |
| dcontext.GetLogger(v.ctx).Infof("deleting manifest tag reference: %s", tagsPath) |
| err = v.driver.Delete(v.ctx, tagsPath) |
| if err != nil { |
| return err |
| } |
| } |
| |
| manifestPath, err := pathFor(manifestRevisionPathSpec{name: name, revision: dgst}) |
| if err != nil { |
| return err |
| } |
| dcontext.GetLogger(v.ctx).Infof("deleting manifest: %s", manifestPath) |
| return v.driver.Delete(v.ctx, manifestPath) |
| } |
| |
| // RemoveRepository removes a repository directory from the |
| // filesystem |
| func (v Vacuum) RemoveRepository(repoName string) error { |
| rootForRepository, err := pathFor(repositoriesRootPathSpec{}) |
| if err != nil { |
| return err |
| } |
| repoDir := path.Join(rootForRepository, repoName) |
| dcontext.GetLogger(v.ctx).Infof("Deleting repo: %s", repoDir) |
| err = v.driver.Delete(v.ctx, repoDir) |
| if err != nil { |
| return err |
| } |
| |
| return nil |
| } |