Skip to content

Commit 2445cbe

Browse files
Merge pull request #2 from rosen-vladimirov/vladimirov/get-global-path
Get result from which/where first
2 parents 41b36b2 + 464570e commit 2445cbe

File tree

3 files changed

+178
-14
lines changed

3 files changed

+178
-14
lines changed

lib/index.js

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,16 @@ const getPathFromExecutableNameOnWindows = (packageName, executableName) => {
6464
const pathToExecutable = line && line.trim(),
6565
pathToLib = pathToExecutable && path.join(path.dirname(pathToExecutable), nodeModulesDirName, packageName);
6666

67-
if (pathToLib && fs.existsSync(pathToLib)) {
68-
return pathToLib;
67+
if (pathToLib) {
68+
if (fs.existsSync(pathToLib)) {
69+
return pathToLib;
70+
}
71+
72+
// In case the path to <package>/bin/ is added to the PATH
73+
const resolvedPath = getPathWhenExecutableIsAddedDirectlyToPath(packageName, pathToExecutable);
74+
if (resolvedPath) {
75+
return resolvedPath;
76+
}
6977
}
7078
}
7179
} catch (err) {
@@ -100,6 +108,9 @@ const getPathFromExecutableNameOnNonWindows = (packageName, executableName) => {
100108
return packagePathMatch[1];
101109
}
102110
}
111+
112+
// In case executable is added to PATH directly
113+
return getPathWhenExecutableIsAddedDirectlyToPath(packageName, whichResult);
103114
}
104115
} catch (err) {
105116
console.error(err.message);
@@ -108,6 +119,18 @@ const getPathFromExecutableNameOnNonWindows = (packageName, executableName) => {
108119
return null;
109120
};
110121

122+
const getPathWhenExecutableIsAddedDirectlyToPath = (packageName, executablePath) => {
123+
const pathToPackageJson = path.join(path.dirname(executablePath), "..", "package.json");
124+
if (fs.existsSync(pathToPackageJson)) {
125+
const packageNameFromPackageJson = JSON.parse(fs.readFileSync(pathToPackageJson)).name;
126+
if (packageNameFromPackageJson === packageName) {
127+
return path.dirname(pathToPackageJson);
128+
}
129+
}
130+
131+
return null;
132+
};
133+
111134
// For some packages executable name is not the same as package name
112135
// For example our package is called nativescript, but the executable name is called "tns"
113136
const getPath = (packageName, executableName) => {
@@ -117,19 +140,18 @@ const getPath = (packageName, executableName) => {
117140
throw new Error(`OS '${platform}' is not supported.'`);
118141
}
119142

120-
const resultWithNpmConfig = getPathFromNpmConfig(platform, packageName);
121-
122-
if (resultWithNpmConfig) {
123-
return resultWithNpmConfig;
124-
}
125-
143+
let foundPath = null;
126144
if (executableName) {
127-
return platform === "win32" ?
145+
foundPath = platform === "win32" ?
128146
getPathFromExecutableNameOnWindows(packageName, executableName) :
129147
getPathFromExecutableNameOnNonWindows(packageName, executableName);
130148
}
131149

132-
return null;
150+
if (!foundPath) {
151+
foundPath = getPathFromNpmConfig(platform, packageName);
152+
}
153+
154+
return foundPath;
133155
};
134156

135157
module.exports = {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "global-modules-path",
3-
"version": "1.0.0",
3+
"version": "2.0.0",
44
"description": "Returns path to globally installed package",
55
"main": "./lib/index.js",
66
"scripts": {

test/index.js

Lines changed: 145 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ let fs = require("fs"),
1515
const originalExecSync = childProcess.execSync;
1616
const originalConsoleError = console.error;
1717
const originalExistsSync = fs.existsSync;
18+
const originalReadFileSync = fs.readFileSync;
1819

1920
describe("getPath", () => {
2021

@@ -23,6 +24,7 @@ describe("getPath", () => {
2324
childProcess.execSync = originalExecSync;
2425
console.error = originalConsoleError;
2526
fs.existsSync = originalExistsSync;
27+
fs.readFileSync = originalReadFileSync;
2628
});
2729

2830
// platform independant tests. Execute them by simulating all supported platforms, but results should be the same.
@@ -173,13 +175,77 @@ describe("getPath", () => {
173175
assert.deepEqual(result, path.join(executableDirName, "node_modules", packageName));
174176
});
175177

178+
it("returns correct result when where result is correct, and package is added to PATH via its bin dir", () => {
179+
const packageName = "test1",
180+
executableName = "test1.js",
181+
executableDirName = path.join("C:", "Users", "username", "nativescript-cli", "bin"),
182+
whereResult = path.join(executableDirName, executableName);
183+
184+
fs.existsSync = (filePath) => {
185+
return filePath.indexOf("package.json") !== -1;
186+
};
187+
188+
fs.readFileSync = (filePath) => {
189+
if (filePath.indexOf("package.json") !== -1) {
190+
return JSON.stringify({
191+
"name": packageName
192+
});
193+
}
194+
195+
return "";
196+
};
197+
198+
childProcess.execSync = (command) => {
199+
if (command.indexOf("where") !== -1) {
200+
return whereResult;
201+
}
202+
203+
return null;
204+
};
205+
206+
const result = index.getPath(packageName, executableName);
207+
assert.deepEqual(result, path.join(path.dirname(executableDirName)));
208+
});
209+
210+
it("returns null when package is added to PATH via its bin dir, but the name in package.json is incorrect", () => {
211+
const packageName = "test1",
212+
executableName = "test1.js",
213+
executableDirName = path.join("C:", "Users", "username", "nativescript-cli", "bin"),
214+
whereResult = path.join(executableDirName, executableName);
215+
216+
fs.existsSync = (filePath) => {
217+
return filePath.indexOf("package.json") !== -1;
218+
};
219+
220+
fs.readFileSync = (filePath) => {
221+
if (filePath.indexOf("package.json") !== -1) {
222+
return JSON.stringify({
223+
"name": "invalidName"
224+
});
225+
}
226+
227+
return "";
228+
};
229+
230+
childProcess.execSync = (command) => {
231+
if (command.indexOf("where") !== -1) {
232+
return whereResult;
233+
}
234+
235+
return null;
236+
};
237+
238+
const result = index.getPath(packageName, executableName);
239+
assert.deepEqual(result, null);
240+
});
241+
176242
it("returns correct result when where result returns multiple lines correct", () => {
177243
const packageName = "test1",
178244
executableName = "test1.js",
179245
executableDirName = path.join("C:", "Users", "username", "AppData", "Roaming", "npm"),
180246
invalidName = "invalidName",
181-
invalidLineOfWhereResult = path.join(executableDirName, invalidName, executableName),
182-
whereResult = invalidLineOfWhereResult + "\n" + invalidLineOfWhereResult + "\r\n" + path.join(executableDirName, executableName);
247+
invalidLineOfWhereResult = path.join(executableDirName, invalidName, invalidName, executableName),
248+
whereResult = invalidLineOfWhereResult + "\n" + invalidLineOfWhereResult + "\r\n" + path.join(executableDirName, executableName);
183249

184250
fs.existsSync = (filePath) => {
185251
if (filePath && filePath.indexOf(invalidName) !== -1) {
@@ -348,14 +414,90 @@ describe("getPath", () => {
348414
const result = index.getPath(packageName, executableName);
349415
assert.deepEqual(result, null);
350416
});
417+
418+
it("returns correct result when which result is correct, and package is added to PATH via its bin dir", () => {
419+
const packageName = "test1",
420+
executableName = "test1.js",
421+
executableDirName = path.join("/usr", "username", "repository_name", "bin"),
422+
whichResult = path.join(executableDirName, executableName),
423+
lsLResult = `lrwxrwxrwx 1 rvladimirov rvladimirov 52 Oct 20 14:51 ${whichResult} -> incorrect`;
424+
425+
fs.existsSync = (filePath) => {
426+
return filePath.indexOf("package.json") !== -1;
427+
};
428+
429+
childProcess.execSync = (command) => {
430+
431+
if (command.indexOf("ls -l") !== -1) {
432+
return lsLResult;
433+
}
434+
435+
if (command.indexOf("which") !== -1) {
436+
return whichResult;
437+
}
438+
439+
return null;
440+
};
441+
442+
fs.readFileSync = (filePath) => {
443+
if (filePath.indexOf("package.json") !== -1) {
444+
return JSON.stringify({
445+
"name": packageName
446+
});
447+
}
448+
449+
return "";
450+
};
451+
452+
const result = index.getPath(packageName, executableName);
453+
assert.deepEqual(result, path.dirname(executableDirName));
454+
});
455+
456+
it("returns null when package is added to PATH via its bin dir, but the name in package.json is incorrect", () => {
457+
const packageName = "test1",
458+
executableName = "test1.js",
459+
executableDirName = path.join("/usr", "username", "repository_name", "bin"),
460+
whichResult = path.join(executableDirName, executableName),
461+
lsLResult = `lrwxrwxrwx 1 rvladimirov rvladimirov 52 Oct 20 14:51 ${whichResult} -> incorrect`;
462+
463+
fs.existsSync = (filePath) => {
464+
return filePath.indexOf("package.json") !== -1;
465+
};
466+
467+
childProcess.execSync = (command) => {
468+
469+
if (command.indexOf("ls -l") !== -1) {
470+
return lsLResult;
471+
}
472+
473+
if (command.indexOf("which") !== -1) {
474+
return whichResult;
475+
}
476+
477+
return null;
478+
};
479+
480+
fs.readFileSync = (filePath) => {
481+
if (filePath.indexOf("package.json") !== -1) {
482+
return JSON.stringify({
483+
"name": "invalid name"
484+
});
485+
}
486+
487+
return "";
488+
};
489+
490+
const result = index.getPath(packageName, executableName);
491+
assert.deepEqual(result, null);
492+
});
351493
}
352494
});
353495
});
354496
});
355497

356498
it("throws error when process.platform is not valid", () => {
357499
require("../lib/process-wrapper").getProcessPlatform = () => "1";
358-
assert.throws( () => index.getPath("test1", "test1"), "OS '1' is not supported" );
500+
assert.throws(() => index.getPath("test1", "test1"), "OS '1' is not supported");
359501
});
360502

361503
});

0 commit comments

Comments
 (0)