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

pack: include contents of directories in files field #3175

Merged
merged 13 commits into from
Apr 28, 2017
Merged
Show file tree
Hide file tree
Changes from all 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
14 changes: 9 additions & 5 deletions __tests__/commands/pack.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export async function getFilesFromArchive(source, destination): Promise<Array<st
.on('error', reject);
});
await unzip;
const files = await fs.readdir(destination);
const files = (await fs.walk(destination)).map(({relative}) => relative);
return files;
}

Expand All @@ -115,10 +115,14 @@ test.concurrent('pack should inlude all files listed in the files array', (): Pr
path.join(cwd, 'files-include-v1.0.0.tgz'),
path.join(cwd, 'files-include-v1.0.0'),
);
const expected = ['index.js', 'a.js', 'b.js'];
expected.forEach((filename) => {
expect(files.indexOf(filename)).toBeGreaterThanOrEqual(0);
});
expect(files.sort()).toEqual([
'a.js',
'b.js',
'dir',
path.join('dir', 'nested.js'),
'index.js',
'package.json',
]);
});
});

Expand Down
2 changes: 2 additions & 0 deletions __tests__/fixtures/pack/files-include/dir/nested.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/* @flow */
console.log('hello world');
2 changes: 1 addition & 1 deletion __tests__/fixtures/pack/files-include/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"files": ["index.js", "a.js", "b.js"]
"files": ["index.js", "a.js", "b.js", "dir/"]
}
34 changes: 17 additions & 17 deletions __tests__/util/filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,22 @@ test('ignoreLinesToRegex', () => {
'! F # # ',
'#! G',
])).toEqual([
{base: '.', isNegation: false, regex: /^(?:(?=.)a)$/i},
{base: '.', isNegation: false, regex: /^(?:(?=.)b)$/i},
{base: '.', isNegation: false, regex: /^(?:(?=.)c)$/i},
{base: '.', isNegation: false, regex: /^(?:(?=.)d #)$/i},
{base: '.', isNegation: false, regex: /^(?:(?=.)e#)$/i},
{base: '.', isNegation: false, regex: /^(?:(?=.)f #)$/i},
{base: '.', isNegation: false, regex: /^(?:(?=.)g#)$/i},
{base: '.', isNegation: false, regex: /^(?:(?=.)h # foo)$/i},
{base: '.', isNegation: false, regex: /^(?:(?=.)i# foo)$/i},
{base: '.', isNegation: false, regex: /^(?:(?=.)j # foo #)$/i},
{base: '.', isNegation: false, regex: /^(?:(?=.)k # foo # #)$/i},
{base: '.', isNegation: true, regex: /^(?:(?=.)A)$/i},
{base: '.', isNegation: true, regex: /^(?:(?=.)B)$/i},
{base: '.', isNegation: true, regex: /^(?:(?=.)C)$/i},
{base: '.', isNegation: true, regex: /^(?:(?=.)D #)$/i},
{base: '.', isNegation: true, regex: /^(?:(?=.)E #)$/i},
{base: '.', isNegation: true, regex: /^(?:(?=.)F # #)$/i},
{base: '.', isNegation: false, pattern: 'a', regex: /^(?:(?=.)a)$/i},
{base: '.', isNegation: false, pattern: 'b ', regex: /^(?:(?=.)b)$/i},
{base: '.', isNegation: false, pattern: ' c ', regex: /^(?:(?=.)c)$/i},
{base: '.', isNegation: false, pattern: 'd #', regex: /^(?:(?=.)d #)$/i},
{base: '.', isNegation: false, pattern: 'e#', regex: /^(?:(?=.)e#)$/i},
{base: '.', isNegation: false, pattern: 'f # ', regex: /^(?:(?=.)f #)$/i},
{base: '.', isNegation: false, pattern: 'g# ', regex: /^(?:(?=.)g#)$/i},
{base: '.', isNegation: false, pattern: 'h # foo', regex: /^(?:(?=.)h # foo)$/i},
{base: '.', isNegation: false, pattern: 'i# foo', regex: /^(?:(?=.)i# foo)$/i},
{base: '.', isNegation: false, pattern: 'j # foo #', regex: /^(?:(?=.)j # foo #)$/i},
{base: '.', isNegation: false, pattern: 'k # foo # #', regex: /^(?:(?=.)k # foo # #)$/i},
{base: '.', isNegation: true, pattern: 'A', regex: /^(?:(?=.)A)$/i},
{base: '.', isNegation: true, pattern: ' B', regex: /^(?:(?=.)B)$/i},
{base: '.', isNegation: true, pattern: ' C ', regex: /^(?:(?=.)C)$/i},
{base: '.', isNegation: true, pattern: ' D #', regex: /^(?:(?=.)D #)$/i},
{base: '.', isNegation: true, pattern: ' E # ', regex: /^(?:(?=.)E #)$/i},
{base: '.', isNegation: true, pattern: ' F # # ', regex: /^(?:(?=.)F # #)$/i},
]);
});
73 changes: 22 additions & 51 deletions src/cli/commands/pack.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {MessageError} from '../../errors.js';

const zlib = require('zlib');
const path = require('path');
const tar = require('tar-stream');
const tar = require('tar-fs');
const fs2 = require('fs');

const IGNORE_FILENAMES = [
Expand Down Expand Up @@ -54,18 +54,6 @@ const NEVER_IGNORE = ignoreLinesToRegex([
'!/+(changes|changelog|history)*',
]);

function addEntry(packer: any, entry: Object, buffer?: ?Buffer): Promise<void> {
return new Promise((resolve, reject) => {
packer.entry(entry, buffer, function(err) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}

export async function pack(config: Config, dir: string): Promise<stream$Duplex> {
const pkg = await config.readRootManifest();
const {bundledDependencies, files: onlyFiles} = pkg;
Expand Down Expand Up @@ -94,6 +82,7 @@ export async function pack(config: Config, dir: string): Promise<stream$Duplex>
];
lines = lines.concat(
onlyFiles.map((filename: string): string => `!${filename}`),
onlyFiles.map((filename: string): string => `!${path.join(filename, '**')}`),
);
const regexes = ignoreLinesToRegex(lines, '.');
filters = filters.concat(regexes);
Expand Down Expand Up @@ -126,46 +115,28 @@ export async function pack(config: Config, dir: string): Promise<stream$Duplex>
// apply filters
sortFilter(files, filters, keepFiles, possibleKeepFiles, ignoredFiles);

const packer = tar.pack();
const compressor = packer.pipe(new zlib.Gzip());

await addEntry(packer, {
name: 'package',
type: 'directory',
const packer = tar.pack(config.cwd, {
ignore: (name) => {
const relative = path.relative(config.cwd, name);
// Don't ignore directories, since we need to recurse inside them to check for unignored files.
if (fs2.lstatSync(name).isDirectory()) {
const isParentOfKeptFile = Array.from(keepFiles).some((name) =>
!path.relative(relative, name).startsWith('..'));
return !isParentOfKeptFile;
}
// Otherwise, ignore a file if we're not supposed to keep it.
return !keepFiles.has(relative);
},
map: (header) => {
const suffix = header.name === '.' ? '' : `/${header.name}`;
header.name = `package${suffix}`;
delete header.uid;
delete header.gid;
return header;
},
});

for (const name of keepFiles) {
const loc = path.join(config.cwd, name);
const stat = await fs.lstat(loc);

let type: ?string;
let buffer: ?Buffer;
let linkname: ?string;
if (stat.isDirectory()) {
type = 'directory';
} else if (stat.isFile()) {
buffer = await fs.readFileRaw(loc);
type = 'file';
} else if (stat.isSymbolicLink()) {
type = 'symlink';
linkname = await fs.readlink(loc);
} else {
throw new Error();
}

const entry = {
name: `package/${name}`,
size: stat.size,
mode: stat.mode,
mtime: stat.mtime,
type,
linkname,
};

await addEntry(packer, entry, buffer);
}

packer.finalize();
const compressor = packer.pipe(new zlib.Gzip());

return compressor;
}
Expand Down
5 changes: 4 additions & 1 deletion src/util/filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type IgnoreFilter = {
base: string,
isNegation: boolean,
regex: RegExp,
pattern: string,
};

export function sortFilter(
Expand Down Expand Up @@ -99,7 +100,8 @@ export function matchesFilter(filter: IgnoreFilter, basename: string, loc: strin
}
return filter.regex.test(loc) ||
filter.regex.test(`/${loc}`) ||
filter.regex.test(basename);
filter.regex.test(basename) ||
minimatch(loc, filter.pattern);
}

export function ignoreLinesToRegex(lines: Array<string>, base: string = '.'): Array<IgnoreFilter> {
Expand Down Expand Up @@ -131,6 +133,7 @@ export function ignoreLinesToRegex(lines: Array<string>, base: string = '.'): Ar
base,
isNegation,
regex,
pattern,
};
} else {
return null;
Expand Down