diff options
Diffstat (limited to 'deps/npm/lib/utils/relativize.js')
-rw-r--r-- | deps/npm/lib/utils/relativize.js | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/deps/npm/lib/utils/relativize.js b/deps/npm/lib/utils/relativize.js new file mode 100644 index 0000000000..74c45c5d3e --- /dev/null +++ b/deps/npm/lib/utils/relativize.js @@ -0,0 +1,70 @@ + +module.exports = relativize + +// return the shortest path between two folders. +// if the original path is shorter, then use that, +// unless forceRelative is set to true. +var path = require("path") +function relativize (dest, src, forceRelative) { + var orig = dest + if (!isAbsolute(src)) forceRelative = true + else if (!isAbsolute(dest)) return false + src = path.resolve(src) + dest = path.resolve(dest) + if (src === dest) return "." + src = src.split(split) + dest = dest.split(split) + var i = 0 + while (src[i] === dest[i]) i++ + if (!forceRelative && i === 1) return orig // nothing in common + src.splice(0, i + 1) + var dots = [0, i, "."] + for (var i = 0, l = src.length; i < l; i ++) dots.push("..") + dest.splice.apply(dest, dots) + if (dest[0] === "." && dest[1] === "..") dest.shift() + dest = dest.join("/") + return !forceRelative && orig.length < dest.length ? orig : dest +} + +var split = process.platform === "win32" ? /[\/\\]/ : "/" + +function isAbsolute (p) { + if (process.platform !== "win32") return p.charAt(0) === "/" + return path.resolve(p) === p +} + +if (module === require.main) { + // from, to, result, relativeForced + var assert = require("assert") + + ; [ ["/bar" ,"/foo" ,"/bar" ,"./bar" ] + , ["/foo/baz" ,"/foo/bar/baz" ,"../baz" ,"../baz" ] + , ["/a/d" ,"/a/b/c/d/e/f" ,"/a/d" ,"../../../../d" ] + // trailing slashes are ignored. + , ["/a/d" ,"/a/b/c/d/e/" ,"/a/d" ,"../../../d" ] + , ["./foo/bar" ,"./foo/baz" ,"./bar" ,"./bar" ] + // force relative when the src is relative. + , ["./d" ,"./a/b/c/d/e" ,"../../../../d" ,"../../../../d" ] + // if src is abs and dest is relative, then fail + , ["./d" ,"/a/b" ,false ,false ] + ].forEach(function (test) { + var d = test[0] + , s = test[1] + , r = test[2] + , rr = test[3] + , ra = relativize(d, s) + , rra = relativize(d, s, true) + console.log([d, s, r, rr], [ra, rra], [r === ra, rr === rra]) + assert.equal(r, ra) + assert.equal(rr, rra) + if (!r) return + // contract: this is the relative path from absolute A to absolute B + var ad = path.resolve(d) + , as = path.resolve(s) + , dir = path.dirname(as) + assert.equal(path.resolve(dir, rr), ad) + assert.equal(path.resolve(dir, r), ad) + }) + + console.log("ok") +} |