diff --git a/.circleci/config.yml b/.circleci/config.yml index a21dc834..10196b2b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -36,7 +36,7 @@ jobs: <<: *steps-test test-mac: macos: - xcode: "10.2.0" + xcode: "12.5.0" <<: *steps-test test-windows: executor: diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index b6fcc928..00000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -test/input/**/*.txt text eol=lf diff --git a/README.md b/README.md index e05497f7..be98c2cd 100644 --- a/README.md +++ b/README.md @@ -67,21 +67,22 @@ Given: (h) └── w1 ``` -Exclude: a, b +Unpack: a, b ```bash $ asar pack app app.asar --unpack-dir "{x1,x2}" ``` -Exclude: a, b, d, f +Unpack: a, b, d, f ```bash $ asar pack app app.asar --unpack-dir "**/{x1,x2}" ``` -Exclude: a, b, d, f, h +Unpack: a, b, d, f, h ```bash $ asar pack app app.asar --unpack-dir "{**/x1,**/x2,z4/w1}" ``` +Similarly, `--ignore-dir` flag can be used to ignore certain directories and `--ignore` flag can be used to ignore certain files while packaging. ## Using programatically ### Example diff --git a/bin/asar.js b/bin/asar.js index 8efcc1a9..94828368 100755 --- a/bin/asar.js +++ b/bin/asar.js @@ -24,11 +24,15 @@ program.command('pack ') .option('--ordering ', 'path to a text file for ordering contents') .option('--unpack ', 'do not pack files matching glob ') .option('--unpack-dir ', 'do not pack dirs matching glob or starting with literal ') + .option('--ignore ', 'do not include files matching glob ') + .option('--ignore-dir ', 'do not include dirs matching glob ') .option('--exclude-hidden', 'exclude hidden files') .action(function (dir, output, options) { options = { unpack: options.unpack, unpackDir: options.unpackDir, + ignore: options.ignore, + ignoreDir: options.ignoreDir, ordering: options.ordering, version: options.sv, arch: options.sa, diff --git a/lib/asar.js b/lib/asar.js index 050e1a76..50f97c20 100644 --- a/lib/asar.js +++ b/lib/asar.js @@ -8,6 +8,8 @@ const Filesystem = require('./filesystem') const disk = require('./disk') const crawlFilesystem = require('./crawlfs') +const END_CHAR = '/' + /** * Whether a directory should be excluded from packing due to the `--unpack-dir" option. * @@ -26,6 +28,34 @@ function isUnpackedDir (dirPath, pattern, unpackDirs) { } } +/** + * Whether a directory should be ignored while packing due to the `--ignore-dir` option. + * + * @param {string} dirPath - directory path to check + * @param {string} pattern - directory name or glob pattern + */ +function isIgnoredDir (dirPath, pattern, ignoreDirs) { + const dirPathStr = dirPath + END_CHAR + if (dirPathStr.startsWith(pattern + END_CHAR) || minimatch(dirPath, pattern)) { + if (!ignoreDirs.includes(dirPath)) { + ignoreDirs.push(dirPath) + } + return true + } + return ignoreDirs.some(ignoreDir => dirPath.startsWith(ignoreDir)) +} + +/** + * Whether a file should be ignored while packing due to the `--ignore` or `--ignore-dir` option. + * + * @param {string} filePath - file path to check + * @param {string} ignoreFile - file name or glob pattern + */ +function isIgnoredFile (filePath, ignoreFile) { + const filePathStr = filePath + END_CHAR + return filePathStr.startsWith(ignoreFile + END_CHAR) || minimatch(filePath, ignoreFile, { matchBase: true }) +} + module.exports.createPackage = async function (src, dest) { return module.exports.createPackageWithOptions(src, dest, {}) } @@ -60,6 +90,7 @@ module.exports.createPackageFromFiles = async function (src, dest, filenames, me const filesystem = new Filesystem(src) const files = [] const unpackDirs = [] + const ignoreDirs = [] let filenamesSorted = [] if (options.ordering) { @@ -106,18 +137,32 @@ module.exports.createPackageFromFiles = async function (src, dest, filenames, me metadata[filename] = await crawlFilesystem.determineFileType(filename) } const file = metadata[filename] + const filePath = path.relative(src, filename) let shouldUnpack switch (file.type) { case 'directory': + if (options.ignoreDir && + isIgnoredDir(filePath, options.ignoreDir, ignoreDirs) + ) { + break + } + if (options.unpackDir) { - shouldUnpack = isUnpackedDir(path.relative(src, filename), options.unpackDir, unpackDirs) + shouldUnpack = isUnpackedDir(filePath, options.unpackDir, unpackDirs) } else { shouldUnpack = false } filesystem.insertDirectory(filename, shouldUnpack) break case 'file': + if ( + (options.ignore && isIgnoredFile(filePath, options.ignore, options.ignoreDir, ignoreDirs)) || + (options.ignoreDir && isIgnoredDir(filePath, options.ignoreDir, ignoreDirs)) + ) { + break + } + shouldUnpack = false if (options.unpack) { shouldUnpack = minimatch(filename, options.unpack, { matchBase: true }) diff --git a/lib/index.d.ts b/lib/index.d.ts index b3790ecf..556784d5 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -9,6 +9,8 @@ export type CreateOptions = { transform?: (filePath: string) => NodeJS.ReadWriteStream | void; unpack?: string; unpackDir?: string; + ignore?: string; + ignoreDir?: string; }; export type ListOptions = { diff --git a/test/cli-spec.js b/test/cli-spec.js index 2017d323..8f9be168 100644 --- a/test/cli-spec.js +++ b/test/cli-spec.js @@ -45,6 +45,10 @@ describe('command line interface', function () { assert.ok(fs.existsSync('tmp/packthis-unpack-cli.asar.unpacked/dir2/file2.png')) await compFiles('tmp/packthis-unpack-cli.asar', 'test/expected/packthis-unpack.asar') }) + it('should create archive from directory without ignored files', async () => { + await execAsar('p test/input/packthis/ tmp/packthis-ignore-cli.asar --ignore *.png') + await compFiles('tmp/packthis-ignore-cli.asar', 'test/expected/packthis-ignore-cli.asar') + }) it('should list files/dirs in archive', async () => { return assertAsarOutputMatches('l test/input/extractthis.asar', 'test/expected/extractthis-filelist.txt') }) @@ -137,4 +141,24 @@ describe('command line interface', function () { assert.ok(fs.existsSync('tmp/packthis-unpack-subdir-cli.asar.unpacked/dir2/subdir/file2.png')) assert.ok(fs.existsSync('tmp/packthis-unpack-subdir-cli.asar.unpacked/dir2/subdir/file3.txt')) }) + it('should create archive from directory without ignored dirs', async () => { + await execAsar('p test/input/packthis/ tmp/packthis-ignore-dir-cli.asar --ignore-dir dir2') + return compFiles('tmp/packthis-ignore-dir-cli.asar', 'test/expected/packthis-ignore-dir-cli.asar') + }) + it('should create archive from directory without ignored dirs specified by glob pattern', async () => { + await execAsar('p test/input/packthis-glob/ tmp/packthis-ignore-dir-glob-cli.asar --ignore-dir "{x1,x2}"') + return compFiles('tmp/packthis-ignore-dir-glob-cli.asar', 'test/expected/packthis-ignore-dir-glob-cli.asar') + }) + it('should create archive from directory without ignored dirs specified by globstar pattern', async () => { + await execAsar('p test/input/packthis-glob/ tmp/packthis-ignore-dir-globstar-cli.asar --ignore-dir "**/{x1,x2}"') + return compFiles('tmp/packthis-ignore-dir-globstar-cli.asar', 'test/expected/packthis-ignore-dir-globstar-cli.asar') + }) + it('should create archive from directory without ignored dirs specified by foo/{bar,baz} style pattern', async () => { + await execAsar('p test/input/packthis-glob/ tmp/packthis-ignore-dir-glob-foo-bar-baz-cli.asar --ignore-dir "y3/{x1,z1}"') + return compFiles('tmp/packthis-ignore-dir-glob-foo-bar-baz-cli.asar', 'test/expected/packthis-ignore-dir-glob-foo-bar-baz-cli.asar') + }) + it('should create archive from directory without ignored dirs and files', async () => { + await execAsar('p test/input/packthis/ tmp/packthis-ignore-dir-file-cli.asar --ignore *.png --ignore-dir dir2') + return compFiles('tmp/packthis-ignore-dir-file-cli.asar', 'test/expected/packthis-ignore-dir-file-cli.asar') + }) }) diff --git a/test/expected/packthis-ignore-cli.asar b/test/expected/packthis-ignore-cli.asar new file mode 100644 index 00000000..a6b3f147 Binary files /dev/null and b/test/expected/packthis-ignore-cli.asar differ diff --git a/test/expected/packthis-ignore-dir-cli.asar b/test/expected/packthis-ignore-dir-cli.asar new file mode 100644 index 00000000..a6e80a6d Binary files /dev/null and b/test/expected/packthis-ignore-dir-cli.asar differ diff --git a/test/expected/packthis-ignore-dir-file-cli.asar b/test/expected/packthis-ignore-dir-file-cli.asar new file mode 100644 index 00000000..a6e80a6d Binary files /dev/null and b/test/expected/packthis-ignore-dir-file-cli.asar differ diff --git a/test/expected/packthis-ignore-dir-glob-cli.asar b/test/expected/packthis-ignore-dir-glob-cli.asar new file mode 100644 index 00000000..4ff7f8d9 Binary files /dev/null and b/test/expected/packthis-ignore-dir-glob-cli.asar differ diff --git a/test/expected/packthis-ignore-dir-glob-foo-bar-baz-cli.asar b/test/expected/packthis-ignore-dir-glob-foo-bar-baz-cli.asar new file mode 100644 index 00000000..905e0989 Binary files /dev/null and b/test/expected/packthis-ignore-dir-glob-foo-bar-baz-cli.asar differ diff --git a/test/expected/packthis-ignore-dir-globstar-cli.asar b/test/expected/packthis-ignore-dir-globstar-cli.asar new file mode 100644 index 00000000..bcd3479d Binary files /dev/null and b/test/expected/packthis-ignore-dir-globstar-cli.asar differ