2022-12-14 14:37:14 +00:00
|
|
|
package filer
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
2023-05-31 12:22:26 +00:00
|
|
|
"io/fs"
|
2022-12-14 14:37:14 +00:00
|
|
|
)
|
|
|
|
|
2024-11-20 10:11:31 +00:00
|
|
|
// WriteMode captures intent when writing a file.
|
|
|
|
//
|
|
|
|
// The first 9 bits are reserved for the [fs.FileMode] permission bits.
|
|
|
|
// These are used only by the local filer implementation and have
|
|
|
|
// no effect for the other implementations.
|
2022-12-14 14:37:14 +00:00
|
|
|
type WriteMode int
|
|
|
|
|
2024-11-20 10:11:31 +00:00
|
|
|
// writeModePerm is a mask to extract permission bits from a WriteMode.
|
|
|
|
const writeModePerm = WriteMode(fs.ModePerm)
|
|
|
|
|
2022-12-14 14:37:14 +00:00
|
|
|
const (
|
2024-11-20 10:11:31 +00:00
|
|
|
// Note: these constants are defined as powers of 2 to support combining them using a bit-wise OR.
|
|
|
|
// They starts from the 10th bit (permission mask + 1) to avoid conflicts with the permission bits.
|
|
|
|
OverwriteIfExists WriteMode = (writeModePerm + 1) << iota
|
2023-11-24 11:15:46 +00:00
|
|
|
CreateParentDirectories
|
2022-12-14 14:37:14 +00:00
|
|
|
)
|
|
|
|
|
2024-11-20 10:11:31 +00:00
|
|
|
// DeleteMode captures intent when deleting a file.
|
2023-06-06 06:27:47 +00:00
|
|
|
type DeleteMode int
|
|
|
|
|
|
|
|
const (
|
2023-11-24 11:15:46 +00:00
|
|
|
DeleteRecursively DeleteMode = 1 << iota
|
2023-06-06 06:27:47 +00:00
|
|
|
)
|
|
|
|
|
2022-12-14 14:37:14 +00:00
|
|
|
type FileAlreadyExistsError struct {
|
|
|
|
path string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err FileAlreadyExistsError) Error() string {
|
|
|
|
return fmt.Sprintf("file already exists: %s", err.path)
|
|
|
|
}
|
|
|
|
|
2023-05-31 18:47:00 +00:00
|
|
|
func (err FileAlreadyExistsError) Is(other error) bool {
|
|
|
|
return other == fs.ErrExist
|
|
|
|
}
|
|
|
|
|
2023-05-31 11:24:20 +00:00
|
|
|
type FileDoesNotExistError struct {
|
|
|
|
path string
|
|
|
|
}
|
|
|
|
|
2023-05-31 18:47:00 +00:00
|
|
|
func (err FileDoesNotExistError) Is(other error) bool {
|
|
|
|
return other == fs.ErrNotExist
|
|
|
|
}
|
|
|
|
|
2023-05-31 11:24:20 +00:00
|
|
|
func (err FileDoesNotExistError) Error() string {
|
|
|
|
return fmt.Sprintf("file does not exist: %s", err.path)
|
|
|
|
}
|
|
|
|
|
2022-12-14 14:37:14 +00:00
|
|
|
type NoSuchDirectoryError struct {
|
|
|
|
path string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err NoSuchDirectoryError) Error() string {
|
|
|
|
return fmt.Sprintf("no such directory: %s", err.path)
|
|
|
|
}
|
|
|
|
|
2023-05-31 18:47:00 +00:00
|
|
|
func (err NoSuchDirectoryError) Is(other error) bool {
|
|
|
|
return other == fs.ErrNotExist
|
|
|
|
}
|
|
|
|
|
2023-06-02 10:28:35 +00:00
|
|
|
type NotADirectory struct {
|
|
|
|
path string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err NotADirectory) Error() string {
|
|
|
|
return fmt.Sprintf("not a directory: %s", err.path)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err NotADirectory) Is(other error) bool {
|
|
|
|
return other == fs.ErrInvalid
|
|
|
|
}
|
|
|
|
|
2023-06-08 16:15:12 +00:00
|
|
|
type NotAFile struct {
|
|
|
|
path string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err NotAFile) Error() string {
|
|
|
|
return fmt.Sprintf("not a file: %s", err.path)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err NotAFile) Is(other error) bool {
|
|
|
|
return other == fs.ErrInvalid
|
|
|
|
}
|
|
|
|
|
2023-06-06 06:27:47 +00:00
|
|
|
type DirectoryNotEmptyError struct {
|
|
|
|
path string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err DirectoryNotEmptyError) Error() string {
|
|
|
|
return fmt.Sprintf("directory not empty: %s", err.path)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err DirectoryNotEmptyError) Is(other error) bool {
|
|
|
|
return other == fs.ErrInvalid
|
|
|
|
}
|
|
|
|
|
|
|
|
type CannotDeleteRootError struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err CannotDeleteRootError) Error() string {
|
|
|
|
return "unable to delete filer root"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err CannotDeleteRootError) Is(other error) bool {
|
|
|
|
return other == fs.ErrInvalid
|
|
|
|
}
|
|
|
|
|
2024-10-10 11:18:23 +00:00
|
|
|
type PermissionError struct {
|
|
|
|
path string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err PermissionError) Error() string {
|
|
|
|
return fmt.Sprintf("access denied: %s", err.path)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err PermissionError) Is(other error) bool {
|
|
|
|
return other == fs.ErrPermission
|
|
|
|
}
|
|
|
|
|
2022-12-14 14:37:14 +00:00
|
|
|
// Filer is used to access files in a workspace.
|
|
|
|
// It has implementations for accessing files in WSFS and in DBFS.
|
|
|
|
type Filer interface {
|
|
|
|
// Write file at `path`.
|
|
|
|
// Use the mode to further specify behavior.
|
|
|
|
Write(ctx context.Context, path string, reader io.Reader, mode ...WriteMode) error
|
|
|
|
|
|
|
|
// Read file at `path`.
|
2023-06-12 13:53:58 +00:00
|
|
|
Read(ctx context.Context, path string) (io.ReadCloser, error)
|
2022-12-14 14:37:14 +00:00
|
|
|
|
2023-06-06 06:27:47 +00:00
|
|
|
// Delete file or directory at `path`.
|
|
|
|
Delete(ctx context.Context, path string, mode ...DeleteMode) error
|
2023-05-31 09:11:17 +00:00
|
|
|
|
|
|
|
// Return contents of directory at `path`.
|
2023-05-31 12:22:26 +00:00
|
|
|
ReadDir(ctx context.Context, path string) ([]fs.DirEntry, error)
|
2023-05-31 09:11:17 +00:00
|
|
|
|
|
|
|
// Creates directory at `path`, creating any intermediate directories as required.
|
|
|
|
Mkdir(ctx context.Context, path string) error
|
2023-06-01 18:23:22 +00:00
|
|
|
|
|
|
|
// Stat returns information about the file at `path`.
|
|
|
|
Stat(ctx context.Context, name string) (fs.FileInfo, error)
|
2022-12-14 14:37:14 +00:00
|
|
|
}
|