Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Add path.common(path1/*, ...pathn*/); #6328

Open
wants to merge 1 commit into from

5 participants

@medikoo
var path = require('path');

path.common('/lorem/ipsum/foo/bar', '/lorem/ipsum/raz/dwa', '/lorem/elo/foo/bar'); //  => '/lorem'

path.common('/foo/bar', '/raz/dwa'); // => '/'

path.common('C:\\\\foo\\bar', 'D:\\\\foo\\bar'); // => null

I have use case for it in few of my modules (using counterparts for now), and I wonder why it's not part of path API.

I'll be happy to provide a pull request, but before that I'd like to be sure that you're open for such add on.

@isaacs isaacs was assigned
@trevnorris
Owner

@isaacs pretty sure I know your answer will be, but want you to have the final say. :)

@medikoo medikoo referenced this pull request from a commit in medikoo/node
@medikoo medikoo path: `path.common`
Fix #6328
c4c96de
@Nodejs-Jenkins

Thank you for contributing this pull request! Here are a few pointers to make sure your submission will be considered for inclusion.

The following commiters were not found in the CLA:

  • Mariusz Nowak

You can fix all these things without opening another issue.

Please see CONTRIBUTING.md for more information

@medikoo

I've signed the CLA,

Please consider adding this feature. Otherwise I'll probably publish it with e.g. path-ext package. Thanks

@litmit

Why path.common('C:\\\\foo\\bar', 'D:\\\\foo\\bar'); return null not ''?

@medikoo

@litmit '' resolves to current path (process.cwd()) and that's not valid result for that case

@medikoo

In a meantime I've published path.common with path2 package, a modular and extended version of path

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 14, 2014
  1. @medikoo

    path: `path.common`

    medikoo authored
    Fix #6328
This page is out of date. Refresh to see the latest.
Showing with 139 additions and 0 deletions.
  1. +92 −0 lib/path.js
  2. +47 −0 test/simple/test-path.js
