From ea2f394eee9fcdfc20ef4bd1965cc216611cddd1 Mon Sep 17 00:00:00 2001 From: pgkos Date: Wed, 20 May 2015 00:52:54 +0200 Subject: [PATCH 1/6] Fix and optimize load-paths-handler.coffee --- lib/load-paths-handler.coffee | 108 ++++++++++++++++------------------ 1 file changed, 52 insertions(+), 56 deletions(-) diff --git a/lib/load-paths-handler.coffee b/lib/load-paths-handler.coffee index 55d5f575..ed18e681 100644 --- a/lib/load-paths-handler.coffee +++ b/lib/load-paths-handler.coffee @@ -9,8 +9,6 @@ PathsChunkSize = 100 class PathLoader constructor: (@rootPath, ignoreVcsIgnores, @traverseSymlinkDirectories, @ignoredNames) -> - @paths = [] - @realPathCache = {} @repo = null if ignoreVcsIgnores repo = GitRepository.open(@rootPath, refreshOnWindowFocus: false) @@ -18,68 +16,66 @@ class PathLoader load: (done) -> @loadPath @rootPath, => - @flushPaths() @repo?.destroy() done() - isIgnored: (loadedPath) -> - relativePath = path.relative(@rootPath, loadedPath) - if @repo?.isPathIgnored(relativePath) - true - else - for ignoredName in @ignoredNames - return true if ignoredName.match(relativePath) + emitPaths: (paths) -> + emit('load-paths:paths-found', paths) - pathLoaded: (loadedPath, done) -> - @paths.push(loadedPath) unless @isIgnored(loadedPath) - if @paths.length is PathsChunkSize - @flushPaths() - done() - - flushPaths: -> - emit('load-paths:paths-found', @paths) - @paths = [] + isFilenameIgnored: (filename) -> + for matcher in @ignoredNames + return true if matcher.match filename loadPath: (pathToLoad, done) -> - return done() if @isIgnored(pathToLoad) - fs.lstat pathToLoad, (error, stats) => - return done() if error? - if stats.isSymbolicLink() - @isInternalSymlink pathToLoad, (isInternal) => - return done() if isInternal - fs.stat pathToLoad, (error, stats) => - return done() if error? - if stats.isFile() - @pathLoaded(pathToLoad, done) - else if stats.isDirectory() - if @traverseSymlinkDirectories - @loadFolder(pathToLoad, done) - else - done() - else - done() - else if stats.isDirectory() - @loadFolder(pathToLoad, done) - else if stats.isFile() - @pathLoaded(pathToLoad, done) - else - done() + visitedDirs = {}; + paths = []; + counter = 0; + + statOrLstatSync = if @traverseSymlinkDirectories then fs.statSync else fs.lstatSync + + appendPath = (path) => + paths[counter] = path + counter = (counter + 1) % PathsChunkSize + @emitPaths paths if counter == 0 + return + + traverseRecursively = (root) => + try + children = fs.readdirSync root + catch error + return + for child in children + if @isFilenameIgnored child + continue + childPath = path.join root, child + try + fileStat = statOrLstatSync childPath + catch error + continue + if fileStat.isSymbolicLink() + symlinkTargetStat = fs.statSync childPath + appendPath childPath if symlinkTargetStat.isFile() + else if fileStat.isDirectory() + try + childRealPath = fs.realpathSync childPath + catch error + continue + if childRealPath of visitedDirs + continue + else + visitedDirs[childRealPath] = true + traverseRecursively childPath + else if fileStat.isFile() + appendPath childPath + return + + traverseRecursively pathToLoad + + paths.length = counter + @emitPaths paths if paths.length - loadFolder: (folderPath, done) -> - fs.readdir folderPath, (error, children=[]) => - async.each( - children, - (childName, next) => - @loadPath(path.join(folderPath, childName), next) - done - ) + return done() - isInternalSymlink: (pathToLoad, done) -> - fs.realpath pathToLoad, @realPathCache, (err, realPath) => - if err - done(false) - else - done(realPath.search(@rootPath) is 0) module.exports = (rootPaths, followSymlinks, ignoreVcsIgnores, ignores=[]) -> ignoredNames = [] From 8c965a503537284e93604fd85be61f33fc5c4e58 Mon Sep 17 00:00:00 2001 From: pgkos Date: Thu, 21 May 2015 19:13:34 +0200 Subject: [PATCH 2/6] Corrected checking if path is ignored --- lib/load-paths-handler.coffee | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/load-paths-handler.coffee b/lib/load-paths-handler.coffee index ed18e681..4a6a5199 100644 --- a/lib/load-paths-handler.coffee +++ b/lib/load-paths-handler.coffee @@ -22,9 +22,13 @@ class PathLoader emitPaths: (paths) -> emit('load-paths:paths-found', paths) - isFilenameIgnored: (filename) -> - for matcher in @ignoredNames - return true if matcher.match filename + isPathIgnored: (path) -> + relativePath = path.relative(@rootPath, path) + if @repo?.isPathIgnored(relativePath) + return true + else + for ignoredName in @ignoredNames + return true if ignoredName.match(relativePath) loadPath: (pathToLoad, done) -> visitedDirs = {}; @@ -45,9 +49,9 @@ class PathLoader catch error return for child in children - if @isFilenameIgnored child - continue childPath = path.join root, child + if @isPathIgnored childPath + continue try fileStat = statOrLstatSync childPath catch error From 37173279a059c1004cfebfe324e887fdd7468be1 Mon Sep 17 00:00:00 2001 From: pgkos Date: Fri, 29 May 2015 22:59:57 +0200 Subject: [PATCH 3/6] Fix parameter name in PathLoader.isPathIgnored --- lib/load-paths-handler.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/load-paths-handler.coffee b/lib/load-paths-handler.coffee index 4a6a5199..1f2dfb93 100644 --- a/lib/load-paths-handler.coffee +++ b/lib/load-paths-handler.coffee @@ -22,8 +22,8 @@ class PathLoader emitPaths: (paths) -> emit('load-paths:paths-found', paths) - isPathIgnored: (path) -> - relativePath = path.relative(@rootPath, path) + isPathIgnored: (pathStr) -> + relativePath = path.relative(@rootPath, pathStr) if @repo?.isPathIgnored(relativePath) return true else From b531bb3d87cbe286ba694aa24a16b2d3a53787f4 Mon Sep 17 00:00:00 2001 From: pgkos Date: Sat, 30 May 2015 12:37:09 +0200 Subject: [PATCH 4/6] Fix to make tests pass --- lib/load-paths-handler.coffee | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/lib/load-paths-handler.coffee b/lib/load-paths-handler.coffee index 1f2dfb93..5d2cc0c9 100644 --- a/lib/load-paths-handler.coffee +++ b/lib/load-paths-handler.coffee @@ -35,15 +35,13 @@ class PathLoader paths = []; counter = 0; - statOrLstatSync = if @traverseSymlinkDirectories then fs.statSync else fs.lstatSync - appendPath = (path) => paths[counter] = path counter = (counter + 1) % PathsChunkSize @emitPaths paths if counter == 0 return - traverseRecursively = (root) => + traverseRecursively = (root, realRoot) => try children = fs.readdirSync root catch error @@ -53,17 +51,26 @@ class PathLoader if @isPathIgnored childPath continue try - fileStat = statOrLstatSync childPath + fileStat = fs.lstatSync childPath catch error continue if fileStat.isSymbolicLink() - symlinkTargetStat = fs.statSync childPath - appendPath childPath if symlinkTargetStat.isFile() - else if fileStat.isDirectory() + try + symlinkTargetStat = fs.statSync childPath + catch error + continue try childRealPath = fs.realpathSync childPath catch error continue + if symlinkTargetStat.isFile() && childRealPath.startsWith(realPathToLoad) + continue + else if symlinkTargetStat.isDirectory() && !@traverseSymlinkDirectories + continue + fileStat = symlinkTargetStat + else + childRealPath = childPath + if fileStat.isDirectory() if childRealPath of visitedDirs continue else @@ -73,7 +80,8 @@ class PathLoader appendPath childPath return - traverseRecursively pathToLoad + realPathToLoad = fs.realpathSync pathToLoad + traverseRecursively pathToLoad, realPathToLoad paths.length = counter @emitPaths paths if paths.length @@ -90,7 +98,7 @@ module.exports = (rootPaths, followSymlinks, ignoreVcsIgnores, ignores=[]) -> console.warn "Error parsing ignore pattern (#{ignore}): #{error.message}" async.each( - rootPaths, + rootPaths.reverse(), (rootPath, next) -> new PathLoader( rootPath, From c488386097259c8a206b4f0b2063033938f6ea31 Mon Sep 17 00:00:00 2001 From: pgkos Date: Sat, 30 May 2015 12:42:32 +0200 Subject: [PATCH 5/6] Fix style --- lib/load-paths-handler.coffee | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/load-paths-handler.coffee b/lib/load-paths-handler.coffee index 5d2cc0c9..0f2f9e70 100644 --- a/lib/load-paths-handler.coffee +++ b/lib/load-paths-handler.coffee @@ -31,14 +31,14 @@ class PathLoader return true if ignoredName.match(relativePath) loadPath: (pathToLoad, done) -> - visitedDirs = {}; - paths = []; - counter = 0; + visitedDirs = {} + paths = [] + counter = 0 appendPath = (path) => paths[counter] = path counter = (counter + 1) % PathsChunkSize - @emitPaths paths if counter == 0 + @emitPaths paths if counter is 0 return traverseRecursively = (root, realRoot) => @@ -63,9 +63,9 @@ class PathLoader childRealPath = fs.realpathSync childPath catch error continue - if symlinkTargetStat.isFile() && childRealPath.startsWith(realPathToLoad) + if symlinkTargetStat.isFile() and childRealPath.startsWith(realPathToLoad) continue - else if symlinkTargetStat.isDirectory() && !@traverseSymlinkDirectories + else if symlinkTargetStat.isDirectory() and not @traverseSymlinkDirectories continue fileStat = symlinkTargetStat else From 0000ce49f822bb02b91fc976e65e5b317c928e69 Mon Sep 17 00:00:00 2001 From: pgkos Date: Sat, 30 May 2015 13:38:22 +0200 Subject: [PATCH 6/6] Optimize recursive traversal --- lib/load-paths-handler.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/load-paths-handler.coffee b/lib/load-paths-handler.coffee index 0f2f9e70..53c2a151 100644 --- a/lib/load-paths-handler.coffee +++ b/lib/load-paths-handler.coffee @@ -69,13 +69,13 @@ class PathLoader continue fileStat = symlinkTargetStat else - childRealPath = childPath + childRealPath = path.join realRoot, child if fileStat.isDirectory() if childRealPath of visitedDirs continue else visitedDirs[childRealPath] = true - traverseRecursively childPath + traverseRecursively childPath, childRealPath else if fileStat.isFile() appendPath childPath return