mirror of
https://github.com/beshu-tech/deltaglider.git
synced 2026-07-08 05:55:20 +02:00
Initial commit: DeltaGlider - S3-compatible storage with 99.9% compression
- Drop-in replacement for AWS S3 CLI (cp, ls, rm, sync commands) - Binary delta compression using xdelta3 - Hexagonal architecture with clean separation of concerns - Achieves 99.9% compression for versioned files - Full test suite with 100% passing tests - Python 3.11+ support
This commit is contained in:
@@ -20,7 +20,8 @@ class XdeltaAdapter(DiffPort):
|
||||
"-e", # encode
|
||||
"-f", # force overwrite
|
||||
"-9", # compression level
|
||||
"-s", str(base), # source file
|
||||
"-s",
|
||||
str(base), # source file
|
||||
str(target), # target file
|
||||
str(out), # output delta
|
||||
]
|
||||
@@ -40,7 +41,8 @@ class XdeltaAdapter(DiffPort):
|
||||
self.xdelta_path,
|
||||
"-d", # decode
|
||||
"-f", # force overwrite
|
||||
"-s", str(base), # source file
|
||||
"-s",
|
||||
str(base), # source file
|
||||
str(delta), # delta file
|
||||
str(out), # output file
|
||||
]
|
||||
|
||||
@@ -18,9 +18,7 @@ class StdLoggerAdapter(LoggerPort):
|
||||
|
||||
if not self.logger.handlers:
|
||||
handler = logging.StreamHandler(sys.stderr)
|
||||
formatter = logging.Formatter(
|
||||
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
||||
handler.setFormatter(formatter)
|
||||
self.logger.addHandler(handler)
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"""No-op metrics adapter."""
|
||||
|
||||
|
||||
from ..ports.metrics import MetricsPort
|
||||
|
||||
|
||||
|
||||
@@ -51,7 +51,12 @@ class S3StorageAdapter(StoragePort):
|
||||
|
||||
def list(self, prefix: str) -> Iterator[ObjectHead]:
|
||||
"""List objects by prefix."""
|
||||
bucket, prefix_key = self._parse_key(prefix)
|
||||
# Handle bucket-only prefix (e.g., "bucket" or "bucket/")
|
||||
if "/" not in prefix:
|
||||
bucket = prefix
|
||||
prefix_key = ""
|
||||
else:
|
||||
bucket, prefix_key = self._parse_key(prefix)
|
||||
|
||||
paginator = self.client.get_paginator("list_objects_v2")
|
||||
pages = paginator.paginate(Bucket=bucket, Prefix=prefix_key)
|
||||
@@ -69,7 +74,7 @@ class S3StorageAdapter(StoragePort):
|
||||
|
||||
try:
|
||||
response = self.client.get_object(Bucket=bucket, Key=object_key)
|
||||
return response["Body"]
|
||||
return response["Body"] # type: ignore[return-value]
|
||||
except ClientError as e:
|
||||
if e.response["Error"]["Code"] == "NoSuchKey":
|
||||
raise FileNotFoundError(f"Object not found: {key}") from e
|
||||
@@ -133,4 +138,3 @@ class S3StorageAdapter(StoragePort):
|
||||
"""Extract user metadata from S3 response."""
|
||||
# S3 returns user metadata as-is (already lowercase)
|
||||
return raw_metadata
|
||||
|
||||
|
||||
Reference in New Issue
Block a user