aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--object/store/errors.go8
-rw-r--r--object/store/quarantiner.go70
-rw-r--r--object/store/reader.go61
-rw-r--r--object/store/writer.go74
4 files changed, 213 insertions, 0 deletions
diff --git a/object/store/errors.go b/object/store/errors.go
new file mode 100644
index 00000000..12bb8b28
--- /dev/null
+++ b/object/store/errors.go
@@ -0,0 +1,8 @@
+package store
+
+import "errors"
+
+// ErrObjectNotFound indicates that an object does not exist in a backend.
+// This error must only be produced by object stores, when it has no
+// specified object ID, but no other unexpected conditions were encountered.
+var ErrObjectNotFound = errors.New("objectstore: object not found")
diff --git a/object/store/quarantiner.go b/object/store/quarantiner.go
new file mode 100644
index 00000000..4a2b7e02
--- /dev/null
+++ b/object/store/quarantiner.go
@@ -0,0 +1,70 @@
+package store
+
+// QuarantineBase is one quarantined write.
+// It is intended to be embedded.
+type QuarantineBase interface {
+ // Reader exposes the objects written into this quarantine.
+ Reader
+
+ // Promote publishes quarantined writes into their final destination.
+ //
+ // Promote invalidates the receiver.
+ Promote() error
+
+ // Discard abandons quarantined writes.
+ //
+ // Discard invalidates the receiver.
+ Discard() error
+}
+
+// Quarantine represents one quarantined write
+// that accepts both object-wise and pack-wise writes.
+type Quarantine interface {
+ QuarantineBase
+ Writer
+}
+
+// QuarantineOptions controls the options
+// for one coordinated quarantine creation.
+type QuarantineOptions struct {
+ Object ObjectQuarantineOptions
+ Pack PackQuarantineOptions
+}
+
+// Quarantiner creates coordinated quarantines
+// that accept both object-wise and pack-wise writes.
+type Quarantiner interface {
+ BeginQuarantine(opts QuarantineOptions) (Quarantine, error)
+}
+
+// ObjectQuarantine represents one quarantined object-wise write.
+type ObjectQuarantine interface {
+ QuarantineBase
+ ObjectWriter
+}
+
+// ObjectQuarantineOptions controls the options
+// for one object quarantine creation.
+type ObjectQuarantineOptions struct{}
+
+// ObjectQuarantiner creates quarantines
+// for object-wise writes.
+type ObjectQuarantiner interface {
+ BeginObjectQuarantine(opts ObjectQuarantineOptions) (ObjectQuarantine, error)
+}
+
+// PackQuarantine represents one quarantined pack-wise write.
+type PackQuarantine interface {
+ QuarantineBase
+ PackWriter
+}
+
+// PackQuarantineOptions controls the options
+// for one pack quarantine creation.
+type PackQuarantineOptions struct{}
+
+// PackQuarantiner creates quarantines
+// for pack-wise writes.
+type PackQuarantiner interface {
+ BeginPackQuarantine(opts PackQuarantineOptions) (PackQuarantine, error)
+}
diff --git a/object/store/reader.go b/object/store/reader.go
new file mode 100644
index 00000000..ac1a10ee
--- /dev/null
+++ b/object/store/reader.go
@@ -0,0 +1,61 @@
+package store
+
+import (
+ "io"
+
+ "codeberg.org/lindenii/furgit/object/id"
+ "codeberg.org/lindenii/furgit/object/typ"
+)
+
+// Reader reads Git objects by object ID.
+//
+// Methods may perform implementation-defined integrity verification
+// beyond successfully producing their documented result.
+//
+// Labels: MT-Safe.
+type Reader interface {
+ // ReadBytesFull reads a full serialized object as "type size\0content".
+ //
+ // In a valid repository,
+ // hashing this payload with the same algorithm
+ // yields the requested object ID.
+ // Users should treat this as an invariant;
+ // implementations should not re-verify it on every read.
+ //
+ // Labels: Life-Parent.
+ ReadBytesFull(id id.ObjectID) ([]byte, error)
+
+ // ReadBytesContent reads an object's type and content bytes.
+ //
+ // Labels: Life-Parent.
+ ReadBytesContent(id id.ObjectID) (typ.Type, []byte, error)
+
+ // ReadReaderFull reads a full serialized object stream
+ // as "type size\0content".
+ //
+ // Labels: Life-Parent, Close-Caller.
+ ReadReaderFull(id id.ObjectID) (io.ReadCloser, error)
+
+ // ReadReaderContent reads an object's type,
+ // declared content length, and content stream.
+ //
+ // Labels: Life-Parent, Close-Caller.
+ ReadReaderContent(id id.ObjectID) (typ.Type, int64, io.ReadCloser, error)
+
+ // ReadSize reads an object's declared content length.
+ //
+ // This is equivalent to ReadHeader(...).size;
+ // for some implementations, this may be cheaper than ReadHeader
+ // when callers do not need object type.
+ ReadSize(id id.ObjectID) (int64, error)
+
+ // ReadHeader reads an object's type and declared content length.
+ ReadHeader(id id.ObjectID) (typ.Type, int64, error)
+
+ // Refresh updates any backend-local discovery/cache view of on-disk objects.
+ //
+ // Backends without dynamic discovery should do nothing and return nil.
+ //
+ // TODO
+ Refresh() error
+}
diff --git a/object/store/writer.go b/object/store/writer.go
new file mode 100644
index 00000000..828237f5
--- /dev/null
+++ b/object/store/writer.go
@@ -0,0 +1,74 @@
+package store
+
+import (
+ "io"
+
+ "codeberg.org/lindenii/furgit/common/iowrap"
+ "codeberg.org/lindenii/furgit/object/id"
+ "codeberg.org/lindenii/furgit/object/typ"
+)
+
+// Writer represents a store
+// that could perform both pack ingestions
+// and individual object writes.
+type Writer interface {
+ PackWriter
+ ObjectWriter
+}
+
+// ObjectWriter writes individual Git objects.
+type ObjectWriter interface {
+ // WriteReaderContent writes one typed object content stream.
+ WriteReaderContent(ty typ.Type, size int64, src io.Reader) (id.ObjectID, error)
+
+ // WriteReaderFull writes one full serialized object stream as "type size\0content".
+ WriteReaderFull(src io.Reader) (id.ObjectID, error)
+
+ // WriteBytesContent writes one typed object content byte slice.
+ WriteBytesContent(ty typ.Type, content []byte) (id.ObjectID, error)
+
+ // WriteBytesFull writes one full serialized object byte slice as "type size\0content".
+ WriteBytesFull(raw []byte) (id.ObjectID, error)
+}
+
+// PackWriter writes Git pack streams.
+type PackWriter interface {
+ // WritePack ingests one pack stream,
+ // such that the objects contained therein
+ // become available in the relevant store.
+ WritePack(src io.Reader, opts PackWriteOptions) error
+}
+
+// PackWriteOptions controls one pack write operation.
+type PackWriteOptions struct {
+ // ThinBase supplies the wider object reader
+ // used to complete thin packs during ingestion.
+ //
+ // This is an option for the write operation
+ // rather than on a particular pack-backed store
+ // because any pack-accepting store
+ // is not generally expected to know
+ // the entire repository object universe around it.
+ // In a normal repository,
+ // thin bases usually come from a broader view
+ // such as mix(loose, packed),
+ // and should not be treated as
+ // a property of the destination pack-accepting store.
+ // Thus, in almost all pack-ingesting operations
+ // where thin bases are relevant,
+ // a thin base reader would be required,
+ // and hence it is included here.
+ //
+ // When nil,
+ // external thin-base repair is disabled,
+ // and unresolved thin deltas fail ingestion.
+ //
+ // TODO: Define the errors here?
+ ThinBase Reader
+
+ // Progress receives human-readable progress messages
+ // for packfile ingestion.
+ //
+ // When nil, no progress output is emitted.
+ Progress iowrap.WriteFlusher
+}