From f9af4e6dfbf78c57d16e8db21b9eec4988558014 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 6 Feb 2020 10:12:31 +0000 Subject: [PATCH 1/2] feat: add .path and .path.silent functions to detect binary After installation if you wish to specify a path to the installed binary, it's useful for this module to be able to tell the world where it put the binary, so this PR adds `.path` and `.path.silent()` functions to do that. This way we can use the installed module without having to rely on any external context or platform. --- README.md | 16 +++++++++++++++ src/index.js | 24 ++++++++++++++++++++++ test/index.js | 56 +++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 88 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 5601c93..ef12d09 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,22 @@ This module downloads `go-ipfs` binaries from https://dist.ipfs.io into your pro By default it will download the go-ipfs version that matches the npm version of this module. So depending on `go-ipfs-dep@0.4.19` will install `go-ipfs v0.4.19` for your current system architecture, in to your project at `node_modules/go-ipfs-dep/go-ipfs/ipfs`. +After downloading you can find out the path of the installed binary by calling the `path` function exported by this module: + +```javascript +const { path } = require('go-ipfs-dep') + +console.info('go-ipfs is installed at', path()) +``` + +An error will be thrown if the path to the binary cannot be resolved - if you do not wish this to happen, call `path.silent()`: + +```javascript +const { path: silent } = require('go-ipfs-dep') + +console.info('go-ipfs may installed at', silent()) +``` + ### Overriding the go-ipfs version You can override the version of go-ipfs that gets downloaded by adding by adding a `go-ipfs.version` field to your `package.json` diff --git a/src/index.js b/src/index.js index 2f7adfa..61e22ca 100644 --- a/src/index.js +++ b/src/index.js @@ -27,6 +27,7 @@ const unzip = require('unzip-stream') const fetch = require('node-fetch') const pkgConf = require('pkg-conf') const pkg = require('./../package.json') +const fs = require('fs') function unpack ({ url, installPath, stream }) { return new Promise((resolve, reject) => { @@ -115,3 +116,26 @@ module.exports = async function () { installPath: path.join(args.installPath, 'go-ipfs') + path.sep } } + +module.exports.path = function () { + const paths = [ + path.resolve(path.join(__dirname, '..', 'go-ipfs', 'ipfs')), + path.resolve(path.join(__dirname, '..', 'go-ipfs', 'ipfs.exe')) + ] + + for (const bin of paths) { + if (fs.existsSync(bin)) { + return bin + } + } + + throw new Error('go-ipfs binary not found, it may not be installed or an error may have occured during installation') +} + +module.exports.path.silent = function () { + try { + return module.exports.path() + } catch (err) { + // ignore + } +} diff --git a/test/index.js b/test/index.js index bef4b1d..c10b650 100644 --- a/test/index.js +++ b/test/index.js @@ -39,7 +39,7 @@ function download (version, platform, arch, callback) { } test('Ensure ipfs gets downloaded (current version and platform)', (t) => { - t.plan(5) + t.plan(7) const dir = path.resolve(__dirname, '../go-ipfs') rimraf.sync(dir) @@ -52,12 +52,17 @@ test('Ensure ipfs gets downloaded (current version and platform)', (t) => { fs.stat(dir, (err, stats) => { t.error(err, 'go-ipfs should stat without error') t.ok(stats, 'go-ipfs was downloaded') + // Check detected path + fs.stat(Download.path(), (err3, stats3) => { + t.error(err3, 'detected binary path should stat without error') + t.ok(stats3.mode, 'downloaded binary was detected') + }) }) }) }) test('Ensure Windows version gets downloaded', (t) => { - t.plan(7) + t.plan(9) const dir = path.resolve(__dirname, '../go-ipfs') rimraf.sync(dir) download(version, 'windows', (err, res) => { @@ -72,13 +77,18 @@ test('Ensure Windows version gets downloaded', (t) => { fs.stat(path.join(dir, 'ipfs.exe'), (err2, stats2) => { t.error(err2, 'windows bin should stat without error') t.ok(stats2, 'windows bin was downloaded') + // Check detected path + fs.stat(Download.path(), (err3, stats3) => { + t.error(err3, 'detected binary path should stat without error') + t.ok(stats3.mode, 'downloaded binary was detected') + }) }) }) }) }) test('Ensure Linux version gets downloaded', (t) => { - t.plan(7) + t.plan(9) const dir = path.resolve(__dirname, '../go-ipfs') rimraf.sync(dir) download(version, 'linux', (err, res) => { @@ -93,13 +103,18 @@ test('Ensure Linux version gets downloaded', (t) => { fs.stat(path.join(dir, 'ipfs'), (err2, stats2) => { t.error(err2, 'linux bin should stat without error') t.ok(stats2, 'linux bin was downloaded') + // Check detected path + fs.stat(Download.path(), (err3, stats3) => { + t.error(err3, 'detected binary path should stat without error') + t.ok(stats3.mode, 'downloaded binary was detected') + }) }) }) }) }) test('Ensure OSX version gets downloaded', (t) => { - t.plan(7) + t.plan(9) const dir = path.resolve(__dirname, '../go-ipfs') rimraf.sync(dir) download(version, 'darwin', (err, res) => { @@ -114,13 +129,18 @@ test('Ensure OSX version gets downloaded', (t) => { fs.stat(path.join(dir, 'ipfs'), (err2, stats2) => { t.error(err2, 'OSX bin should stat without error') t.ok(stats2, 'OSX bin was downloaded') + // Check detected path + fs.stat(Download.path(), (err3, stats3) => { + t.error(err3, 'detected binary path should stat without error') + t.ok(stats3.mode, 'downloaded binary was detected') + }) }) }) }) }) test('Ensure TARGET_OS, TARGET_VERSION and TARGET_ARCH version gets downloaded', (t) => { - t.plan(7) + t.plan(9) const dir = path.resolve(__dirname, '../go-ipfs') rimraf.sync(dir) process.env.TARGET_OS = 'windows' @@ -142,9 +162,14 @@ test('Ensure TARGET_OS, TARGET_VERSION and TARGET_ARCH version gets downloaded', fs.stat(path.join(dir, 'ipfs.exe'), (err2, stats2) => { t.error(err2, 'windows bin should stat without error') t.ok(stats2, 'windows bin was downloaded') - delete process.env.TARGET_OS - delete process.env.TARGET_VERSION - delete process.env.TARGET_ARCH + // Check detected path + fs.stat(Download.path(), (err3, stats3) => { + t.error(err3, 'detected binary path should stat without error') + t.ok(stats3.mode, 'downloaded binary was detected') + delete process.env.TARGET_OS + delete process.env.TARGET_VERSION + delete process.env.TARGET_ARCH + }) }) }) }) @@ -171,3 +196,18 @@ test('Returns an error when dist url is 404', (t) => { delete process.env.GO_IPFS_DIST_URL }) }) + +test('Path returns undefined when no binary has been downloaded', (t) => { + t.plan(1) + const dir = path.resolve(__dirname, '../go-ipfs') + rimraf.sync(dir) + t.ok(Download.path.silent() === undefined, 'Path is undefined before installation') +}) + +test('Path returns undefined when no binary has been downloaded', (t) => { + t.plan(1) + const dir = path.resolve(__dirname, '../go-ipfs') + rimraf.sync(dir) + + t.throws(Download.path, /not found/, 'Path throws if binary is not installed') +}) From 8aecef2b4a924862305e356e9b3b03c5362240f5 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 6 Feb 2020 10:16:09 +0000 Subject: [PATCH 2/2] fix: skip download if binary has already been installed fixes #25 --- src/bin.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/bin.js b/src/bin.js index ae8af36..186a60f 100644 --- a/src/bin.js +++ b/src/bin.js @@ -16,6 +16,14 @@ const success = (output) => { process.exit(0) } +const existingPath = download.path.silent() + +if (existingPath) { + process.stdout.write(`Detected existing binary at ${existingPath}\n`) + process.stdout.write(`Skipping download\n`) + process.exit(0) +} + // First param is the target version // Second param is the target platform // Third param is the target architecture