Add Stat function to filer.Filer interface (#421)

## Changes

TSIA

## Tests

New integration test passes.
This commit is contained in:
Pieter Noordhuis 2023-06-01 20:23:22 +02:00 committed by GitHub
parent 7a4ca786d8
commit 2b56af6016
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 79 additions and 6 deletions

View File

@ -68,11 +68,32 @@ func runFilerReadWriteTest(t *testing.T, ctx context.Context, f filer.Filer) {
assert.NoError(t, err)
filerTest{t, f}.assertContents(ctx, "/foo/bar", `hello universe`)
// Stat on a directory should succeed.
// Note: size and modification time behave differently between WSFS and DBFS.
info, err := f.Stat(ctx, "/foo")
require.NoError(t, err)
assert.Equal(t, "foo", info.Name())
assert.True(t, info.Mode().IsDir())
assert.Equal(t, true, info.IsDir())
// Stat on a file should succeed.
// Note: size and modification time behave differently between WSFS and DBFS.
info, err = f.Stat(ctx, "/foo/bar")
require.NoError(t, err)
assert.Equal(t, "bar", info.Name())
assert.True(t, info.Mode().IsRegular())
assert.Equal(t, false, info.IsDir())
// Delete should fail if the file doesn't exist.
err = f.Delete(ctx, "/doesnt_exist")
assert.True(t, errors.As(err, &filer.FileDoesNotExistError{}))
assert.True(t, errors.Is(err, fs.ErrNotExist))
// Stat should fail if the file doesn't exist.
_, err = f.Stat(ctx, "/doesnt_exist")
assert.True(t, errors.As(err, &filer.FileDoesNotExistError{}))
assert.True(t, errors.Is(err, fs.ErrNotExist))
// Delete should succeed for file that does exist.
err = f.Delete(ctx, "/foo/bar")
assert.NoError(t, err)

View File

@ -22,11 +22,7 @@ type dbfsDirEntry struct {
}
func (entry dbfsDirEntry) Type() fs.FileMode {
typ := fs.ModePerm
if entry.fi.IsDir {
typ |= fs.ModeDir
}
return typ
return entry.Mode()
}
func (entry dbfsDirEntry) Info() (fs.FileInfo, error) {
@ -47,7 +43,11 @@ func (info dbfsFileInfo) Size() int64 {
}
func (info dbfsFileInfo) Mode() fs.FileMode {
return fs.ModePerm
mode := fs.ModePerm
if info.fi.IsDir {
mode |= fs.ModeDir
}
return mode
}
func (info dbfsFileInfo) ModTime() time.Time {
@ -240,3 +240,29 @@ func (w *DbfsClient) Mkdir(ctx context.Context, name string) error {
return w.workspaceClient.Dbfs.MkdirsByPath(ctx, dirPath)
}
func (w *DbfsClient) Stat(ctx context.Context, name string) (fs.FileInfo, error) {
absPath, err := w.root.Join(name)
if err != nil {
return nil, err
}
info, err := w.workspaceClient.Dbfs.GetStatusByPath(ctx, absPath)
if err != nil {
var aerr *apierr.APIError
if !errors.As(err, &aerr) {
return nil, err
}
// This API returns a 404 if the file doesn't exist.
if aerr.StatusCode == http.StatusNotFound {
if aerr.ErrorCode == "RESOURCE_DOES_NOT_EXIST" {
return nil, FileDoesNotExistError{absPath}
}
}
return nil, err
}
return dbfsFileInfo{*info}, nil
}

View File

@ -68,4 +68,7 @@ type Filer interface {
// Creates directory at `path`, creating any intermediate directories as required.
Mkdir(ctx context.Context, path string) error
// Stat returns information about the file at `path`.
Stat(ctx context.Context, name string) (fs.FileInfo, error)
}

View File

@ -256,3 +256,26 @@ func (w *WorkspaceFilesClient) Mkdir(ctx context.Context, name string) error {
Path: dirPath,
})
}
func (w *WorkspaceFilesClient) Stat(ctx context.Context, name string) (fs.FileInfo, error) {
absPath, err := w.root.Join(name)
if err != nil {
return nil, err
}
info, err := w.workspaceClient.Workspace.GetStatusByPath(ctx, absPath)
if err != nil {
// If we got an API error we deal with it below.
var aerr *apierr.APIError
if !errors.As(err, &aerr) {
return nil, err
}
// This API returns a 404 if the specified path does not exist.
if aerr.StatusCode == http.StatusNotFound {
return nil, FileDoesNotExistError{absPath}
}
}
return wsfsFileInfo{*info}, nil
}