diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5a47e9a --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +.PHONY: proto build test lint clean + +proto: + protoc \ + --go_out=. --go_opt=module=github.com/kisom/sgard \ + --go-grpc_out=. --go-grpc_opt=module=github.com/kisom/sgard \ + -I proto \ + proto/sgard/v1/sgard.proto + +build: + go build ./... + +test: + go test ./... + +lint: + golangci-lint run ./... + +clean: + rm -f sgard diff --git a/PROGRESS.md b/PROGRESS.md index c468871..17d6804 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -7,7 +7,7 @@ ARCHITECTURE.md for design details. ## Current Status -**Phase:** Phase 1 complete (Steps 1–8). All local commands implemented. +**Phase:** Phase 2 in progress. Step 9 complete, ready for Steps 10+11. **Last updated:** 2026-03-23 @@ -38,11 +38,11 @@ ARCHITECTURE.md for design details. ## In Progress -(none) +Phase 2: gRPC Remote Sync. ## Up Next -Phase 1 is complete. Future work: blob durability, gRPC remote mode. +Steps 10 (Garden accessors) + 11 (proto-manifest conversion) — can be parallel. ## Known Issues / Decisions Deferred @@ -67,3 +67,5 @@ Phase 1 is complete. Future work: blob durability, gRPC remote mode. | 2026-03-23 | 7 | Remaining commands complete. Remove, Verify, List, Diff — 10 tests across 4 parallel units. | | 2026-03-23 | 8 | Polish complete. golangci-lint, clockwork, e2e test, doc updates. | | 2026-03-23 | — | README, goreleaser config, version command, Nix flake, homebrew formula, release pipeline validated (v0.1.0–v0.1.2). | +| 2026-03-23 | — | v1.0.0 released. Docs updated for release. | +| 2026-03-23 | 9 | Proto definitions: 5 RPCs (Push/Pull manifest+blobs, Prune), generated sgardpb, Makefile, deps added. | diff --git a/PROJECT_PLAN.md b/PROJECT_PLAN.md index 6aaea5b..e495393 100644 --- a/PROJECT_PLAN.md +++ b/PROJECT_PLAN.md @@ -92,9 +92,82 @@ Depends on Step 5. - [x] Ensure `go vet ./...` and `go test ./...` pass clean - [x] Update CLAUDE.md, ARCHITECTURE.md, PROGRESS.md -## Future Steps (Not Phase 1) +## Phase 2: gRPC Remote Sync + +### Step 9: Proto Definitions + Code Gen + +- [x] Write `proto/sgard/v1/sgard.proto` — 5 RPCs (PushManifest, PushBlobs, PullManifest, PullBlobs, Prune), all messages +- [x] Add Makefile target for protoc code generation +- [x] Add grpc, protobuf, x/crypto deps to go.mod +- [x] Update flake.nix devShell with protoc tools +- [x] Verify: `go build ./sgardpb` compiles + +### Step 10: Garden Accessor Methods + +*Can be done in parallel with Step 11.* + +- [ ] `garden/garden.go`: `GetManifest()`, `BlobExists()`, `ReadBlob()`, `WriteBlob()`, `ReplaceManifest()` +- [ ] Tests for each accessor +- [ ] Verify: `go test ./garden/...` + +### Step 11: Proto-Manifest Conversion + +*Can be done in parallel with Step 10.* + +- [ ] `server/convert.go`: `ManifestToProto`, `ProtoToManifest`, entry helpers +- [ ] `server/convert_test.go`: round-trip test +- [ ] Verify: `go test ./server/...` + +### Step 12: Server Implementation (No Auth) + +Depends on Steps 9, 10, 11. + +- [ ] `server/server.go`: Server struct with RWMutex, 4 RPC handlers +- [ ] PushManifest: timestamp compare, compute missing blobs +- [ ] PushBlobs: receive stream, write to store, replace manifest +- [ ] PullManifest: return manifest +- [ ] PullBlobs: stream requested blobs (64 KiB chunks) +- [ ] `server/server_test.go`: in-process test with bufconn, push+pull between two repos + +### Step 13: Client Library (No Auth) + +Depends on Step 12. + +- [ ] `client/client.go`: Client struct, `Push()`, `Pull()` methods +- [ ] `client/client_test.go`: integration test against in-process server + +### Step 14: SSH Key Auth + +- [ ] `server/auth.go`: AuthInterceptor, parse authorized_keys, verify SSH signatures +- [ ] `client/auth.go`: LoadSigner (ssh-agent or key file), PerRPCCredentials +- [ ] `server/auth_test.go`: in-memory ed25519 key pair, reject unauthenticated +- [ ] `client/auth_test.go`: metadata generation test + +### Step 15: CLI Wiring + Prune + +Depends on Steps 13, 14. + +- [ ] `garden/prune.go`: `Prune() (int, error)` — collect referenced hashes from manifest, delete orphaned blobs, return count removed +- [ ] `garden/prune_test.go`: add file, remove it, prune removes orphaned blob +- [ ] `server/server.go`: add `Prune` RPC — server-side prune, returns count +- [ ] `proto/sgard/v1/sgard.proto`: add `rpc Prune(PruneRequest) returns (PruneResponse)` +- [ ] `client/client.go`: add `Prune()` method +- [ ] `cmd/sgard/prune.go`: local prune; with `--remote` flag prunes remote instead +- [ ] `cmd/sgard/main.go`: add `--remote`, `--ssh-key` persistent flags +- [ ] `cmd/sgard/push.go`, `cmd/sgard/pull.go` +- [ ] `cmd/sgardd/main.go`: flags, garden open, auth interceptor, gRPC serve +- [ ] Verify: both binaries compile + +### Step 16: Polish + Release + +- [ ] Update ARCHITECTURE.md, README.md, CLAUDE.md, PROGRESS.md +- [ ] Update flake.nix (add sgardd, protoc to devShell) +- [ ] Update .goreleaser.yaml (add sgardd build) +- [ ] E2e integration test: init two repos, push from one, pull into other +- [ ] Verify: all tests pass, full push/pull cycle works + +## Future Steps (Not Phase 2) -- Blob durability (backup/replication strategy) -- gRPC remote mode (push/pull/serve) -- Proto definitions for wire format - Shell completion via cobra +- TLS transport (optional --tls-cert/--tls-key on sgardd) +- Multiple repo support on server diff --git a/flake.nix b/flake.nix index ea55456..64b56c9 100644 --- a/flake.nix +++ b/flake.nix @@ -36,6 +36,9 @@ buildInputs = with pkgs; [ go golangci-lint + protobuf + protoc-gen-go + protoc-gen-go-grpc ]; }; } diff --git a/go.mod b/go.mod index 4faf47e..0083bcb 100644 --- a/go.mod +++ b/go.mod @@ -7,5 +7,12 @@ require ( github.com/jonboulle/clockwork v0.5.0 // indirect github.com/spf13/cobra v1.10.2 // indirect github.com/spf13/pflag v1.0.9 // indirect + golang.org/x/crypto v0.49.0 // indirect + golang.org/x/net v0.51.0 // indirect + golang.org/x/sys v0.42.0 // indirect + golang.org/x/text v0.35.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect + google.golang.org/grpc v1.79.3 // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 722a4c0..89ff90f 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,20 @@ github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiT github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= +golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= +golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= +google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/proto/sgard/v1/sgard.proto b/proto/sgard/v1/sgard.proto new file mode 100644 index 0000000..f25453b --- /dev/null +++ b/proto/sgard/v1/sgard.proto @@ -0,0 +1,97 @@ +syntax = "proto3"; + +package sgard.v1; + +option go_package = "github.com/kisom/sgard/sgardpb"; + +import "google/protobuf/timestamp.proto"; + +// ManifestEntry mirrors manifest.Entry from the YAML model. +message ManifestEntry { + string path = 1; + string hash = 2; + string type = 3; // "file", "directory", "link" + string mode = 4; + string target = 5; + google.protobuf.Timestamp updated = 6; +} + +// Manifest mirrors the top-level manifest.Manifest. +message Manifest { + int32 version = 1; + google.protobuf.Timestamp created = 2; + google.protobuf.Timestamp updated = 3; + string message = 4; + repeated ManifestEntry files = 5; +} + +// BlobChunk is one piece of a streamed blob. The first chunk for a given +// hash carries the hash field; subsequent chunks omit it. +message BlobChunk { + string hash = 1; // SHA-256 hex, present on the first chunk of each blob + bytes data = 2; // up to 64 KiB per chunk +} + +// Push messages. + +message PushManifestRequest { + Manifest manifest = 1; +} + +message PushManifestResponse { + enum Decision { + DECISION_UNSPECIFIED = 0; + ACCEPTED = 1; // server is older; push proceeds + REJECTED = 2; // server is newer; client should pull + UP_TO_DATE = 3; // timestamps match; nothing to do + } + Decision decision = 1; + repeated string missing_blobs = 2; // hashes the server needs + google.protobuf.Timestamp server_updated = 3; +} + +message PushBlobsRequest { + BlobChunk chunk = 1; +} + +message PushBlobsResponse { + int32 blobs_received = 1; +} + +// Pull messages. + +message PullManifestRequest {} + +message PullManifestResponse { + Manifest manifest = 1; +} + +message PullBlobsRequest { + repeated string hashes = 1; // blobs the client needs +} + +message PullBlobsResponse { + BlobChunk chunk = 1; +} + +// Prune messages. + +message PruneRequest {} + +message PruneResponse { + int32 blobs_removed = 1; +} + +// GardenSync is the sgard remote sync service. +service GardenSync { + // Push flow: send manifest, then stream missing blobs. + rpc PushManifest(PushManifestRequest) returns (PushManifestResponse); + rpc PushBlobs(stream PushBlobsRequest) returns (PushBlobsResponse); + + // Pull flow: get manifest, then stream requested blobs. + rpc PullManifest(PullManifestRequest) returns (PullManifestResponse); + rpc PullBlobs(PullBlobsRequest) returns (stream PullBlobsResponse); + + // Prune removes orphaned blobs on the server. + rpc Prune(PruneRequest) returns (PruneResponse); +} diff --git a/sgardpb/sgard.pb.go b/sgardpb/sgard.pb.go new file mode 100644 index 0000000..0b78166 --- /dev/null +++ b/sgardpb/sgard.pb.go @@ -0,0 +1,870 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.10 +// protoc v6.32.1 +// source: sgard/v1/sgard.proto + +package sgardpb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type PushManifestResponse_Decision int32 + +const ( + PushManifestResponse_DECISION_UNSPECIFIED PushManifestResponse_Decision = 0 + PushManifestResponse_ACCEPTED PushManifestResponse_Decision = 1 // server is older; push proceeds + PushManifestResponse_REJECTED PushManifestResponse_Decision = 2 // server is newer; client should pull + PushManifestResponse_UP_TO_DATE PushManifestResponse_Decision = 3 // timestamps match; nothing to do +) + +// Enum value maps for PushManifestResponse_Decision. +var ( + PushManifestResponse_Decision_name = map[int32]string{ + 0: "DECISION_UNSPECIFIED", + 1: "ACCEPTED", + 2: "REJECTED", + 3: "UP_TO_DATE", + } + PushManifestResponse_Decision_value = map[string]int32{ + "DECISION_UNSPECIFIED": 0, + "ACCEPTED": 1, + "REJECTED": 2, + "UP_TO_DATE": 3, + } +) + +func (x PushManifestResponse_Decision) Enum() *PushManifestResponse_Decision { + p := new(PushManifestResponse_Decision) + *p = x + return p +} + +func (x PushManifestResponse_Decision) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PushManifestResponse_Decision) Descriptor() protoreflect.EnumDescriptor { + return file_sgard_v1_sgard_proto_enumTypes[0].Descriptor() +} + +func (PushManifestResponse_Decision) Type() protoreflect.EnumType { + return &file_sgard_v1_sgard_proto_enumTypes[0] +} + +func (x PushManifestResponse_Decision) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PushManifestResponse_Decision.Descriptor instead. +func (PushManifestResponse_Decision) EnumDescriptor() ([]byte, []int) { + return file_sgard_v1_sgard_proto_rawDescGZIP(), []int{4, 0} +} + +// ManifestEntry mirrors manifest.Entry from the YAML model. +type ManifestEntry struct { + state protoimpl.MessageState `protogen:"open.v1"` + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + Hash string `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` + Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` // "file", "directory", "link" + Mode string `protobuf:"bytes,4,opt,name=mode,proto3" json:"mode,omitempty"` + Target string `protobuf:"bytes,5,opt,name=target,proto3" json:"target,omitempty"` + Updated *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=updated,proto3" json:"updated,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ManifestEntry) Reset() { + *x = ManifestEntry{} + mi := &file_sgard_v1_sgard_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ManifestEntry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ManifestEntry) ProtoMessage() {} + +func (x *ManifestEntry) ProtoReflect() protoreflect.Message { + mi := &file_sgard_v1_sgard_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ManifestEntry.ProtoReflect.Descriptor instead. +func (*ManifestEntry) Descriptor() ([]byte, []int) { + return file_sgard_v1_sgard_proto_rawDescGZIP(), []int{0} +} + +func (x *ManifestEntry) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *ManifestEntry) GetHash() string { + if x != nil { + return x.Hash + } + return "" +} + +func (x *ManifestEntry) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *ManifestEntry) GetMode() string { + if x != nil { + return x.Mode + } + return "" +} + +func (x *ManifestEntry) GetTarget() string { + if x != nil { + return x.Target + } + return "" +} + +func (x *ManifestEntry) GetUpdated() *timestamppb.Timestamp { + if x != nil { + return x.Updated + } + return nil +} + +// Manifest mirrors the top-level manifest.Manifest. +type Manifest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Version int32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` + Created *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=created,proto3" json:"created,omitempty"` + Updated *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=updated,proto3" json:"updated,omitempty"` + Message string `protobuf:"bytes,4,opt,name=message,proto3" json:"message,omitempty"` + Files []*ManifestEntry `protobuf:"bytes,5,rep,name=files,proto3" json:"files,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Manifest) Reset() { + *x = Manifest{} + mi := &file_sgard_v1_sgard_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Manifest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Manifest) ProtoMessage() {} + +func (x *Manifest) ProtoReflect() protoreflect.Message { + mi := &file_sgard_v1_sgard_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Manifest.ProtoReflect.Descriptor instead. +func (*Manifest) Descriptor() ([]byte, []int) { + return file_sgard_v1_sgard_proto_rawDescGZIP(), []int{1} +} + +func (x *Manifest) GetVersion() int32 { + if x != nil { + return x.Version + } + return 0 +} + +func (x *Manifest) GetCreated() *timestamppb.Timestamp { + if x != nil { + return x.Created + } + return nil +} + +func (x *Manifest) GetUpdated() *timestamppb.Timestamp { + if x != nil { + return x.Updated + } + return nil +} + +func (x *Manifest) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *Manifest) GetFiles() []*ManifestEntry { + if x != nil { + return x.Files + } + return nil +} + +// BlobChunk is one piece of a streamed blob. The first chunk for a given +// hash carries the hash field; subsequent chunks omit it. +type BlobChunk struct { + state protoimpl.MessageState `protogen:"open.v1"` + Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` // SHA-256 hex, present on the first chunk of each blob + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` // up to 64 KiB per chunk + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BlobChunk) Reset() { + *x = BlobChunk{} + mi := &file_sgard_v1_sgard_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BlobChunk) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlobChunk) ProtoMessage() {} + +func (x *BlobChunk) ProtoReflect() protoreflect.Message { + mi := &file_sgard_v1_sgard_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BlobChunk.ProtoReflect.Descriptor instead. +func (*BlobChunk) Descriptor() ([]byte, []int) { + return file_sgard_v1_sgard_proto_rawDescGZIP(), []int{2} +} + +func (x *BlobChunk) GetHash() string { + if x != nil { + return x.Hash + } + return "" +} + +func (x *BlobChunk) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +type PushManifestRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Manifest *Manifest `protobuf:"bytes,1,opt,name=manifest,proto3" json:"manifest,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PushManifestRequest) Reset() { + *x = PushManifestRequest{} + mi := &file_sgard_v1_sgard_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PushManifestRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PushManifestRequest) ProtoMessage() {} + +func (x *PushManifestRequest) ProtoReflect() protoreflect.Message { + mi := &file_sgard_v1_sgard_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PushManifestRequest.ProtoReflect.Descriptor instead. +func (*PushManifestRequest) Descriptor() ([]byte, []int) { + return file_sgard_v1_sgard_proto_rawDescGZIP(), []int{3} +} + +func (x *PushManifestRequest) GetManifest() *Manifest { + if x != nil { + return x.Manifest + } + return nil +} + +type PushManifestResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Decision PushManifestResponse_Decision `protobuf:"varint,1,opt,name=decision,proto3,enum=sgard.v1.PushManifestResponse_Decision" json:"decision,omitempty"` + MissingBlobs []string `protobuf:"bytes,2,rep,name=missing_blobs,json=missingBlobs,proto3" json:"missing_blobs,omitempty"` // hashes the server needs + ServerUpdated *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=server_updated,json=serverUpdated,proto3" json:"server_updated,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PushManifestResponse) Reset() { + *x = PushManifestResponse{} + mi := &file_sgard_v1_sgard_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PushManifestResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PushManifestResponse) ProtoMessage() {} + +func (x *PushManifestResponse) ProtoReflect() protoreflect.Message { + mi := &file_sgard_v1_sgard_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PushManifestResponse.ProtoReflect.Descriptor instead. +func (*PushManifestResponse) Descriptor() ([]byte, []int) { + return file_sgard_v1_sgard_proto_rawDescGZIP(), []int{4} +} + +func (x *PushManifestResponse) GetDecision() PushManifestResponse_Decision { + if x != nil { + return x.Decision + } + return PushManifestResponse_DECISION_UNSPECIFIED +} + +func (x *PushManifestResponse) GetMissingBlobs() []string { + if x != nil { + return x.MissingBlobs + } + return nil +} + +func (x *PushManifestResponse) GetServerUpdated() *timestamppb.Timestamp { + if x != nil { + return x.ServerUpdated + } + return nil +} + +type PushBlobsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Chunk *BlobChunk `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PushBlobsRequest) Reset() { + *x = PushBlobsRequest{} + mi := &file_sgard_v1_sgard_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PushBlobsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PushBlobsRequest) ProtoMessage() {} + +func (x *PushBlobsRequest) ProtoReflect() protoreflect.Message { + mi := &file_sgard_v1_sgard_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PushBlobsRequest.ProtoReflect.Descriptor instead. +func (*PushBlobsRequest) Descriptor() ([]byte, []int) { + return file_sgard_v1_sgard_proto_rawDescGZIP(), []int{5} +} + +func (x *PushBlobsRequest) GetChunk() *BlobChunk { + if x != nil { + return x.Chunk + } + return nil +} + +type PushBlobsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + BlobsReceived int32 `protobuf:"varint,1,opt,name=blobs_received,json=blobsReceived,proto3" json:"blobs_received,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PushBlobsResponse) Reset() { + *x = PushBlobsResponse{} + mi := &file_sgard_v1_sgard_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PushBlobsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PushBlobsResponse) ProtoMessage() {} + +func (x *PushBlobsResponse) ProtoReflect() protoreflect.Message { + mi := &file_sgard_v1_sgard_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PushBlobsResponse.ProtoReflect.Descriptor instead. +func (*PushBlobsResponse) Descriptor() ([]byte, []int) { + return file_sgard_v1_sgard_proto_rawDescGZIP(), []int{6} +} + +func (x *PushBlobsResponse) GetBlobsReceived() int32 { + if x != nil { + return x.BlobsReceived + } + return 0 +} + +type PullManifestRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PullManifestRequest) Reset() { + *x = PullManifestRequest{} + mi := &file_sgard_v1_sgard_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PullManifestRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PullManifestRequest) ProtoMessage() {} + +func (x *PullManifestRequest) ProtoReflect() protoreflect.Message { + mi := &file_sgard_v1_sgard_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PullManifestRequest.ProtoReflect.Descriptor instead. +func (*PullManifestRequest) Descriptor() ([]byte, []int) { + return file_sgard_v1_sgard_proto_rawDescGZIP(), []int{7} +} + +type PullManifestResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Manifest *Manifest `protobuf:"bytes,1,opt,name=manifest,proto3" json:"manifest,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PullManifestResponse) Reset() { + *x = PullManifestResponse{} + mi := &file_sgard_v1_sgard_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PullManifestResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PullManifestResponse) ProtoMessage() {} + +func (x *PullManifestResponse) ProtoReflect() protoreflect.Message { + mi := &file_sgard_v1_sgard_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PullManifestResponse.ProtoReflect.Descriptor instead. +func (*PullManifestResponse) Descriptor() ([]byte, []int) { + return file_sgard_v1_sgard_proto_rawDescGZIP(), []int{8} +} + +func (x *PullManifestResponse) GetManifest() *Manifest { + if x != nil { + return x.Manifest + } + return nil +} + +type PullBlobsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Hashes []string `protobuf:"bytes,1,rep,name=hashes,proto3" json:"hashes,omitempty"` // blobs the client needs + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PullBlobsRequest) Reset() { + *x = PullBlobsRequest{} + mi := &file_sgard_v1_sgard_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PullBlobsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PullBlobsRequest) ProtoMessage() {} + +func (x *PullBlobsRequest) ProtoReflect() protoreflect.Message { + mi := &file_sgard_v1_sgard_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PullBlobsRequest.ProtoReflect.Descriptor instead. +func (*PullBlobsRequest) Descriptor() ([]byte, []int) { + return file_sgard_v1_sgard_proto_rawDescGZIP(), []int{9} +} + +func (x *PullBlobsRequest) GetHashes() []string { + if x != nil { + return x.Hashes + } + return nil +} + +type PullBlobsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Chunk *BlobChunk `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PullBlobsResponse) Reset() { + *x = PullBlobsResponse{} + mi := &file_sgard_v1_sgard_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PullBlobsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PullBlobsResponse) ProtoMessage() {} + +func (x *PullBlobsResponse) ProtoReflect() protoreflect.Message { + mi := &file_sgard_v1_sgard_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PullBlobsResponse.ProtoReflect.Descriptor instead. +func (*PullBlobsResponse) Descriptor() ([]byte, []int) { + return file_sgard_v1_sgard_proto_rawDescGZIP(), []int{10} +} + +func (x *PullBlobsResponse) GetChunk() *BlobChunk { + if x != nil { + return x.Chunk + } + return nil +} + +type PruneRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PruneRequest) Reset() { + *x = PruneRequest{} + mi := &file_sgard_v1_sgard_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PruneRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PruneRequest) ProtoMessage() {} + +func (x *PruneRequest) ProtoReflect() protoreflect.Message { + mi := &file_sgard_v1_sgard_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PruneRequest.ProtoReflect.Descriptor instead. +func (*PruneRequest) Descriptor() ([]byte, []int) { + return file_sgard_v1_sgard_proto_rawDescGZIP(), []int{11} +} + +type PruneResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + BlobsRemoved int32 `protobuf:"varint,1,opt,name=blobs_removed,json=blobsRemoved,proto3" json:"blobs_removed,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PruneResponse) Reset() { + *x = PruneResponse{} + mi := &file_sgard_v1_sgard_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PruneResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PruneResponse) ProtoMessage() {} + +func (x *PruneResponse) ProtoReflect() protoreflect.Message { + mi := &file_sgard_v1_sgard_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PruneResponse.ProtoReflect.Descriptor instead. +func (*PruneResponse) Descriptor() ([]byte, []int) { + return file_sgard_v1_sgard_proto_rawDescGZIP(), []int{12} +} + +func (x *PruneResponse) GetBlobsRemoved() int32 { + if x != nil { + return x.BlobsRemoved + } + return 0 +} + +var File_sgard_v1_sgard_proto protoreflect.FileDescriptor + +const file_sgard_v1_sgard_proto_rawDesc = "" + + "\n" + + "\x14sgard/v1/sgard.proto\x12\bsgard.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"\xad\x01\n" + + "\rManifestEntry\x12\x12\n" + + "\x04path\x18\x01 \x01(\tR\x04path\x12\x12\n" + + "\x04hash\x18\x02 \x01(\tR\x04hash\x12\x12\n" + + "\x04type\x18\x03 \x01(\tR\x04type\x12\x12\n" + + "\x04mode\x18\x04 \x01(\tR\x04mode\x12\x16\n" + + "\x06target\x18\x05 \x01(\tR\x06target\x124\n" + + "\aupdated\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\aupdated\"\xd9\x01\n" + + "\bManifest\x12\x18\n" + + "\aversion\x18\x01 \x01(\x05R\aversion\x124\n" + + "\acreated\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\acreated\x124\n" + + "\aupdated\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\aupdated\x12\x18\n" + + "\amessage\x18\x04 \x01(\tR\amessage\x12-\n" + + "\x05files\x18\x05 \x03(\v2\x17.sgard.v1.ManifestEntryR\x05files\"3\n" + + "\tBlobChunk\x12\x12\n" + + "\x04hash\x18\x01 \x01(\tR\x04hash\x12\x12\n" + + "\x04data\x18\x02 \x01(\fR\x04data\"E\n" + + "\x13PushManifestRequest\x12.\n" + + "\bmanifest\x18\x01 \x01(\v2\x12.sgard.v1.ManifestR\bmanifest\"\x95\x02\n" + + "\x14PushManifestResponse\x12C\n" + + "\bdecision\x18\x01 \x01(\x0e2'.sgard.v1.PushManifestResponse.DecisionR\bdecision\x12#\n" + + "\rmissing_blobs\x18\x02 \x03(\tR\fmissingBlobs\x12A\n" + + "\x0eserver_updated\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\rserverUpdated\"P\n" + + "\bDecision\x12\x18\n" + + "\x14DECISION_UNSPECIFIED\x10\x00\x12\f\n" + + "\bACCEPTED\x10\x01\x12\f\n" + + "\bREJECTED\x10\x02\x12\x0e\n" + + "\n" + + "UP_TO_DATE\x10\x03\"=\n" + + "\x10PushBlobsRequest\x12)\n" + + "\x05chunk\x18\x01 \x01(\v2\x13.sgard.v1.BlobChunkR\x05chunk\":\n" + + "\x11PushBlobsResponse\x12%\n" + + "\x0eblobs_received\x18\x01 \x01(\x05R\rblobsReceived\"\x15\n" + + "\x13PullManifestRequest\"F\n" + + "\x14PullManifestResponse\x12.\n" + + "\bmanifest\x18\x01 \x01(\v2\x12.sgard.v1.ManifestR\bmanifest\"*\n" + + "\x10PullBlobsRequest\x12\x16\n" + + "\x06hashes\x18\x01 \x03(\tR\x06hashes\">\n" + + "\x11PullBlobsResponse\x12)\n" + + "\x05chunk\x18\x01 \x01(\v2\x13.sgard.v1.BlobChunkR\x05chunk\"\x0e\n" + + "\fPruneRequest\"4\n" + + "\rPruneResponse\x12#\n" + + "\rblobs_removed\x18\x01 \x01(\x05R\fblobsRemoved2\xf4\x02\n" + + "\n" + + "GardenSync\x12M\n" + + "\fPushManifest\x12\x1d.sgard.v1.PushManifestRequest\x1a\x1e.sgard.v1.PushManifestResponse\x12F\n" + + "\tPushBlobs\x12\x1a.sgard.v1.PushBlobsRequest\x1a\x1b.sgard.v1.PushBlobsResponse(\x01\x12M\n" + + "\fPullManifest\x12\x1d.sgard.v1.PullManifestRequest\x1a\x1e.sgard.v1.PullManifestResponse\x12F\n" + + "\tPullBlobs\x12\x1a.sgard.v1.PullBlobsRequest\x1a\x1b.sgard.v1.PullBlobsResponse0\x01\x128\n" + + "\x05Prune\x12\x16.sgard.v1.PruneRequest\x1a\x17.sgard.v1.PruneResponseB Z\x1egithub.com/kisom/sgard/sgardpbb\x06proto3" + +var ( + file_sgard_v1_sgard_proto_rawDescOnce sync.Once + file_sgard_v1_sgard_proto_rawDescData []byte +) + +func file_sgard_v1_sgard_proto_rawDescGZIP() []byte { + file_sgard_v1_sgard_proto_rawDescOnce.Do(func() { + file_sgard_v1_sgard_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_sgard_v1_sgard_proto_rawDesc), len(file_sgard_v1_sgard_proto_rawDesc))) + }) + return file_sgard_v1_sgard_proto_rawDescData +} + +var file_sgard_v1_sgard_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_sgard_v1_sgard_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_sgard_v1_sgard_proto_goTypes = []any{ + (PushManifestResponse_Decision)(0), // 0: sgard.v1.PushManifestResponse.Decision + (*ManifestEntry)(nil), // 1: sgard.v1.ManifestEntry + (*Manifest)(nil), // 2: sgard.v1.Manifest + (*BlobChunk)(nil), // 3: sgard.v1.BlobChunk + (*PushManifestRequest)(nil), // 4: sgard.v1.PushManifestRequest + (*PushManifestResponse)(nil), // 5: sgard.v1.PushManifestResponse + (*PushBlobsRequest)(nil), // 6: sgard.v1.PushBlobsRequest + (*PushBlobsResponse)(nil), // 7: sgard.v1.PushBlobsResponse + (*PullManifestRequest)(nil), // 8: sgard.v1.PullManifestRequest + (*PullManifestResponse)(nil), // 9: sgard.v1.PullManifestResponse + (*PullBlobsRequest)(nil), // 10: sgard.v1.PullBlobsRequest + (*PullBlobsResponse)(nil), // 11: sgard.v1.PullBlobsResponse + (*PruneRequest)(nil), // 12: sgard.v1.PruneRequest + (*PruneResponse)(nil), // 13: sgard.v1.PruneResponse + (*timestamppb.Timestamp)(nil), // 14: google.protobuf.Timestamp +} +var file_sgard_v1_sgard_proto_depIdxs = []int32{ + 14, // 0: sgard.v1.ManifestEntry.updated:type_name -> google.protobuf.Timestamp + 14, // 1: sgard.v1.Manifest.created:type_name -> google.protobuf.Timestamp + 14, // 2: sgard.v1.Manifest.updated:type_name -> google.protobuf.Timestamp + 1, // 3: sgard.v1.Manifest.files:type_name -> sgard.v1.ManifestEntry + 2, // 4: sgard.v1.PushManifestRequest.manifest:type_name -> sgard.v1.Manifest + 0, // 5: sgard.v1.PushManifestResponse.decision:type_name -> sgard.v1.PushManifestResponse.Decision + 14, // 6: sgard.v1.PushManifestResponse.server_updated:type_name -> google.protobuf.Timestamp + 3, // 7: sgard.v1.PushBlobsRequest.chunk:type_name -> sgard.v1.BlobChunk + 2, // 8: sgard.v1.PullManifestResponse.manifest:type_name -> sgard.v1.Manifest + 3, // 9: sgard.v1.PullBlobsResponse.chunk:type_name -> sgard.v1.BlobChunk + 4, // 10: sgard.v1.GardenSync.PushManifest:input_type -> sgard.v1.PushManifestRequest + 6, // 11: sgard.v1.GardenSync.PushBlobs:input_type -> sgard.v1.PushBlobsRequest + 8, // 12: sgard.v1.GardenSync.PullManifest:input_type -> sgard.v1.PullManifestRequest + 10, // 13: sgard.v1.GardenSync.PullBlobs:input_type -> sgard.v1.PullBlobsRequest + 12, // 14: sgard.v1.GardenSync.Prune:input_type -> sgard.v1.PruneRequest + 5, // 15: sgard.v1.GardenSync.PushManifest:output_type -> sgard.v1.PushManifestResponse + 7, // 16: sgard.v1.GardenSync.PushBlobs:output_type -> sgard.v1.PushBlobsResponse + 9, // 17: sgard.v1.GardenSync.PullManifest:output_type -> sgard.v1.PullManifestResponse + 11, // 18: sgard.v1.GardenSync.PullBlobs:output_type -> sgard.v1.PullBlobsResponse + 13, // 19: sgard.v1.GardenSync.Prune:output_type -> sgard.v1.PruneResponse + 15, // [15:20] is the sub-list for method output_type + 10, // [10:15] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name +} + +func init() { file_sgard_v1_sgard_proto_init() } +func file_sgard_v1_sgard_proto_init() { + if File_sgard_v1_sgard_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_sgard_v1_sgard_proto_rawDesc), len(file_sgard_v1_sgard_proto_rawDesc)), + NumEnums: 1, + NumMessages: 13, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_sgard_v1_sgard_proto_goTypes, + DependencyIndexes: file_sgard_v1_sgard_proto_depIdxs, + EnumInfos: file_sgard_v1_sgard_proto_enumTypes, + MessageInfos: file_sgard_v1_sgard_proto_msgTypes, + }.Build() + File_sgard_v1_sgard_proto = out.File + file_sgard_v1_sgard_proto_goTypes = nil + file_sgard_v1_sgard_proto_depIdxs = nil +} diff --git a/sgardpb/sgard_grpc.pb.go b/sgardpb/sgard_grpc.pb.go new file mode 100644 index 0000000..62d2477 --- /dev/null +++ b/sgardpb/sgard_grpc.pb.go @@ -0,0 +1,280 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc v6.32.1 +// source: sgard/v1/sgard.proto + +package sgardpb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + GardenSync_PushManifest_FullMethodName = "/sgard.v1.GardenSync/PushManifest" + GardenSync_PushBlobs_FullMethodName = "/sgard.v1.GardenSync/PushBlobs" + GardenSync_PullManifest_FullMethodName = "/sgard.v1.GardenSync/PullManifest" + GardenSync_PullBlobs_FullMethodName = "/sgard.v1.GardenSync/PullBlobs" + GardenSync_Prune_FullMethodName = "/sgard.v1.GardenSync/Prune" +) + +// GardenSyncClient is the client API for GardenSync service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// GardenSync is the sgard remote sync service. +type GardenSyncClient interface { + // Push flow: send manifest, then stream missing blobs. + PushManifest(ctx context.Context, in *PushManifestRequest, opts ...grpc.CallOption) (*PushManifestResponse, error) + PushBlobs(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[PushBlobsRequest, PushBlobsResponse], error) + // Pull flow: get manifest, then stream requested blobs. + PullManifest(ctx context.Context, in *PullManifestRequest, opts ...grpc.CallOption) (*PullManifestResponse, error) + PullBlobs(ctx context.Context, in *PullBlobsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PullBlobsResponse], error) + // Prune removes orphaned blobs on the server. + Prune(ctx context.Context, in *PruneRequest, opts ...grpc.CallOption) (*PruneResponse, error) +} + +type gardenSyncClient struct { + cc grpc.ClientConnInterface +} + +func NewGardenSyncClient(cc grpc.ClientConnInterface) GardenSyncClient { + return &gardenSyncClient{cc} +} + +func (c *gardenSyncClient) PushManifest(ctx context.Context, in *PushManifestRequest, opts ...grpc.CallOption) (*PushManifestResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PushManifestResponse) + err := c.cc.Invoke(ctx, GardenSync_PushManifest_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gardenSyncClient) PushBlobs(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[PushBlobsRequest, PushBlobsResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &GardenSync_ServiceDesc.Streams[0], GardenSync_PushBlobs_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[PushBlobsRequest, PushBlobsResponse]{ClientStream: stream} + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type GardenSync_PushBlobsClient = grpc.ClientStreamingClient[PushBlobsRequest, PushBlobsResponse] + +func (c *gardenSyncClient) PullManifest(ctx context.Context, in *PullManifestRequest, opts ...grpc.CallOption) (*PullManifestResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PullManifestResponse) + err := c.cc.Invoke(ctx, GardenSync_PullManifest_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gardenSyncClient) PullBlobs(ctx context.Context, in *PullBlobsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PullBlobsResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &GardenSync_ServiceDesc.Streams[1], GardenSync_PullBlobs_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[PullBlobsRequest, PullBlobsResponse]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type GardenSync_PullBlobsClient = grpc.ServerStreamingClient[PullBlobsResponse] + +func (c *gardenSyncClient) Prune(ctx context.Context, in *PruneRequest, opts ...grpc.CallOption) (*PruneResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PruneResponse) + err := c.cc.Invoke(ctx, GardenSync_Prune_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GardenSyncServer is the server API for GardenSync service. +// All implementations must embed UnimplementedGardenSyncServer +// for forward compatibility. +// +// GardenSync is the sgard remote sync service. +type GardenSyncServer interface { + // Push flow: send manifest, then stream missing blobs. + PushManifest(context.Context, *PushManifestRequest) (*PushManifestResponse, error) + PushBlobs(grpc.ClientStreamingServer[PushBlobsRequest, PushBlobsResponse]) error + // Pull flow: get manifest, then stream requested blobs. + PullManifest(context.Context, *PullManifestRequest) (*PullManifestResponse, error) + PullBlobs(*PullBlobsRequest, grpc.ServerStreamingServer[PullBlobsResponse]) error + // Prune removes orphaned blobs on the server. + Prune(context.Context, *PruneRequest) (*PruneResponse, error) + mustEmbedUnimplementedGardenSyncServer() +} + +// UnimplementedGardenSyncServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedGardenSyncServer struct{} + +func (UnimplementedGardenSyncServer) PushManifest(context.Context, *PushManifestRequest) (*PushManifestResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PushManifest not implemented") +} +func (UnimplementedGardenSyncServer) PushBlobs(grpc.ClientStreamingServer[PushBlobsRequest, PushBlobsResponse]) error { + return status.Errorf(codes.Unimplemented, "method PushBlobs not implemented") +} +func (UnimplementedGardenSyncServer) PullManifest(context.Context, *PullManifestRequest) (*PullManifestResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PullManifest not implemented") +} +func (UnimplementedGardenSyncServer) PullBlobs(*PullBlobsRequest, grpc.ServerStreamingServer[PullBlobsResponse]) error { + return status.Errorf(codes.Unimplemented, "method PullBlobs not implemented") +} +func (UnimplementedGardenSyncServer) Prune(context.Context, *PruneRequest) (*PruneResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Prune not implemented") +} +func (UnimplementedGardenSyncServer) mustEmbedUnimplementedGardenSyncServer() {} +func (UnimplementedGardenSyncServer) testEmbeddedByValue() {} + +// UnsafeGardenSyncServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GardenSyncServer will +// result in compilation errors. +type UnsafeGardenSyncServer interface { + mustEmbedUnimplementedGardenSyncServer() +} + +func RegisterGardenSyncServer(s grpc.ServiceRegistrar, srv GardenSyncServer) { + // If the following call pancis, it indicates UnimplementedGardenSyncServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&GardenSync_ServiceDesc, srv) +} + +func _GardenSync_PushManifest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PushManifestRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GardenSyncServer).PushManifest(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: GardenSync_PushManifest_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GardenSyncServer).PushManifest(ctx, req.(*PushManifestRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GardenSync_PushBlobs_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(GardenSyncServer).PushBlobs(&grpc.GenericServerStream[PushBlobsRequest, PushBlobsResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type GardenSync_PushBlobsServer = grpc.ClientStreamingServer[PushBlobsRequest, PushBlobsResponse] + +func _GardenSync_PullManifest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PullManifestRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GardenSyncServer).PullManifest(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: GardenSync_PullManifest_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GardenSyncServer).PullManifest(ctx, req.(*PullManifestRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GardenSync_PullBlobs_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(PullBlobsRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GardenSyncServer).PullBlobs(m, &grpc.GenericServerStream[PullBlobsRequest, PullBlobsResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type GardenSync_PullBlobsServer = grpc.ServerStreamingServer[PullBlobsResponse] + +func _GardenSync_Prune_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PruneRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GardenSyncServer).Prune(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: GardenSync_Prune_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GardenSyncServer).Prune(ctx, req.(*PruneRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// GardenSync_ServiceDesc is the grpc.ServiceDesc for GardenSync service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var GardenSync_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "sgard.v1.GardenSync", + HandlerType: (*GardenSyncServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "PushManifest", + Handler: _GardenSync_PushManifest_Handler, + }, + { + MethodName: "PullManifest", + Handler: _GardenSync_PullManifest_Handler, + }, + { + MethodName: "Prune", + Handler: _GardenSync_Prune_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "PushBlobs", + Handler: _GardenSync_PushBlobs_Handler, + ClientStreams: true, + }, + { + StreamName: "PullBlobs", + Handler: _GardenSync_PullBlobs_Handler, + ServerStreams: true, + }, + }, + Metadata: "sgard/v1/sgard.proto", +}