Skip to content

Commit 974fd52

Browse files
authored
Merge pull request #11 from londogard/copilot/implement-s3-import-command
fix: WIP
2 parents 92f62d4 + 9978987 commit 974fd52

14 files changed

Lines changed: 853 additions & 204 deletions

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,16 @@ uv run fluxel commit --repo /tmp/fluxel-demo -m "update"
109109

110110
uv run fluxel branch --repo /tmp/fluxel-demo experiment
111111
uv run fluxel diff --repo /tmp/fluxel-demo <from_ref> <to_ref>
112-
uv run fluxel rm --repo /tmp/fluxel-demo old-prefix -m "remove old files"
113-
uv run fluxel mv --repo /tmp/fluxel-demo raw/images curated/images -m "rename image prefix"
112+
113+
# Stage and commit metadata mutations
114+
uv run fluxel rm --repo /tmp/fluxel-demo old-prefix
115+
uv run fluxel mv --repo /tmp/fluxel-demo raw/images curated/images
116+
uv run fluxel status --repo /tmp/fluxel-demo
117+
uv run fluxel commit --repo /tmp/fluxel-demo -m "clean up old files and rename image prefix"
118+
119+
# Or commit metadata mutations directly with a message
120+
uv run fluxel rm --repo /tmp/fluxel-demo logs/2025 -m "remove old logs"
121+
uv run fluxel mv --repo /tmp/fluxel-demo incoming/images curated/images -m "reorganize images"
114122

115123
# remote repo metadata operations from the current working tree
116124
uv run fluxel branch --repo s3://my-bucket/datasets/demo feature

scripts/run_s3_integration.sh

100644100755
File mode changed.

src/fluxel/__init__.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
from .core import (
33
DEFAULT_CHUNK_SIZE,
44
AnalyticalIndexPaths,
5+
BlobTransferBackend,
56
LocalClientState,
67
CommitObject,
78
DiffEntry,
9+
FileEntry,
810
FluxelFileSystem,
911
FluxelLayout,
1012
FluxelRepository,
@@ -18,9 +20,10 @@
1820
ManifestReader,
1921
ManifestWriter,
2022
OptimisticLockError,
21-
RepositoryStore,
2223
RefConflictError,
2324
RemoveResult,
25+
S3BlobTransferBackend,
26+
S5CmdBlobTransferBackend,
2427
S3RepositoryStore,
2528
S3StorageBackend,
2629
StorageBackend,
@@ -34,6 +37,7 @@
3437
build_analytical_index,
3538
blob_relpath,
3639
branch,
40+
build_blob_transfer_backend,
3741
build_manifest_entries,
3842
commit,
3943
diff,
@@ -53,18 +57,22 @@
5357
__all__ = [
5458
"DEFAULT_CHUNK_SIZE",
5559
"AnalyticalIndexPaths",
60+
"BlobTransferBackend",
5661
"LocalClientState",
5762
"CommitObject",
5863
"DiffEntry",
5964
"FluxelFileSystem",
6065
"FluxelLayout",
6166
"FluxelRepository",
6267
"FluxelURI",
68+
"FileEntry",
6369
"BranchRefState",
6470
"MoveResult",
6571
"open_repository",
6672
"RefConflictError",
6773
"RemoveResult",
74+
"S3BlobTransferBackend",
75+
"S5CmdBlobTransferBackend",
6876
"StageChange",
6977
"StageStatus",
7078
"MergeResult",
@@ -85,6 +93,7 @@
8593
"blob_relpath",
8694
"add",
8795
"branch",
96+
"build_blob_transfer_backend",
8897
"build_manifest_entries",
8998
"build_parser",
9099
"commit",

src/fluxel/cli.py

Lines changed: 28 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,13 @@
1919
drop_analytical_index,
2020
import_s3,
2121
merge,
22-
move,
22+
move_staged,
2323
query_analytical_index,
24-
remove,
2524
rm,
2625
status,
2726
verify,
2827
)
2928

30-
3129
IdentityMode = Literal["blake3", "meta"]
3230
HANDLED_CLI_ERRORS = (
3331
BotoCoreError,
@@ -56,6 +54,11 @@ class CommitArgs:
5654
help="Commit only staged changes for a branch",
5755
)
5856
ref: str | None = None # Branch ref to update (defaults to current branch)
57+
transfer_backend: str | None = field(
58+
default=None,
59+
alias=["--transfer-backend", "--backend"],
60+
help="Blob transfer backend (boto3 or s5cmd)",
61+
)
5962

6063

6164
@dataclass
@@ -79,6 +82,11 @@ class ImportArgs:
7982
help="Repository path or URI",
8083
)
8184
ref: str | None = None # Branch ref to update (defaults to current branch)
85+
transfer_backend: str | None = field(
86+
default=None,
87+
alias=["--transfer-backend", "--backend"],
88+
help="Blob transfer backend (boto3 or s5cmd)",
89+
)
8290

