Documentation
¶
Overview ¶
Package fs implements blob.Store on a local directory tree. It is the "no bucket" storage option and the target of `backyard deploy --method rsync`, and also works on top of mounted buckets (gcsfuse, blobfuse2; see below for mountpoint-s3).
Keys map to files below the root directory ("sites/foo/index.html" → <root>/sites/foo/index.html). All access goes through os.Root handles, so no operation can reach outside the root. Beyond that, every directory on a key's path is opened one component at a time and must be a real directory (verified against its Lstat result); files are then created, renamed, read and removed by name relative to that directory handle. A concurrent writer below the root (e.g. a racing rsync) that swaps a directory for a symlink therefore cannot redirect a write, read or delete to another part of the tree (such as a database file kept in the root).
Writes are atomic: data is written to a hidden temporary file in the destination directory and renamed into place. Path segments starting with ".backyard-tmp-" are reserved for these files: such keys are rejected with blob.ErrInvalidKey and such entries are hidden from List.
Because files may be written by tools other than Backyard (rsync), object metadata is derived from the file itself:
- ETag is a hash of size and modification time (nanoseconds), so it changes whenever rsync replaces a file. Put sets a fresh, unique mtime.
- Content type comes from blob.DetectContentType (extension, else sniffing); the contentType argument of Put is not persisted.
Symbolic links (rsync -a preserves them) are handled conservatively: a symlink is only followed when it is the last path component and its target is a relative path without ".." segments (so it resolves within the link's own directory subtree); chains are followed up to 8 links. Symlinked directories, absolute targets and targets containing ".." are never followed; such entries are invisible to Get/Stat/List. Directories reached through symlinks are never written to, listed or deleted from.
Writes need rename support, so the fs store cannot write on mountpoint-s3; use the s3 backend there.
The fs store cannot presign URLs; PresignPut and PresignGet return blob.ErrNotSupported (the deploy gateway serves self-hosted upload URLs instead).
Index ¶
- type Option
- type Store
- func (s *Store) Close() error
- func (s *Store) Delete(ctx context.Context, key string) error
- func (s *Store) DeletePrefix(ctx context.Context, prefix string) error
- func (s *Store) Describe() blob.Description
- func (s *Store) Dir() string
- func (s *Store) Get(ctx context.Context, key string) (io.ReadCloser, *blob.ObjectInfo, error)
- func (s *Store) GetRange(ctx context.Context, key string, offset, length int64) (io.ReadCloser, *blob.ObjectInfo, error)
- func (s *Store) List(ctx context.Context, prefix, delimiter string) (*blob.ListResult, error)
- func (s *Store) Ping(ctx context.Context) error
- func (s *Store) PresignGet(_ context.Context, key string, _ time.Duration) (*blob.PresignedRequest, error)
- func (s *Store) PresignPut(_ context.Context, key string, _ blob.PresignPutOptions, _ time.Duration) (*blob.PresignedRequest, error)
- func (s *Store) Put(ctx context.Context, key string, r io.Reader, size int64, contentType string) (*blob.ObjectInfo, error)
- func (s *Store) Stat(ctx context.Context, key string) (*blob.ObjectInfo, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Option ¶
type Option func(*Store)
Option configures a Store.
func WithFsync ¶
WithFsync makes Put fsync the file before renaming it into place and the directory afterwards (durable, slower). Default off.
func WithLogger ¶
WithLogger sets the logger (default slog.Default()).
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is a blob.Store backed by a local directory. It is safe for concurrent use.
func (*Store) Delete ¶
Delete removes an object; missing objects (and directories) are ignored. A symlink key removes the link, never its target.
func (*Store) DeletePrefix ¶
DeletePrefix removes every object whose key starts with prefix and prunes directories left empty. Symlinks are removed, never followed. An empty prefix is rejected.
func (*Store) Describe ¶
func (s *Store) Describe() blob.Description
Describe returns {type: "fs"}; the local path is deliberately not exposed.
func (*Store) Get ¶
func (s *Store) Get(ctx context.Context, key string) (io.ReadCloser, *blob.ObjectInfo, error)
Get opens an object for reading.
func (*Store) GetRange ¶
func (s *Store) GetRange(ctx context.Context, key string, offset, length int64) (io.ReadCloser, *blob.ObjectInfo, error)
GetRange reads length bytes from offset (length < 0 = to the end). The returned ObjectInfo describes the whole object. Ranges past the end yield an empty body.
func (*Store) List ¶
List returns objects under prefix sorted by key. With delimiter "/", sub-directories that contain at least one object are returned as Prefixes.
func (*Store) PresignGet ¶
func (s *Store) PresignGet(_ context.Context, key string, _ time.Duration) (*blob.PresignedRequest, error)
PresignGet is not supported by the fs backend.
func (*Store) PresignPut ¶
func (s *Store) PresignPut(_ context.Context, key string, _ blob.PresignPutOptions, _ time.Duration) (*blob.PresignedRequest, error)
PresignPut is not supported by the fs backend.