Skip to content

Commit 3ed3574

Browse files
feat: index ignored paths
1 parent 4575137 commit 3ed3574

File tree

6 files changed

+109
-25
lines changed

6 files changed

+109
-25
lines changed

packages/fuzzy-finder/lib/load-paths-handler.js

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const realRgPath = rgPath.replace(/\bapp\.asar\b/, 'app.asar.unpacked')
1919
const MaxConcurrentCrawls = Math.min(Math.max(os.cpus().length - 1, 8), 1)
2020

2121
const trackedPaths = new Set()
22+
const ignoredPaths = new Set()
2223

2324
class PathLoader {
2425
constructor (rootPath, options) {
@@ -29,6 +30,7 @@ class PathLoader {
2930
this.useRipGrep = options.useRipGrep
3031
this.indexIgnoredPaths = options.indexIgnoredPaths
3132
this.paths = []
33+
this.ignoredPaths = []
3234
this.inodes = new Set()
3335
this.repo = null
3436
if (this.ignoreVcsIgnores && !this.useRipGrep) {
@@ -41,7 +43,11 @@ class PathLoader {
4143

4244
load (done) {
4345
if (this.useRipGrep) {
44-
this.loadFromRipGrep().then(done)
46+
// first, load tracked paths and populate the set of tracked paths
47+
// then, load all paths (tracked and not), using the above set to differentiate
48+
this.loadFromRipGrep()
49+
.then(() => this.indexIgnoredPaths && this.loadFromRipGrep({loadIgnoredPaths: true}))
50+
.then(done)
4551

4652
return
4753
}
@@ -53,20 +59,22 @@ class PathLoader {
5359
})
5460
}
5561

56-
async loadFromRipGrep () {
62+
async loadFromRipGrep (options = {}) {
5763
return new Promise((resolve) => {
5864
const args = ['--files', '--hidden', '--sort', 'path']
5965

60-
if (!this.ignoreVcsIgnores) {
66+
if (!this.ignoreVcsIgnores || options.loadIgnoredPaths) {
6167
args.push('--no-ignore')
6268
}
6369

6470
if (this.traverseSymlinkDirectories) {
6571
args.push('--follow')
6672
}
6773

68-
for (let ignoredName of this.ignoredNames) {
69-
args.push('-g', '!' + ignoredName.pattern)
74+
if (! options.loadIgnoredPaths) {
75+
for (let ignoredName of this.ignoredNames) {
76+
args.push('-g', '!' + ignoredName.pattern)
77+
}
7078
}
7179

7280
if (this.ignoreVcsIgnores) {
@@ -83,7 +91,11 @@ class PathLoader {
8391

8492
for (const file of files) {
8593
let loadedPath = path.join(this.rootPath, file)
86-
this.trackedPathLoaded(loadedPath, null)
94+
if (options.loadIgnoredPaths) {
95+
this.ignoredPathLoaded(loadedPath)
96+
} else {
97+
this.trackedPathLoaded(loadedPath)
98+
}
8799
}
88100
})
89101
result.stderr.on('data', () => {
@@ -116,16 +128,36 @@ class PathLoader {
116128
if (this.paths.length === PathsChunkSize) {
117129
this.flushPaths()
118130
}
131+
132+
done && done()
133+
}
134+
135+
ignoredPathLoaded (loadedPath, done) {
136+
if (trackedPaths.has(loadedPath)) {
137+
return
138+
}
139+
140+
if (!ignoredPaths.has(loadedPath)) {
141+
ignoredPaths.add(loadedPath)
142+
this.ignoredPaths.push(loadedPath)
143+
}
144+
145+
if (this.ignoredPaths.length === PathsChunkSize) {
146+
this.flushPaths()
147+
}
148+
119149
done && done()
120150
}
121151

122152
flushPaths () {
123-
emit('load-paths:paths-found', this.paths)
153+
emit('load-paths:paths-found', {paths: this.paths, ignoredPaths: this.ignoredPaths})
124154
this.paths = []
155+
this.ignoredPaths = []
125156
}
126157

127158
loadPath (pathToLoad, root, done) {
128-
if (this.isIgnored(pathToLoad) && !root) return done()
159+
const isIgnored = this.isIgnored(pathToLoad)
160+
if (isIgnored && !this.indexIgnoredPaths && !root) return done()
129161

130162
fs.lstat(pathToLoad, (error, stats) => {
131163
if (error != null) { return done() }
@@ -139,7 +171,13 @@ class PathLoader {
139171
}
140172

141173
if (stats.isFile()) {
142-
this.trackedPathLoaded(pathToLoad, done)
174+
if (!isIgnored ) {
175+
this.trackedPathLoaded(pathToLoad, done)
176+
} else if (this.indexIgnoredPaths) {
177+
this.ignoredPathLoaded(pathToLoad, done)
178+
} else {
179+
done()
180+
}
143181
} else if (stats.isDirectory()) {
144182
if (this.traverseSymlinkDirectories) {
145183
this.loadFolder(pathToLoad, done)
@@ -153,9 +191,22 @@ class PathLoader {
153191
} else {
154192
this.inodes.add(stats.ino)
155193
if (stats.isDirectory()) {
156-
this.loadFolder(pathToLoad, done)
194+
// descend into the .git dir only if we're including ignored paths
195+
// FIXME this it not correct if the repo dir is non-default
196+
// FIXME / is not platform agnostic
197+
if (!pathToLoad.match(/(^|\/)\.git/) || !this.ignoreVcsIgnores) {
198+
this.loadFolder(pathToLoad, done)
199+
} else {
200+
done()
201+
}
157202
} else if (stats.isFile()) {
158-
this.trackedPathLoaded(pathToLoad, done)
203+
if (!isIgnored) {
204+
this.trackedPathLoaded(pathToLoad, done)
205+
} else if (this.indexIgnoredPaths) {
206+
this.ignoredPathLoaded(pathToLoad, done)
207+
} else {
208+
done()
209+
}
159210
} else {
160211
done()
161212
}

packages/fuzzy-finder/lib/main.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ module.exports = {
4848
this.gitStatusView = null
4949
}
5050
this.projectPaths = null
51+
this.ignoredPaths = null
5152
this.stopLoadPathsTask()
5253
this.active = false
5354
},
@@ -82,8 +83,9 @@ module.exports = {
8283

8384
if (this.projectView == null) {
8485
const ProjectView = require('./project-view')
85-
this.projectView = new ProjectView(this.projectPaths)
86+
this.projectView = new ProjectView(this.projectPaths, this.ignoredPaths)
8687
this.projectPaths = null
88+
this.ignoredPaths = null
8789
if (this.teletypeService) {
8890
this.projectView.setTeletypeService(this.teletypeService)
8991
}
@@ -117,11 +119,13 @@ module.exports = {
117119
if (atom.project.getPaths().length === 0) return
118120

119121
const PathLoader = require('./path-loader')
120-
this.loadPathsTask = PathLoader.startTask((projectPaths) => {
122+
this.loadPathsTask = PathLoader.startTask((projectPaths, ignoredPaths) => {
121123
this.projectPaths = projectPaths
124+
this.ignoredPaths = ignoredPaths
122125
})
123126
this.projectPathsSubscription = atom.project.onDidChangePaths(() => {
124127
this.projectPaths = null
128+
this.ignoredPaths = null
125129
this.stopLoadPathsTask()
126130
})
127131
},

packages/fuzzy-finder/lib/path-loader.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const {Task} = require('atom')
44
module.exports = {
55
startTask (callback) {
66
const results = []
7+
const ignoredResults = []
78
const taskPath = require.resolve('./load-paths-handler')
89
const followSymlinks = atom.config.get('core.followSymlinks')
910
let ignoredNames = atom.config.get('fuzzy-finder.ignoredNames') || []
@@ -23,13 +24,14 @@ module.exports = {
2324
useRipGrep,
2425
indexIgnoredPaths
2526
},
26-
() => callback(results)
27+
() => callback(results, ignoredResults)
2728
)
2829

2930
task.on('load-paths:paths-found',
3031
(paths) => {
31-
paths = paths || []
32-
results.push(...paths)
32+
paths = paths || {paths: [], ignoredPaths: []}
33+
results.push(...paths.paths)
34+
ignoredResults.push(...paths.ignoredPaths)
3335
}
3436
)
3537

packages/fuzzy-finder/lib/project-view.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ const PathLoader = require('./path-loader')
66

77
module.exports =
88
class ProjectView extends FuzzyFinderView {
9-
constructor (paths) {
9+
constructor (paths, ignoredPaths) {
1010
super()
1111
this.disposables = new CompositeDisposable()
1212
this.paths = paths
13+
this.ignoredPaths = ignoredPaths
14+
// if no paths were passed in, then we should try to reload them
1315
this.reloadPaths = !this.paths || this.paths.length === 0
1416
this.reloadAfterFirstLoad = false
1517

@@ -30,8 +32,10 @@ class ProjectView extends FuzzyFinderView {
3032
this.disposables.add(atom.config.onDidChange('core.ignoredNames', () => { this.reloadPaths = true }))
3133
this.disposables.add(atom.config.onDidChange('core.excludeVcsIgnoredPaths', () => { this.reloadPaths = true }))
3234
this.disposables.add(atom.project.onDidChangePaths(() => {
35+
// if a project path was changed/added/removed, clear our list and reindex
3336
this.reloadPaths = true
3437
this.paths = null
38+
this.ignoredPaths = null
3539
}))
3640

3741
if (!this.reloadPaths) {
@@ -74,7 +78,8 @@ class ProjectView extends FuzzyFinderView {
7478
})
7579

7680
const localItems = this.projectRelativePathsForFilePaths(this.paths || [])
77-
await this.setItems(remoteItems.concat(localItems))
81+
const localIgnoredItems = this.projectRelativePathsForFilePaths(this.ignoredPaths || [])
82+
await this.setItems(remoteItems.concat(localItems), localIgnoredItems)
7883
}
7984

8085
async reloadPathsIfNeeded () {
@@ -114,7 +119,8 @@ class ProjectView extends FuzzyFinderView {
114119
if (task) {
115120
let pathsFound = 0
116121
task.on('load-paths:paths-found', (paths) => {
117-
pathsFound += paths.length
122+
paths = paths || {paths: [], ignoredPaths: []}
123+
pathsFound += paths.paths.length + paths.ignoredPaths.length
118124
this.selectListView.update({loadingMessage: 'Indexing project\u2026', infoMessage: null, loadingBadge: humanize.intComma(pathsFound)})
119125
})
120126
}
@@ -178,8 +184,9 @@ class ProjectView extends FuzzyFinderView {
178184
this.loadPathsTask.terminate()
179185
}
180186

181-
this.loadPathsTask = PathLoader.startTask((paths) => {
187+
this.loadPathsTask = PathLoader.startTask((paths, ignoredPaths) => {
182188
this.paths = paths
189+
this.ignoredPaths = ignoredPaths
183190
this.reloadPaths = false
184191
if (fn) {
185192
fn()

packages/fuzzy-finder/spec/fuzzy-finder-spec.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -822,21 +822,26 @@ describe('FuzzyFinder', () => {
822822
})
823823

824824
it('passes the indexed paths into the project view when it is created', () => {
825-
const {projectPaths} = fuzzyFinder
825+
const {projectPaths, ignoredPaths} = fuzzyFinder
826826
expect(projectPaths.length).toBe(19)
827+
expect(ignoredPaths.length).toBe(0)
828+
827829
projectView = fuzzyFinder.createProjectView()
828830
expect(projectView.paths).toBe(projectPaths)
831+
expect(projectView.ignoredPaths).toBe(ignoredPaths)
829832
expect(projectView.reloadPaths).toBe(false)
830833
})
831834

832835
it('busts the cached paths when the project paths change', () => {
833836
atom.project.setPaths([])
834837

835-
const {projectPaths} = fuzzyFinder
838+
const {projectPaths, ignoredPaths} = fuzzyFinder
836839
expect(projectPaths).toBe(null)
840+
expect(ignoredPaths).toBe(null)
837841

838842
projectView = fuzzyFinder.createProjectView()
839843
expect(projectView.paths).toBe(null)
844+
expect(projectView.ignoredPaths).toBe(null)
840845
expect(projectView.reloadPaths).toBe(true)
841846
})
842847
})
@@ -1612,6 +1617,21 @@ describe('FuzzyFinder', () => {
16121617

16131618
await waitForPathsToDisplay(projectView)
16141619

1620+
expect(projectView.paths.length).toBe(6)
1621+
expect(projectView.ignoredPaths.length).toBe(0)
1622+
1623+
expect(Array.from(projectView.element.querySelectorAll('li')).find(a => a.textContent.includes('ignored.txt'))).not.toBeDefined()
1624+
})
1625+
1626+
it('includes paths that are git ignored when indexIgnoredPaths is true', async () => {
1627+
atom.config.set('fuzzy-finder.indexIgnoredPaths', true)
1628+
await projectView.toggle()
1629+
1630+
await waitForPathsToDisplay(projectView)
1631+
1632+
expect(projectView.paths.length).toBe(6)
1633+
expect(projectView.ignoredPaths.length).toBe(1)
1634+
16151635
expect(Array.from(projectView.element.querySelectorAll('li')).find(a => a.textContent.includes('ignored.txt'))).not.toBeDefined()
16161636
})
16171637
})

packages/fuzzy-finder/spec/project-view-spec.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ describe('ProjectView', () => {
2020
})
2121

2222
it('includes remote editors when teletype is enabled', async () => {
23-
const projectView = new ProjectView([])
23+
const projectView = new ProjectView([], [])
2424

2525
const projectPath = fs.realpathSync(temp.mkdirSync())
2626
const file1Path = path.join(projectPath, 'a')
@@ -49,7 +49,7 @@ describe('ProjectView', () => {
4949
})
5050

5151
it('shows remote editors even when there is no open project', async () => {
52-
const projectView = new ProjectView([])
52+
const projectView = new ProjectView([], [])
5353

5454
atom.project.setPaths([])
5555
projectView.setTeletypeService({
@@ -69,7 +69,7 @@ describe('ProjectView', () => {
6969
})
7070

7171
it('gracefully defaults to empty list if teletype is unable to provide remote editors', async () => {
72-
const projectView = new ProjectView([])
72+
const projectView = new ProjectView([], [])
7373

7474
atom.project.setPaths([])
7575
projectView.setTeletypeService({

0 commit comments

Comments
 (0)