8391

8492
@dataclass
@@ -101,16 +109,16 @@ class AddArgs:
101109
default=None,
102110
help="Branch ref for staging (defaults to current branch)",
103111
)
112+
transfer_backend: str | None = field(
113+
default=None,
114+
alias=["--transfer-backend", "--backend"],
115+
help="Blob transfer backend (boto3 or s5cmd)",
116+
)
104117

105118

106119
@dataclass
107120
class RmArgs:
108121
paths: list[str] = field(positional=True, nargs="+", help="Paths to remove")
109-
message: str | None = field(
110-
default=None,
111-
alias=["-m", "--message"],
112-
help="Commit message for a metadata-only removal",
113-
)
114122
root: str = field(
115123
default=".",
116124
alias="--repo",
@@ -120,10 +128,6 @@ class RmArgs:
120128
default=None,
121129
help="Branch ref for staging (defaults to current branch)",
122130
)
123-
staged: bool = flag(
124-
False,
125-
help="Stage removals instead of writing a metadata-only commit",
126-
)
127131

128132

129133
@dataclass
@@ -133,15 +137,14 @@ class MoveArgs:
133137
positional=True,
134138
help="Destination path or prefix",
135139
)
136-
message: str = field(alias=["-m", "--message"], help="Commit message")
137140
root: str = field(
138141
default=".",
139142
alias="--repo",
140143
help="Repository path or URI",
141144
)
142145
ref: str | None = field(
143146
default=None,
144-
help="Branch ref to update (defaults to current branch)",
147+
help="Branch ref for staging (defaults to current branch)",
145148
)
146149

147150

@@ -209,6 +212,11 @@ class VerifyArgs:
209212
alias="--dry-run",
210213
help="Report entries that would be verified without writing blobs or commits",
211214
)
215+
transfer_backend: str | None = field(
216+
default=None,
217+
alias=["--transfer-backend", "--backend"],
218+
help="Blob transfer backend (boto3 or s5cmd)",
219+
)
212220

213221

214222
@dataclass
@@ -356,6 +364,7 @@ def run_cli(argv: list[str] | None = None) -> int:
356364
identity_mode=command.identity,
357365
staged=command.staged,
358366
ref=command.ref,
367+
blob_transfer=command.transfer_backend,
359368
)
360369
print(commit_id)
361370
return 0
@@ -368,6 +377,7 @@ def run_cli(argv: list[str] | None = None) -> int:
368377
identity_mode=command.identity,
369378
path_patterns=_flatten_option_values(command.path_patterns),
370379
ref=command.ref,
380+
blob_transfer=command.transfer_backend,
371381
)
372382
print(commit_id)
373383
return 0
@@ -379,60 +389,24 @@ def run_cli(argv: list[str] | None = None) -> int:
379389
ref=command.ref,
380390
identity_mode=command.identity,
381391
destination_path=command.destination_path,
392+
blob_transfer=command.transfer_backend,
382393
)
383394
print(json.dumps(_stage_payload(stage), indent=2))
384395
return 0
385396

386397
if isinstance(command, RmArgs):
387-
if command.message is not None and command.staged:
388-
print(
389-
"rm error: cannot combine --message with --staged",
390-
file=sys.stderr,
391-
)
392-
return 2
393-
if command.message is not None:
394-
result = remove(
395-
root=command.root,
396-
paths=command.paths,
397-
message=command.message,
398-
ref=command.ref,
399-
)
400-
print(
401-
json.dumps(
402-
{
403-
"ref": result.ref,
404-
"commit_id": result.commit_id,
405-
"removed_paths": result.removed_paths,
406-
},
407-
indent=2,
408-
)
409-
)
410-
return 0
411-
412398
stage = rm(root=command.root, paths=command.paths, ref=command.ref)
413399
print(json.dumps(_stage_payload(stage), indent=2))
414400
return 0
415401

416402
if isinstance(command, MoveArgs):
417-
result = move(
403+
stage = move_staged(
418404
root=command.root,
419405
source_path=command.source_path,
420406
destination_path=command.destination_path,
421-
message=command.message,
422407
ref=command.ref,
423408
)
424-
print(
425-
json.dumps(
426-
{
427-
"ref": result.ref,
428-
"commit_id": result.commit_id,
429-
"source_path": result.source_path,
430-
"destination_path": result.destination_path,
431-
"moved_paths": result.moved_paths,
432-
},
433-
indent=2,
434-
)
435-
)
409+
print(json.dumps(_stage_payload(stage), indent=2))
436410
return 0
437411

438412
if isinstance(command, StatusArgs):
@@ -493,6 +467,7 @@ def run_cli(argv: list[str] | None = None) -> int:
493467
ref=command.ref,
494468
path_prefixes=_flatten_option_values(command.path),
495469
dry_run=command.dry_run,
470+
blob_transfer=command.transfer_backend,
496471
)
497472
payload = {
498473
"commit_id": result.commit_id,

src/fluxel/core/__init__.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
)
1010
from .layout import FluxelLayout, blob_relpath, initialize_fluxel_layout
1111
from .manifest import (
12+
FileEntry,
1213
ManifestEntry,
1314
ManifestReader,
1415
ManifestWriter,
@@ -40,17 +41,22 @@
4041
import_s3,
4142
merge,
4243
move,
44+
move_staged,
4345
remove,
4446
rm,
4547
status,
4648
verify,
4749
)
4850
from .storage import (
51+
BlobTransferBackend,
4952
LocalStorageBackend,
5053
OptimisticLockError,
54+
S3BlobTransferBackend,
55+
S5CmdBlobTransferBackend,
5156
S3ObjectMetadata,
5257
S3StorageBackend,
5358
StorageBackend,
59+
build_blob_transfer_backend,
5460
iter_s3_objects,
5561
open_source_uri,
5662
parse_s3_uri,
@@ -60,6 +66,7 @@
6066
"DEFAULT_CHUNK_SIZE",
6167
"AnalyticalIndexPaths",
6268
"LocalClientState",
69+
"BlobTransferBackend",
6370
"CommitObject",
6471
"DiffEntry",
6572
"FluxelFileSystem",
@@ -69,11 +76,14 @@
6976
"open_repository",
7077
"RefConflictError",
7178
"RemoveResult",
79+
"S3BlobTransferBackend",
80+
"S5CmdBlobTransferBackend",
7281
"StageChange",
7382
"StageStatus",
7483
"VerifyResult",
7584
"FluxelURI",
7685
"FluxelLayout",
86+
"FileEntry",
7787
"BranchRefState",
7888
"LocalRepositoryStore",
7989
"LocalStorageBackend",
@@ -85,25 +95,27 @@
8595
"S3RepositoryStore",
8696
"S3StorageBackend",
8797
"StorageBackend",
98+
"build_analytical_index",
8899
"blake3_digest_file",
89100
"blake3_digest_stream",
90-
"build_analytical_index",
91-
"build_manifest_entries",
101+
"build_blob_transfer_backend",
92102
"blob_relpath",
103+
"build_manifest_entries",
93104
"add",
94105
"branch",
95106
"commit",
96107
"diff",
108+
"drop_analytical_index",
97109
"import_s3",
110+
"initialize_fluxel_layout",
98111
"merge",
99112
"move",
113+
"move_staged",
114+
"query_analytical_index",
100115
"remove",
101116
"rm",
102117
"status",
103118
"verify",
104-
"drop_analytical_index",
105-
"initialize_fluxel_layout",
106-
"query_analytical_index",
107119
"S3ObjectMetadata",
108120
"walk_files",
109121
"iter_s3_objects",

0 commit comments

Comments
 (0)