-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[dev/build] scan node_modules rather than lots of deleteAll() calls
- Loading branch information
spalger
committed
Oct 26, 2018
1 parent
a0543b1
commit 232fd17
Showing
7 changed files
with
273 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,3 +31,4 @@ export { | |
untar, | ||
deleteAll, | ||
} from './fs'; | ||
export { scanDelete } from './scan_delete'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import { readdirSync } from 'fs'; | ||
import { relative, resolve } from 'path'; | ||
|
||
import del from 'del'; | ||
|
||
// @ts-ignore | ||
import { mkdirp, write } from './fs'; | ||
import { scanDelete } from './scan_delete'; | ||
|
||
const TMP = resolve(__dirname, '__tests__/__tmp__'); | ||
|
||
// clean and recreate TMP directory | ||
beforeEach(async () => { | ||
await del(TMP); | ||
await mkdirp(resolve(TMP, 'foo/bar/baz')); | ||
await mkdirp(resolve(TMP, 'foo/bar/box')); | ||
await mkdirp(resolve(TMP, 'a/b/c/d/e')); | ||
await write(resolve(TMP, 'a/bar'), 'foo'); | ||
}); | ||
|
||
// cleanup TMP directory | ||
afterAll(async () => { | ||
await del(TMP); | ||
}); | ||
|
||
it('requires an absolute directory', async () => { | ||
await expect( | ||
scanDelete({ | ||
directory: relative(process.cwd(), TMP), | ||
regularExpressions: [], | ||
}) | ||
).rejects.toMatchInlineSnapshot( | ||
`[TypeError: Please use absolute paths to keep things explicit. You probably want to use \`build.resolvePath()\` or \`config.resolveFromRepo()\`.]` | ||
); | ||
}); | ||
|
||
it('deletes files/folders matching regular expression', async () => { | ||
await scanDelete({ | ||
directory: TMP, | ||
regularExpressions: [/^.*[\/\\](bar|c)([\/\\]|$)/], | ||
}); | ||
expect(readdirSync(resolve(TMP, 'foo'))).toEqual([]); | ||
expect(readdirSync(resolve(TMP, 'a'))).toEqual(['b']); | ||
expect(readdirSync(resolve(TMP, 'a/b'))).toEqual([]); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import Fs from 'fs'; | ||
|
||
import del from 'del'; | ||
import { join } from 'path'; | ||
import * as Rx from 'rxjs'; | ||
import { count, map, mergeAll, mergeMap } from 'rxjs/operators'; | ||
|
||
// @ts-ignore | ||
import { assertAbsolute } from './fs'; | ||
|
||
const getStat$ = Rx.bindNodeCallback(Fs.stat); | ||
const getReadDir$ = Rx.bindNodeCallback(Fs.readdir); | ||
|
||
interface Options { | ||
directory: string; | ||
regularExpressions: RegExp[]; | ||
concurrency?: 20; | ||
} | ||
|
||
/** | ||
* Scan the files in a directory and delete the directories/files that | ||
* are matched by an array of regular expressions. | ||
* | ||
* @param options.directory the directory to scan, all files including dot files will be checked | ||
* @param options.regularExpressions an array of regular expressions, if any matches the file/directory will be deleted | ||
* @param options.concurrency optional concurrency to run deletes, defaults to 20 | ||
*/ | ||
export async function scanDelete(options: Options) { | ||
const { directory, regularExpressions, concurrency = 20 } = options; | ||
|
||
assertAbsolute(directory); | ||
|
||
// get an observable of absolute paths within a directory | ||
const getChildPath$ = (path: string) => | ||
getReadDir$(path).pipe( | ||
mergeAll(), | ||
map(name => join(path, name)) | ||
); | ||
|
||
// get an observable of all paths to be deleted, by starting with the arg | ||
// and recursively iterating through all children, unless a child matches | ||
// one of the supplied regular expressions | ||
const getPathsToDelete$ = (path: string): Rx.Observable<string> => { | ||
if (regularExpressions.some(re => re.test(path))) { | ||
return Rx.of(path); | ||
} | ||
|
||
return getStat$(path).pipe( | ||
mergeMap(stat => (stat.isDirectory() ? getChildPath$(path) : Rx.EMPTY)), | ||
mergeMap(getPathsToDelete$) | ||
); | ||
}; | ||
|
||
return await Rx.of(directory) | ||
.pipe( | ||
mergeMap(getPathsToDelete$), | ||
mergeMap(async path => await del(path), concurrency), | ||
count() | ||
) | ||
.toPromise(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.