Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for following symlinks #148

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ test/a/
node_modules/*
v8.log
profile.txt
.idea
.DS_Store
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ filesystem.
* `symlinks` A cache of known symbolic links. You may pass in a
previously generated `symlinks` object to save `lstat` calls when
resolving `**` matches.
* `realpath` Set to true to follow all symlinks with `**` and `*` matchers.
By default symlinks are not followed by `*` or `**`.
* `sync` Perform a synchronous glob search.
* `nounique` In some cases, brace-expanded patterns can result in the
same file showing up multiple times in the result set. By default,
Expand Down
1 change: 1 addition & 0 deletions common.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ function setopts (self, pattern, options) {
self.cache = options.cache || Object.create(null)
self.statCache = options.statCache || Object.create(null)
self.symlinks = options.symlinks || Object.create(null)
self.realpath = !!options.realpath

self.changedCwd = false
var cwd = process.cwd()
Expand Down
9 changes: 6 additions & 3 deletions glob.js
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,9 @@ Glob.prototype._readdirInGlobStar = function (abs, cb) {

// If it's not a symlink or a dir, then it's definitely a regular file.
// don't bother doing a readdir in that case.
if (!isSym && !lstat.isDirectory()) {
// If it's a symlink with followSymlinks toggled true and not a dir,
// treat as file
if ((!isSym || this.followSymlinks) && !lstat.isDirectory()) {
self.cache[abs] = 'FILE'
cb()
} else
Expand Down Expand Up @@ -529,8 +531,9 @@ Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, i
var isSym = this.symlinks[abs]
var len = entries.length

// If it's a symlink, and we're in a globstar, then stop
if (isSym && inGlobStar)
// If it's a symlink, we're in a globstar,
// and we did not specify realpath, then stop
if (isSym && inGlobStar && !this.realpath)
return cb()

for (var i = 0; i < len; i++) {
Expand Down
9 changes: 6 additions & 3 deletions sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,9 @@ GlobSync.prototype._readdirInGlobStar = function (abs) {

// If it's not a symlink or a dir, then it's definitely a regular file.
// don't bother doing a readdir in that case.
if (!isSym && !lstat.isDirectory())
// If it's a symlink with followSymlinks toggled true and not a dir,
// treat as file
if ((!isSym || this.realpath) && !lstat.isDirectory())
this.cache[abs] = 'FILE'
else
entries = this._readdir(abs, false)
Expand Down Expand Up @@ -306,8 +308,9 @@ GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index
var len = entries.length
var isSym = this.symlinks[abs]

// If it's a symlink, and we're in a globstar, then stop
if (isSym && inGlobStar)
// If it's a symlink, and we're in a globstar,
// and we did not specify realpath, then stop
if (isSym && inGlobStar && !this.realpath)
return

for (var i = 0; i < len; i++) {
Expand Down
1 change: 1 addition & 0 deletions test/bash-results.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
"./test/error-callback.js",
"./test/global-leakage.js",
"./test/globstar-match.js",
"./test/globstar-symlink.js",
"./test/has-magic.js",
"./test/mark-sync.js",
"./test/mark.js",
Expand Down
2 changes: 1 addition & 1 deletion test/globstar-match.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ test('globstar should not have dupe matches', function(t) {
t.same(matches, set, 'should have same set of matches')
t.end()
})
})
})
31 changes: 31 additions & 0 deletions test/globstar-symlink.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require("./global-leakage.js")
var Glob = require("../glob.js").Glob
var GlobSync = require("../sync.js").GlobSync
var test = require('tap').test
var path = require('path')
var fs = require('fs')
var pattern = '**/g.js'
var symlinkTo = path.join(__dirname, 'a/symlink2')
var symlinkFrom = path.join(__dirname, '../examples')

test('globstar should match symlinks', function(t) {
fs.symlinkSync(symlinkFrom, symlinkTo)
var g = new Glob(pattern, { cwd: __dirname, realpath: true })
var matches = []
g.on('match', function (m) {
matches.push(m)
})
g.on('end', function() {
fs.unlink(symlinkTo)
t.equal(matches.length, 1)
t.end()
})
})

test('sync globstar should match symlinks', function(t) {
fs.symlinkSync(symlinkFrom, symlinkTo)
var g = new GlobSync(pattern, { cwd: __dirname, realpath: true })
fs.unlink(symlinkTo)
t.equal(g.found.length, 1)
t.end()
})