View
92 lib/path.js
@@ -84,6 +84,16 @@ if (isWindows) {
return '\\\\' + device.replace(/^[\\\/]+/, '').replace(/[\\\/]+/g, '\\');
};
+ var normalizeForCommon = function (path) {
+ if (!util.isString(path)) {
+ throw new TypeError('Arguments to path.common must be strings');
+ }
+ var isDir = (path[path.length - 1] === '\\');
+ path = exports.resolve(path);
+ if (isDir) return path;
+ return exports.dirname(path);
+ };
+
// path.resolve([from ...], to)
// windows version
exports.resolve = function() {
@@ -300,6 +310,44 @@ if (isWindows) {
return outputParts.join('\\');
};
+ // path.common(path1/*, ...pathn*/)
+ // windows version
+ exports.common = function(path/*, ...pathn*/) {
+ path = normalizeForCommon(path);
+ var i = 1;
+ var l = arguments.length;
+ var pathLength = path.length;
+ for (; i < l; ++i) {
+ var other = normalizeForCommon(arguments[i]).toLowerCase();
+ var end = 0;
+ var j = 0;
+ var otherLength = other.length;
+ while (path[j].toLowerCase() === other[j]) {
+ if (path[j] === '\\') end = j;
+ ++j;
+ if (pathLength === j) {
+ if (otherLength === j) end = j;
+ else if (other[j] === '\\') end = j;
+ break;
+ }
+ if (otherLength === j) {
+ if (path[j] === '\\') end = j;
+ break;
+ }
+ }
+ if (!end) return null;
+ if (end !== pathLength) {
+ path = path.slice(0, end);
+ if (path[path.length - 1] === ':') {
+ path += '\\';
+ ++end;
+ }
+ pathLength = end;
+ }
+ }
+ return path;
+ };
+
exports.sep = '\\';
exports.delimiter = ';';
@@ -312,6 +360,15 @@ if (isWindows) {
var splitPath = function(filename) {
return splitPathRe.exec(filename).slice(1);
};
+ var normalizeForCommon = function (path) {
+ if (!util.isString(path)) {
+ throw new TypeError('Arguments to path.common must be strings');
+ }
+ var isDir = (path[path.length - 1] === '/');
+ path = exports.resolve(path);
+ if (isDir) return path;
+ return exports.dirname(path);
+ };
// path.resolve([from ...], to)
// posix version
@@ -438,6 +495,41 @@ if (isWindows) {
return outputParts.join('/');
};
+ // path.common(path1/*, ...pathn*/)
+ // posix version
+ exports.common = function(path/*, ...pathn*/) {
+ path = normalizeForCommon(path);
+ if (path === '/') return '/';
+ var i = 1;
+ var l = arguments.length;
+ var pathLength = path.length;
+ for (; i < l; ++i) {
+ var other = normalizeForCommon(arguments[i]);
+ var end = 0;
+ var j = 0;
+ var otherLength = other.length;
+ while (path[j] === other[j]) {
+ if (path[j] === '/') end = j;
+ ++j;
+ if (pathLength === j) {
+ if (otherLength === j) end = j;
+ else if (other[j] === '/') end = j;
+ break;
+ }
+ if (otherLength === j) {
+ if (path[j] === '/') end = j;
+ break;
+ }
+ }
+ if (end <= 1) return '/';
+ if (end !== pathLength) {
+ path = path.slice(0, end);
+ pathLength = end;
+ }
+ }
+ return path;
+ };
+
exports.sep = '/';
exports.delimiter = ':';
}
View
47 test/simple/test-path.js
@@ -405,6 +405,53 @@ relativeTests.forEach(function(test) {
});
assert.equal(failures.length, 0, failures.join(''));
+// path.common tests
+if (isWindows) {
+ // windows
+ var resolveTests =
+ // arguments result
+ [[['C:\\'], 'C:\\'],
+ [['d:\\'], 'd:\\'],
+ [['c:\\', 'd:\\'], null],
+ [['c:\\raz\\dwa\\'], 'c:\\raz\\dwa'],
+ [['C:\\raZ\\dwa'], 'C:\\raZ'],
+ [['c:\\raz\\dwa', 'c:\\trzy\\cztery'], 'c:\\'],
+ [['c:\\raz\\dwa', 'c:\\raz\\trzy'], 'c:\\raz'],
+ [['c:\\raZ\\dwa', 'c:\\rAz\\trzy'], 'c:\\raZ'],
+ [['c:\\raz\\dwa', 'c:\\raz\\dwa\\trzy', 'c:\\raz\\cztery'], 'c:\\raz'],
+ [['C:\\raz\\dwa\\piec', 'c:\\raz\\dwa\\trzy', 'c:\\raz\\dwa\\cztery'],
+ 'C:\\raz\\dwa'],
+ [['C:\\raz\\dwa\\piec', 'c:\\raz\\dwa\\trzy', 'c:\\raz\\dwa\\'],
+ 'C:\\raz\\dwa'],
+ [['c:\\raz\\dwa\\piec', 'c:\\raz\\dwa\\trzy', 'c:\\raz\\dwa'],
+ 'c:\\raz'],
+ [['c:\\raz\\dwa\\trzy', 'c:\\raz\\dwatrzy'], 'c:\\raz']];
+} else {
+ // Posix
+ var resolveTests =
+ // arguments result
+ [[['/'], '/'],
+ [['/raz/dwa/'], '/raz/dwa'],
+ [['/raz/dwa'], '/raz'],
+ [['/raz/dwa', '/trzy/cztery'], '/'],
+ [['/raz/dwa', '/raz/trzy'], '/raz'],
+ [['/raz/dwa', '/raz/dwa/trzy', '/raz/cztery'], '/raz'],
+ [['/raz/dwa/piec', '/raz/dwa/trzy', '/raz/dwa/cztery'], '/raz/dwa'],
+ [['/raz/dwa/piec', '/raz/dwa/trzy', '/raz/dwa/'], '/raz/dwa'],
+ [['/raz/dwa/piec', '/raz/dwa/trzy', '/raz/dwa'], '/raz'],
+ [['/raz/dwa/trzy', '/raz/dwatrzy'], '/raz']];
+}
+var failures = [];
+resolveTests.forEach(function(test) {
+ var actual = path.common.apply(path, test[0]);
+ var expected = test[1];
+ var message = 'path.common(' + test[0].map(JSON.stringify).join(',') + ')' +
+ '\n expect=' + JSON.stringify(expected) +
+ '\n actual=' + JSON.stringify(actual);
+ if (actual !== expected) failures.push('\n' + message);
+});
+assert.equal(failures.length, 0, failures.join(''));
+
// path.sep tests
if (isWindows) {
// windows
Something went wrong with that request. Please try again.