Skip to content

Commit

Permalink
Add support for UNC paths
Browse files Browse the repository at this point in the history
Wildcards that now work: \\host\directory\*

Wildcards that still don't work: \\host\*

[fixes #74, #123, #146] handle UNC paths on win32

credit to @staticshock for the WinPath work
  • Loading branch information
stefanpenner committed May 6, 2015
1 parent f692617 commit 33cc844
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 10 deletions.
35 changes: 33 additions & 2 deletions common.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ exports.finish = finish
exports.mark = mark
exports.isIgnored = isIgnored
exports.childrenIgnored = childrenIgnored
exports.WinPath = WinPath;

function ownProp (obj, field) {
return Object.prototype.hasOwnProperty.call(obj, field)
Expand All @@ -17,6 +18,22 @@ var minimatch = require("minimatch")
var isAbsolute = require("path-is-absolute")
var Minimatch = minimatch.Minimatch

function WinPath (p) {
if (!(this instanceof WinPath))
return new WinPath(p)

// pull off the device/UNC bit from a windows path.
// from node's lib/path.js
var splitDeviceRe =
/^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/
var result = splitDeviceRe.exec(p)
this.device = result[1] || ''
this.sep = result[2] || ''
this.tail = result[3] || ''
this.isUnc = !!this.device && this.device.charAt(1) !== ':'
this.isAbsolute = !!this.sep || this.isUnc // UNC paths are always absolute
}

function alphasorti (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase())
}
Expand Down Expand Up @@ -62,6 +79,12 @@ function setopts (self, pattern, options) {
}

self.pattern = pattern

self.platform = options.platform || process.platform
self.isAbsolute = isAbsolute[self.platform] || isAbsolute
self.resolve = (path[self.platform] || path).resolve
self.sep = (path[self.platform] || path).sep;

self.strict = options.strict !== false
self.realpath = !!options.realpath
self.realpathCache = options.realpathCache || Object.create(null)
Expand Down Expand Up @@ -95,9 +118,17 @@ function setopts (self, pattern, options) {
self.changedCwd = path.resolve(options.cwd) !== cwd
}

if (self.platform === "win32") {
var winPath = new WinPath(pattern)
if (winPath.isAbsolute) {
options.root = winPath.device
pattern = winPath.sep + winPath.tail
}
}

self.root = options.root || path.resolve(self.cwd, "/")
self.root = path.resolve(self.root)
if (process.platform === "win32")
if (self.platform === "win32")
self.root = self.root.replace(/\\/g, "/")

self.nomount = !!options.nomount
Expand Down Expand Up @@ -212,7 +243,7 @@ function makeAbs (self, f) {
var abs = f
if (f.charAt(0) === '/') {
abs = path.join(self.root, f)
} else if (isAbsolute(f) || f === '') {
} else if (self.isAbsolute(f) || f === '') {
abs = f
} else if (self.changedCwd) {
abs = path.resolve(self.cwd, f)
Expand Down
14 changes: 6 additions & 8 deletions glob.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ var minimatch = require('minimatch')
var Minimatch = minimatch.Minimatch
var inherits = require('inherits')
var EE = require('events').EventEmitter
var path = require('path')
var assert = require('assert')
var isAbsolute = require('path-is-absolute')
var globSync = require('./sync.js')
var common = require('./common.js')
var alphasort = common.alphasort
Expand All @@ -57,7 +55,7 @@ var ownProp = common.ownProp
var inflight = require('inflight')
var util = require('util')
var childrenIgnored = common.childrenIgnored

var path = require('path')
var once = require('once')

function glob (pattern, options, cb) {
Expand Down Expand Up @@ -319,8 +317,8 @@ Glob.prototype._process = function (pattern, index, inGlobStar, cb) {
var read
if (prefix === null)
read = '.'
else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
if (!prefix || !isAbsolute(prefix))
else if (this.isAbsolute(prefix) || this.isAbsolute(pattern.join('/'))) {
if (!prefix || !this.isAbsolute(prefix))
prefix = '/' + prefix
read = prefix
} else
Expand Down Expand Up @@ -639,18 +637,18 @@ Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) {
if (!exists)
return cb()

if (prefix && isAbsolute(prefix) && !this.nomount) {
if (prefix && this.isAbsolute(prefix) && !this.nomount) {
var trail = /[\/\\]$/.test(prefix)
if (prefix.charAt(0) === '/') {
prefix = path.join(this.root, prefix)
} else {
prefix = path.resolve(this.root, prefix)
prefix = this.resolve(this.root, prefix)
if (trail)
prefix += '/'
}
}

if (process.platform === 'win32')
if (this.platform === 'win32')
prefix = prefix.replace(/\\/g, '/')

// Mark this as a match
Expand Down
3 changes: 3 additions & 0 deletions test/bash-results.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,12 @@
"./test/realpath.js",
"./test/root-nomount.js",
"./test/root.js",
"./test/setopts.js",
"./test/slash-cwd.js",
"./test/stat.js",
"./test/sync-cb-throw.js",
"./test/unc-path.js",
"./test/win-path.js",
"./test/zz-cleanup.js",
"/tmp/glob-test/asdf",
"/tmp/glob-test/bar",
Expand Down
35 changes: 35 additions & 0 deletions test/setopts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
var test = require("tap").test
var setopts = require("../common").setopts;

function stubPlatform(platform, fn) {
var descriptor = Object.getOwnPropertyDescriptor(process, 'platform');

try {
Object.defineProperty(process, 'platform', {
value: platform,
writable: false
});

fn();
} finally {
Object.defineProperty(process, 'platform', descriptor);
}

}

test("unit test – setopts – ensure UNC paths are handled correctly", function (t) {

stubPlatform("win32", function() {
var sentinel = { }
setopts(sentinel, "\\\\vmware-host\\Shared Folders\\-folder\\*", { platform: 'win32' })
t.same(sentinel.minimatch.pattern, "\\-folder\\\*")
})

stubPlatform("darwin", function() {
var sentinel = { }
setopts(sentinel, "\\\\vmware-host\\Shared Folders\\-folder\\*", { platform: 'darwin' })
t.same(sentinel.minimatch.pattern, "\\\\vmware-host\\Shared Folders\\-folder\\*")
})

t.end()
})
71 changes: 71 additions & 0 deletions test/unc-path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
var test = require('tap').test;
var glob = require('../');
var fs = require('fs');
var path = require('path');

test('glob doesn\'t choke on UNC paths', function(t) {
stubPlatform('win32', function(restorePlatform) {
var readdir = fs.readdir;

fs.readdir = function(path, cb) {
if (path === '\\\\vmware-share\\share-name\\baz') {
return cb(undefined, [
'some-file.txt',
'some-other-file.txt'
])
}

readdir(path, cb)
}

var results = glob('\\\\vmware-share\\share-name\\baz\\*', function (er, results) {
restorePlatform();

if (er)
throw er

t.same(results, [
'\\\\vmware-share\\share-name\\baz\\some-file.txt',
'\\\\vmware-share\\share-name\\baz\\some-other-file.txt'
])

t.end()
}, { platform: 'win32' })
})
})

function stubPlatform(platform, fn) {
var descriptor = Object.getOwnPropertyDescriptor(process, 'platform')
var path = require('path');
var join = path.join;
var normalize = path.normalize;
var sep = path.sep;
var resolve = path.resolve;
var isAbsolute = require('path-is-absolute');

function restore() {
path.resolve = resolve;
path.sep = sep;
path.join = join;
path.normalize = normalize;
var isAbsolute = require('path-is-absolute');
Object.defineProperty(process, 'platform', descriptor);
}

try {
Object.defineProperty(process, 'platform', {
value: platform,
writable: false
});

path.sep = '\\';
path.resolve = path[platform].resolve;
path.join = path.win32.join;
path.normalize = path.win32.normalize;

return fn(restore);
} catch(e) {
restore();
throw e;
}
}
72 changes: 72 additions & 0 deletions test/win-path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
var WinPath = require('../common').WinPath;
var test = require('tap').test

test("UNIT: WinPath – basic path", function(t) {
var path = new WinPath('basic-path')

t.same(path.device, '');
t.same(path.sep, '');
t.same(path.tail, 'basic-path')

t.end();
});

test("UNIT: WinPath – relative path", function(t) {
var path = new WinPath('relative\\path')

t.same(path.device, '');
t.same(path.sep, '');
t.same(path.tail, 'relative\\path')

t.end();
});

test("UNIT: WinPath – relative path \w glob", function(t) {
var path = new WinPath('relative\\path\\*')

t.same(path.device, '');
t.same(path.sep, '');
t.same(path.tail, 'relative\\path\\*')

t.end();
});

test("UNIT: WinPath – absolute path", function(t) {
var path = new WinPath('\\relative\\path')

t.same(path.device, '');
t.same(path.sep, '\\');
t.same(path.tail, 'relative\\path')

t.end();
});

test("UNIT: WinPath – absolute path \w glob", function(t) {
var path = new WinPath('\\relative\\path\\*')

t.same(path.device, '');
t.same(path.sep, '\\');
t.same(path.tail, 'relative\\path\\*')

t.end();
});

test("UNIT: WinPath – UNC path", function(t) {
var path = new WinPath('\\\\vmware-share\\share-name\\relative\\path')

t.same(path.device, '\\\\vmware-share\\share-name');
t.same(path.sep, '\\');
t.same(path.tail, 'relative\\path')

t.end();
});

test("UNIT: WinPath – UNC path \w glob", function(t) {
var path = new WinPath('\\\\vmware-share\\share-name\\relative\\path\\*')

t.same(path.device, '\\\\vmware-share\\share-name');
t.same(path.sep, '\\');
t.same(path.tail, 'relative\\path\\*')

t.end();
});

0 comments on commit 33cc844

Please sign in to comment.