Steps 12 & 12b: gRPC server and directory recursion + mirror.
Step 12: GardenSync gRPC server with 5 RPC handlers — PushManifest (timestamp comparison, missing blob detection), PushBlobs (chunked streaming, manifest replacement), PullManifest, PullBlobs, Prune. Added store.List() and garden.ListBlobs()/DeleteBlob() for prune. In-process tests via bufconn. Step 12b: Add now recurses directories (walks files/symlinks, skips dir entries). Mirror up syncs filesystem → manifest (add new, remove deleted, rehash changed). Mirror down syncs manifest → filesystem (restore + delete untracked with optional confirm). 7 tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -131,6 +131,32 @@ func (s *Store) Delete(hash string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// List returns all blob hashes in the store by walking the blobs directory.
|
||||
func (s *Store) List() ([]string, error) {
|
||||
blobsDir := filepath.Join(s.root, "blobs")
|
||||
var hashes []string
|
||||
err := filepath.WalkDir(blobsDir, func(path string, d os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
name := d.Name()
|
||||
if validHash(name) {
|
||||
hashes = append(hashes, name)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("store: listing blobs: %w", err)
|
||||
}
|
||||
return hashes, nil
|
||||
}
|
||||
|
||||
// blobPath returns the filesystem path for a blob with the given hash.
|
||||
// Layout: blobs/<first 2 hex chars>/<next 2 hex chars>/<full 64-char hash>
|
||||
func (s *Store) blobPath(hash string) string {
|
||||
|
||||
Reference in New Issue
Block a user