fix: add file-based lock mechanism to npm installs and links
MODIFY
lib/npm.js
lib/npm.js
import _ from 'lodash';
import path from 'path';
import { exec } from 'teen_process';
+import { util } from 'appium-support';
+
+const INSTALL_LOCKFILE = '.appium.install.lock';
+const LINK_LOCKFILE = '.appium.link.lock';
async function npmExec (cmd, args, opts, execOpts = {}) {
- const json = opts.json;
- if (!opts.appiumHome) {
+ const { appiumHome, json, lockFile } = opts;
+ if (!appiumHome) {
throw new Error('appiumHome was not provided to npmExec');
}
- execOpts.cwd = opts.appiumHome;
+ execOpts.cwd = appiumHome;
args.unshift(cmd);
if (json) {
args.push('-json');
}
- const {stdout, stderr, code} = await exec('npm', args, execOpts);
+ let runner = async () => await exec('npm', args, execOpts);
+ if (lockFile) {
+ const acquireLock = util.getLockFileGuard(path.resolve(appiumHome, lockFile));
+ const _runner = runner;
+ runner = async () => await acquireLock(_runner);
+ }
+ const {stdout, stderr, code} = await runner();
const ret = {stdout, stderr, code, json: null};
if (json) {
@@ -40,7 +50,11 @@ async function installPackage (appiumHome, pkg, ver) {
'--no-save',
'--no-package-lock',
ver ? `${pkg}@${ver}` : pkg
- ], {appiumHome, json: true});
+ ], {
+ appiumHome,
+ json: true,
+ lockFile: INSTALL_LOCKFILE
+ });
// eventually we need to know the npm package name so we can get its
// package.json, but if we're installing from github, we don't know that yet.
@@ -87,7 +101,7 @@ async function linkPackage (appiumHome, pkgPath) {
`provided: ${pkgPath}`);
}
- const res = await npmExec('link', [pkgPath], {appiumHome});
+ const res = await npmExec('link', [pkgPath], {appiumHome, lockFile: LINK_LOCKFILE});
if (res.json && res.json.error) {
throw new Error(res.json.error);
}

fix: add file-based lock mechanism to npm installs and links