Skip to content
Snippets Groups Projects
Commit 24ae7ab4 authored by Pawel Rozlach's avatar Pawel Rozlach Committed by Suleimi Ahmed
Browse files

refactor: proper error chaining in in-memory storage

parent 88bf04ef
No related branches found
No related tags found
1 merge request!1834refactor: proper error chaining in in-memory storage
......@@ -105,7 +105,7 @@ func (ch *catalogHandler) GetCatalog(w http.ResponseWriter, r *http.Request) {
filled, err = ch.App.registry.Repositories(ch.Context, repos, filters.LastEntry)
if err == io.EOF || errors.As(err, new(driver.PathNotFoundError)) {
if errors.Is(err, io.EOF) || errors.As(err, new(driver.PathNotFoundError)) {
moreEntries = false
} else if err != nil {
ch.Errors = append(ch.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
......
......@@ -94,7 +94,7 @@ func (d *driver) PutContent(ctx context.Context, p string, contents []byte) erro
f, err := d.root.mkfile(normalized)
if err != nil {
return fmt.Errorf("not a file")
return fmt.Errorf("failed to create or retrieve file: %w", err)
}
f.truncate()
......@@ -213,13 +213,7 @@ func (d *driver) Move(ctx context.Context, sourcePath, destPath string) error {
normalizedSrc, normalizedDst := normalize(sourcePath), normalize(destPath)
err := d.root.move(normalizedSrc, normalizedDst)
switch err {
case errNotExists:
return storagedriver.PathNotFoundError{Path: destPath, DriverName: driverName}
default:
return err
}
return d.root.move(normalizedSrc, normalizedDst)
}
// Delete recursively deletes all objects stored at "path" and its subpaths.
......@@ -229,13 +223,7 @@ func (d *driver) Delete(ctx context.Context, path string) error {
normalized := normalize(path)
err := d.root.delete(normalized)
switch err {
case errNotExists:
return storagedriver.PathNotFoundError{Path: path, DriverName: driverName}
default:
return err
}
return d.root.delete(normalized)
}
// DeleteFiles deletes a set of files by iterating over their full path list and invoking Delete for each. Returns the
......
......@@ -7,6 +7,8 @@ import (
"sort"
"strings"
"time"
storagedriver "github.com/docker/distribution/registry/storage/driver"
)
var (
......@@ -48,7 +50,7 @@ func (d *dir) add(n node) {
}
// find searches for the node, given path q in dir. If the node is found, it
// will be returned. If the node is not found, the closet existing parent. If
// will be returned. If the node is not found, the closest existing parent. If
// the node is found, the returned (node).path() will match q.
func (d *dir) find(q string) node {
q = strings.Trim(q, "/")
......@@ -125,7 +127,7 @@ func (d *dir) mkfile(p string) (*file, error) {
// Make any non-existent directories
n, err := d.mkdirs(dirpath)
if err != nil {
return nil, err
return nil, fmt.Errorf("mkdirs failed: %w", err)
}
dd := n.(*dir)
......@@ -148,7 +150,7 @@ func (d *dir) mkdirs(p string) (*dir, error) {
if !n.isdir() {
// Found something there
return nil, errIsNotDir
return nil, fmt.Errorf("mkdirs found non-directory element at path %s: %w", n.path(), errIsNotDir)
}
if n.path() == p {
......@@ -168,7 +170,7 @@ func (d *dir) mkdirs(p string) (*dir, error) {
d, err := dd.mkdir(component)
if err != nil {
// This should actually never happen, since there are no children.
return nil, err
return nil, fmt.Errorf("mkdir of %q failed: %w", component, err)
}
dd = d
}
......@@ -179,12 +181,12 @@ func (d *dir) mkdirs(p string) (*dir, error) {
// mkdir creates a child directory under d with the given name.
func (d *dir) mkdir(name string) (*dir, error) {
if name == "" {
return nil, fmt.Errorf("invalid dirname")
return nil, fmt.Errorf("dirname passed to mkdir is empty")
}
_, ok := d.children[name]
if ok {
return nil, errExists
return nil, fmt.Errorf("child %q already exists: %w", name, errExists)
}
child := &dir{
......@@ -204,24 +206,32 @@ func (d *dir) move(src, dst string) error {
dp, err := d.mkdirs(dstDirname)
if err != nil {
return err
return fmt.Errorf("mkdir failed: %w", err)
}
srcDirname, srcFilename := path.Split(src)
sp := d.find(srcDirname)
if normalize(srcDirname) != normalize(sp.path()) {
return errNotExists
return fmt.Errorf(
"source directory %q does not exist: %w",
srcDirname,
storagedriver.PathNotFoundError{DriverName: driverName, Path: src},
)
}
spd, ok := sp.(*dir)
if !ok {
return errIsNotDir // paranoid.
return fmt.Errorf("src paths' directory component is not a directory: %w", errIsNotDir) // paranoid.
}
s, ok := spd.children[srcFilename]
if !ok {
return errNotExists
return fmt.Errorf(
"src file %q does not exist: %w",
srcFilename,
storagedriver.PathNotFoundError{Path: src, DriverName: driverName},
)
}
delete(spd.children, srcFilename)
......@@ -243,11 +253,19 @@ func (d *dir) delete(p string) error {
parent := d.find(dirname)
if normalize(dirname) != normalize(parent.path()) {
return errNotExists
return fmt.Errorf(
"directory %q does not exist: %w",
parent.path(),
storagedriver.PathNotFoundError{DriverName: driverName, Path: p},
)
}
if _, ok := parent.(*dir).children[filename]; !ok {
return errNotExists
return fmt.Errorf(
"file %q does not exist: %w",
filename,
storagedriver.PathNotFoundError{DriverName: driverName, Path: p},
)
}
delete(parent.(*dir).children, filename)
......
......@@ -179,7 +179,7 @@ func (suite *DriverSuite) TestValidPaths(c *check.C) {
func (suite *DriverSuite) deletePath(c *check.C, path string) {
for tries := 2; tries > 0; tries-- {
err := suite.StorageDriver.Delete(suite.ctx, path)
if _, ok := err.(storagedriver.PathNotFoundError); ok {
if errors.As(err, new(storagedriver.PathNotFoundError)) {
err = nil
}
c.Assert(err, check.IsNil)
......@@ -636,7 +636,7 @@ func (suite *DriverSuite) TestMoveNonexistent(c *check.C) {
err = suite.StorageDriver.Move(suite.ctx, sourcePath, destPath)
c.Assert(err, check.NotNil)
c.Assert(err, check.FitsTypeOf, storagedriver.PathNotFoundError{})
c.Assert(errors.As(err, new(storagedriver.PathNotFoundError)), check.Equals, true)
c.Assert(strings.Contains(err.Error(), suite.Name()), check.Equals, true)
received, err := suite.StorageDriver.GetContent(suite.ctx, destPath)
......@@ -877,7 +877,7 @@ func (suite *DriverSuite) TestDeleteNonexistent(c *check.C) {
filename := randomPath(32)
err := suite.StorageDriver.Delete(suite.ctx, filename)
c.Assert(err, check.NotNil)
c.Assert(err, check.FitsTypeOf, storagedriver.PathNotFoundError{})
c.Assert(errors.As(err, new(storagedriver.PathNotFoundError)), check.Equals, true)
c.Assert(strings.Contains(err.Error(), suite.Name()), check.Equals, true)
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment