Skip to content

Commit

Permalink
fix: process bucket prefix like official cli (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeanbmar committed May 24, 2023
1 parent 002bf30 commit 7c529f6
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 35 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ jobs:
run: npm ci
- name: Build
run: npm run build
- name: run test
- name: Run test
run: npm run test
13 changes: 5 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ await sync('s3://my-source-bucket', 's3://my-target-bucket', {
#### Relocate objects during sync

```javascript
// sync s3://my-source-bucket/a/b/c.txt to s3://my-target-bucket/zzz/c.txt
await sync('s3://my-source-bucket/a/b/c.txt', 's3://my-target-bucket', {
// move objects from source folder a/b/ to target folder zzz/
await sync('s3://my-source-bucket', 's3://my-target-bucket', {
relocations: [ // multiple relocations can be applied
(currentPath) =>
currentPath.startsWith('a/b/')
Expand All @@ -188,12 +188,9 @@ await sync('s3://my-source-bucket/a/b/c.txt', 's3://my-target-bucket', {
],
});

// sync s3://mybucket/flowers/red/rose.png to /path/to/local/dir/rose.png
await sync('s3://mybucket/flowers/red/rose.png', '/path/to/local/dir', {
relocations: [
(currentPath) => currentPath.replace('flowers/red/', '') // folder flowers/red will be flattened during sync
],
});
// aws s3 sync s3://mybucket/flowers/red /path/to/local/dir
// as in cli, folder flowers/red will be flattened during sync
await sync('s3://mybucket/flowers/red', '/path/to/local/dir');
```

Note: relocations are applied after every other options such as filters.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "s3-sync-client",
"version": "4.1.0",
"version": "4.1.1",
"description": "AWS CLI s3 sync for Node.js provides a modern client to perform S3 sync operations between file systems and S3 buckets in the spirit of the official AWS CLI command",
"keywords": [
"aws",
Expand Down
8 changes: 8 additions & 0 deletions src/commands/SyncBucketWithBucketCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ export class SyncBucketWithBucketCommand {
(currentPath) => `${targetPrefix}/${currentPath}`,
...this.relocations,
];
if (sourcePrefix !== '')
this.relocations = [
(currentPath) =>
currentPath.startsWith(`${sourcePrefix}/`)
? currentPath.replace(`${sourcePrefix}/`, '')
: currentPath,
...this.relocations,
];
sourceObjects.forEach((sourceObject) =>
sourceObject.applyFilters(this.filters)
);
Expand Down
8 changes: 8 additions & 0 deletions src/commands/SyncLocalWithBucketCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ export class SyncLocalWithBucketCommand {
new ListBucketObjectsCommand({ bucket, prefix }).execute(client),
new ListLocalObjectsCommand({ directory: this.localDir }).execute(),
]);
if (prefix !== '')
this.relocations = [
(currentPath) =>
currentPath.startsWith(`${prefix}/`)
? currentPath.replace(`${prefix}/`, '')
: currentPath,
...this.relocations,
];
sourceObjects.forEach((sourceObject) =>
sourceObject.applyFilters(this.filters)
);
Expand Down
80 changes: 55 additions & 25 deletions test/S3SyncClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ test('s3 sync client', async (t) => {
await syncClient.send(
new SyncBucketWithBucketCommand({
sourceBucketPrefix: `${BUCKET_2}/def/jkl`,
targetBucketPrefix: BUCKET,
targetBucketPrefix: `${BUCKET}/def/jkl`,
maxConcurrentTransfers: 200,
monitor,
})
Expand All @@ -155,7 +155,7 @@ test('s3 sync client', async (t) => {
await syncClient.send(
new SyncBucketWithBucketCommand({
sourceBucketPrefix: `${BUCKET_2}/def/jkl`,
targetBucketPrefix: BUCKET,
targetBucketPrefix: `${BUCKET}/def/jkl`,
maxConcurrentTransfers: 200,
relocations: [(currentPath) => `relocated/${currentPath}`],
})
Expand All @@ -171,15 +171,19 @@ test('s3 sync client', async (t) => {
});

await b.test('syncs a single dir with folder relocation', async () => {
await syncClient.sync(`s3://${BUCKET_2}/def/jkl`, `s3://${BUCKET}`, {
maxConcurrentTransfers: 200,
relocations: [
(currentPath) =>
currentPath.startsWith('def/jkl')
? currentPath.replace('def/jkl', 'relocated-bis/folder')
: currentPath,
],
});
await syncClient.sync(
`s3://${BUCKET_2}/def/jkl`,
`s3://${BUCKET}/def/jkl`,
{
maxConcurrentTransfers: 200,
relocations: [
(currentPath) =>
currentPath.startsWith('def/jkl')
? currentPath.replace('def/jkl', 'relocated-bis/folder')
: currentPath,
],
}
);
const objects = await syncClient.send(
new ListBucketObjectsCommand({
bucket: BUCKET,
Expand Down Expand Up @@ -209,6 +213,23 @@ test('s3 sync client', async (t) => {
assert(objects.length === 5000);
}
);

// https://github.com/jeanbmar/s3-sync-client/issues/40
await b.test('processes prefix properly', async () => {
fs.rmSync(path.join(SYNC_DIR, 'issue40'), {
recursive: true,
force: true,
});
await syncClient.sync(`s3://${BUCKET_2}/def`, `s3://${BUCKET}/issue40`);
const objects = await syncClient.send(
new ListBucketObjectsCommand({
bucket: BUCKET,
prefix: 'issue40',
})
);
assert(hasObject(objects, 'issue40/def/jkl/xmoj') === false);
assert(hasObject(objects, 'issue40/jkl/xmoj') === true);
});
});

await t.test('syncs bucket with local', async (b) => {
Expand Down Expand Up @@ -395,7 +416,7 @@ test('s3 sync client', async (t) => {
await l.test('syncs a single dir with a few files', async () => {
await syncClient.send(
new SyncLocalWithBucketCommand({
bucketPrefix: `${BUCKET_2}/def/jkl`,
bucketPrefix: `${BUCKET_2}/def`,
localDir: SYNC_DIR,
})
);
Expand All @@ -404,7 +425,7 @@ test('s3 sync client', async (t) => {
directory: SYNC_DIR,
})
);
assert(hasObject(objects, 'def/jkl/xmoj') === true);
assert(hasObject(objects, 'jkl/xmoj') === true);
});

await l.test(
Expand All @@ -415,12 +436,7 @@ test('s3 sync client', async (t) => {
new SyncLocalWithBucketCommand({
bucketPrefix: `${BUCKET_2}/def/jkl`,
localDir: SYNC_DIR,
relocations: [
(currentPath) =>
currentPath.startsWith('def/jkl')
? currentPath.replace('def/jkl', 'issue9')
: currentPath,
],
relocations: [(currentPath) => `issue9/${currentPath}`],
})
);
fs.writeFileSync(
Expand All @@ -432,12 +448,7 @@ test('s3 sync client', async (t) => {
new SyncLocalWithBucketCommand({
bucketPrefix: `${BUCKET_2}/def/jkl`,
localDir: SYNC_DIR,
relocations: [
(currentPath) =>
currentPath.startsWith('def/jkl')
? currentPath.replace('def/jkl', 'issue9')
: currentPath,
],
relocations: [(currentPath) => `issue9/${currentPath}`],
del: true,
})
);
Expand Down Expand Up @@ -554,6 +565,25 @@ test('s3 sync client', async (t) => {
assert(atimeMs < now);
assert(mtimeMs < now);
});

// https://github.com/jeanbmar/s3-sync-client/issues/40
await l.test('processes prefix properly', async () => {
fs.rmSync(path.join(SYNC_DIR, 'issue40'), {
recursive: true,
force: true,
});
await syncClient.sync(
`s3://${BUCKET_2}/def`,
path.join(SYNC_DIR, 'issue40')
);
const objects = await syncClient.send(
new ListLocalObjectsCommand({
directory: path.join(SYNC_DIR, 'issue40'),
})
);
assert(hasObject(objects, 'def/jkl/xmoj') === false);
assert(hasObject(objects, 'jkl/xmoj') === true);
});
});

await t.test('diffs sync objects', async (d) => {
Expand Down

0 comments on commit 7c529f6

Please sign in to comment.