Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(toolkit): preserve asset's files mode #3413

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions packages/aws-cdk/lib/archive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ import fs = require('fs-extra');
import glob = require('glob');
import path = require('path');

const appendFiles = async (directory: string, files: string[], archive: archiver.Archiver): Promise<void> => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather declare this as async function appendFiles(directory: string, files: string[], archive: archiver.Archiver): Promise<void> { /*...*/ }

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tslint tells me that async function violates non-arrow-function rule if function keyword used.

Even so should I do?

await Promise.all(files.map(async file => {
aereal marked this conversation as resolved.
Show resolved Hide resolved
const srcPath = path.join(directory, file);
const stat = await fs.stat(srcPath);
archive.append(fs.createReadStream(srcPath), {
mode: stat.mode,
name: file,
date: new Date('1980-01-01T00:00:00.000Z'), // reset dates to get the same hash for the same content
});
}));
};

export function zipDirectory(directory: string, outputFile: string): Promise<void> {
return new Promise((ok, fail) => {
// The below options are needed to support following symlinks when building zip files:
Expand All @@ -24,17 +36,12 @@ export function zipDirectory(directory: string, outputFile: string): Promise<voi
archive.on('error', fail);
archive.pipe(output);

files.forEach(file => { // Append files serially to ensure file order
archive.append(fs.createReadStream(path.join(directory, file)), {
name: file,
date: new Date('1980-01-01T00:00:00.000Z'), // reset dates to get the same hash for the same content
});
});
appendFiles(directory, files, archive).then(() => {
archive.finalize();

archive.finalize();

// archive has been finalized and the output file descriptor has closed, resolve promise
output.once('close', () => ok());
// archive has been finalized and the output file descriptor has closed, resolve promise
output.once('close', () => ok());
});
});
}

Expand Down
2 changes: 2 additions & 0 deletions packages/aws-cdk/test/test-archive-mode/executable.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
I am file2
BLA!
1 change: 1 addition & 0 deletions packages/aws-cdk/test/test-archive-mode/readable.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
I am file1
36 changes: 35 additions & 1 deletion packages/aws-cdk/test/test.archive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,39 @@ export = {
await fs.remove(stagingDir);
await fs.remove(extractDir);
test.done();
}
},

async 'zipDirectory preserves mode of source files'(test: Test) {
const stagingDir = await fs.mkdtemp(path.join(os.tmpdir(), 'test.archive'));
const zipFile = path.join(stagingDir, 'output.zip');
const originalDir = path.join(__dirname, 'test-archive-mode');
const extractDir = await fs.mkdtemp(path.join(os.tmpdir(), 'test.archive.mode'));
await zipDirectory(originalDir, zipFile);

// unzip and verify that the resulting tree is the same
await exec(`unzip ${zipFile}`, { cwd: extractDir });

// tslint:disable-next-line:no-bitwise
const beExecutable = fs.constants.S_IXGRP | fs.constants.S_IXOTH | fs.constants.S_IXUSR;

let readable = true;
try {
await fs.access(path.join(extractDir, 'readable.txt'));
} catch {
readable = false;
}
test.ok(readable, 'extracted readable.txt cannot be accessed');

let executable = true;
try {
await fs.access(path.join(extractDir, 'executable.txt'), beExecutable);
} catch {
executable = false;
}
test.ok(executable, 'extracted executable.txt cannot be executable');

await fs.remove(stagingDir);
await fs.remove(extractDir);
test.done();
},
};