From 5f3bad2f5b56a5891f0c52859794ac37ee48e3ee Mon Sep 17 00:00:00 2001 From: Philip <17368112+vHeemstra@users.noreply.github.com> Date: Fri, 20 Jan 2023 15:18:52 +0100 Subject: [PATCH 1/2] feat: Support for local binaries * Adds support for copying local binaries before trying the downloads. > Works the same as `.src()`, except url is now a local path. > Bin-wrapper now first tries the `localSrc`s (copying them in place when found) and falls back to downloading `src`s on fail. --- index.js | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++- package.json | 14 ++++++++++++- readme.md | 15 +++++++++++++- 3 files changed, 84 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 1aba001..7255c17 100644 --- a/index.js +++ b/index.js @@ -12,6 +12,8 @@ const osFilterObj = importLazy('os-filter-obj'); const statAsync = pify(fs.stat); const chmodAsync = pify(fs.chmod); +const lstatAsync = pify(fs.lstat); +const copyFileAsync = pify(fs.copyFile); /** * Initialize a new `BinWrapper` @@ -30,6 +32,29 @@ module.exports = class BinWrapper { } } + /** + * Get or set local files to use before download + * + * @param {String} src + * @param {String} os + * @param {String} arch + * @api public + */ + localSrc(src, os, arch) { + if (arguments.length === 0) { + return this._localSrc; + } + + this._localSrc = this._localSrc || []; + this._localSrc.push({ + url: src, + os, + arch + }); + + return this; + } + /** * Get or set files to download * @@ -151,13 +176,44 @@ module.exports = class BinWrapper { findExisting() { return statAsync(this.path()).catch(error => { if (error && error.code === 'ENOENT') { - return this.download(); + return this.copyLocal().catch(() => this.download()); } return Promise.reject(error); }); } + /** + * Copying local files + * + * @api private + */ + copyLocal() { + const files = osFilterObj(this.localSrc() || []); + const urls = []; + + if (files.length === 0) { + return Promise.reject(new Error('No binary found matching your system. It\'s probably not supported.')); + } + + files.forEach(file => urls.push(file.url)); + + return Promise.all(urls.map(url => lstatAsync(url).then(stats => { + if (stats.isDirectory()) { + return Promise.reject(new Error('Local source path is a directory.')); + } + if (stats.isSymbolicLink()) { + return Promise.reject(new Error('Local source path is a symbolic link.')); + } + if (!stats.isFile()) { + return Promise.reject(new Error('Local source path is not a file.')); + } + + return copyFileAsync(url, path.join(this.dest(), path.basename(url))) + .then(() => chmodAsync(path.join(this.dest(), fileName), 0o755)); + }))); + } + /** * Download files * diff --git a/package.json b/package.json index e49e305..2ab4602 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bin-wrapper", - "version": "4.1.0", + "version": "4.2.0", "description": "Binary wrapper that makes your programs seamlessly available as local dependencies", "license": "MIT", "repository": "kevva/bin-wrapper", @@ -9,6 +9,18 @@ "email": "kevinmartensson@gmail.com", "url": "https://github.com/kevva" }, + "contributors": [ + { + "name": "Kevin MÃ¥rtensson", + "email": "kevinmartensson@gmail.com", + "url": "https://github.com/kevva" + }, + { + "name": "Philip van Heemstra", + "email": "vanheemstra@gmail.com", + "url": "https://github.com/vheemstra" + } + ], "engines": { "node": ">=6" }, diff --git a/readme.md b/readme.md index e57de2a..711a6f7 100644 --- a/readme.md +++ b/readme.md @@ -17,6 +17,9 @@ const BinWrapper = require('bin-wrapper'); const base = 'https://github.com/imagemin/gifsicle-bin/raw/master/vendor'; const bin = new BinWrapper() + .localSrc(`vendor/macos/gifsicle`, 'darwin') + .localSrc(`vendor/linux/x64/gifsicle`, 'linux', 'x64') + .localSrc(`vendor/win/x64/gifsicle.exe`, 'win32', 'x64') .src(`${base}/macos/gifsicle`, 'darwin') .src(`${base}/linux/x64/gifsicle`, 'linux', 'x64') .src(`${base}/win/x64/gifsicle.exe`, 'win32', 'x64') @@ -84,13 +87,23 @@ Type: `string` Tie the source to a specific arch. +### .localSrc(filepath, [os], [arch]) + +Same as `.src()`, but adds a local source to copy, before trying any downloads. + +#### filepath + +Type: `string` + +Accepts a filepath pointing to a local file. + ### .dest(destination) #### destination Type: `string` -Accepts a path which the files will be downloaded to. +Accepts a path which the files will be copied/downloaded to. ### .use(binary) From 3e02a1f62c0dfa1927ba3edbdfa6b739744c58ae Mon Sep 17 00:00:00 2001 From: Philip <17368112+vHeemstra@users.noreply.github.com> Date: Fri, 20 Jan 2023 15:40:35 +0100 Subject: [PATCH 2/2] Update package.json --- package.json | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/package.json b/package.json index 2ab4602..e02a784 100644 --- a/package.json +++ b/package.json @@ -9,18 +9,6 @@ "email": "kevinmartensson@gmail.com", "url": "https://github.com/kevva" }, - "contributors": [ - { - "name": "Kevin MÃ¥rtensson", - "email": "kevinmartensson@gmail.com", - "url": "https://github.com/kevva" - }, - { - "name": "Philip van Heemstra", - "email": "vanheemstra@gmail.com", - "url": "https://github.com/vheemstra" - } - ], "engines": { "node": ">=6" },