Skip to content

Commit d626de1

Browse files
authored
feat: support glob patterns (#151)
We use a weird mix of multiple glob patterns and ignores which means we parse the available files in an inefficient way. Instead just use a single glob pattern which can do everything we need. Fixes ipfs/js-ipfs#2885 BREAKING CHANGE: the globSource call signature has changed and no longer supports the recursive or ignore options
1 parent 8279445 commit d626de1

File tree

5 files changed

+159
-202
lines changed

5 files changed

+159
-202
lines changed

.github/workflows/main.yml

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ jobs:
7171
test-react-native-android:
7272
runs-on: macos-latest
7373
needs: check
74+
continue-on-error: true
7475
steps:
7576
- uses: actions/checkout@v2
7677
- run: npm install

src/files/glob-source.js

+22-94
Original file line numberDiff line numberDiff line change
@@ -7,131 +7,59 @@ const Path = require('path')
77
const errCode = require('err-code')
88

99
/**
10-
* Create an async iterator that yields paths that match requested file paths.
10+
* Create an async iterator that yields paths that match requested glob pattern
1111
*
12-
* @param {Iterable<string> | AsyncIterable<string> | string} paths - File system path(s) to glob from
12+
* @param {string} cwd - The directory to start matching the pattern in
13+
* @param {string} pattern - Glob pattern to match
1314
* @param {Object} [options] - Optional options
14-
* @param {boolean} [options.recursive] - Recursively glob all paths in directories
1515
* @param {boolean} [options.hidden] - Include .dot files in matched paths
16-
* @param {Array<string>} [options.ignore] - Glob paths to ignore
1716
* @param {boolean} [options.followSymlinks] - follow symlinks
1817
* @param {boolean} [options.preserveMode] - preserve mode
1918
* @param {boolean} [options.preserveMtime] - preserve mtime
2019
* @param {number} [options.mode] - mode to use - if preserveMode is true this will be ignored
2120
* @param {import('ipfs-unixfs').MtimeLike} [options.mtime] - mtime to use - if preserveMtime is true this will be ignored
2221
* @yields {Object} File objects in the form `{ path: String, content: AsyncIterator<Buffer> }`
2322
*/
24-
module.exports = async function * globSource (paths, options) {
23+
module.exports = async function * globSource (cwd, pattern, options) {
2524
options = options || {}
2625

27-
if (typeof paths === 'string') {
28-
paths = [paths]
26+
if (typeof pattern !== 'string') {
27+
throw errCode(
28+
new Error('Pattern must be a string'),
29+
'ERR_INVALID_PATH',
30+
{ pattern }
31+
)
2932
}
3033

31-
const globSourceOptions = {
32-
recursive: options.recursive,
33-
glob: {
34-
dot: Boolean(options.hidden),
35-
ignore: Array.isArray(options.ignore) ? options.ignore : [],
36-
follow: options.followSymlinks != null ? options.followSymlinks : true
37-
}
34+
if (!Path.isAbsolute(cwd)) {
35+
cwd = Path.resolve(process.cwd(), cwd)
3836
}
3937

40-
// Check the input paths comply with options.recursive and convert to glob sources
41-
for await (const path of paths) {
42-
if (typeof path !== 'string') {
43-
throw errCode(
44-
new Error('Path must be a string'),
45-
'ERR_INVALID_PATH',
46-
{ path }
47-
)
48-
}
38+
const globOptions = Object.assign({}, {
39+
nodir: false,
40+
realpath: false,
41+
absolute: true,
42+
dot: Boolean(options.hidden),
43+
follow: options.followSymlinks != null ? options.followSymlinks : true
44+
})
4945

50-
const absolutePath = Path.resolve(process.cwd(), path)
51-
const stat = await fsp.stat(absolutePath)
52-
const prefix = Path.dirname(absolutePath)
46+
for await (const p of glob(cwd, pattern, globOptions)) {
47+
const stat = await fsp.stat(p)
5348

5449
let mode = options.mode
5550

5651
if (options.preserveMode) {
57-
// @ts-ignore
5852
mode = stat.mode
5953
}
6054

6155
let mtime = options.mtime
6256

6357
if (options.preserveMtime) {
64-
// @ts-ignore
6558
mtime = stat.mtime
6659
}
6760

68-
if (stat.isDirectory()) {
69-
yield {
70-
path: `/${Path.basename(path)}`,
71-
mode,
72-
mtime
73-
}
74-
}
75-
76-
yield * toGlobSource({
77-
path,
78-
type: stat.isDirectory() ? 'dir' : 'file',
79-
prefix,
80-
mode,
81-
mtime,
82-
preserveMode: options.preserveMode,
83-
preserveMtime: options.preserveMtime
84-
}, globSourceOptions)
85-
}
86-
}
87-
88-
// @ts-ignore
89-
async function * toGlobSource ({ path, type, prefix, mode, mtime, preserveMode, preserveMtime }, options) {
90-
options = options || {}
91-
92-
const baseName = Path.basename(path)
93-
94-
if (type === 'file') {
95-
yield {
96-
path: `/${baseName.replace(prefix, '')}`,
97-
content: fs.createReadStream(Path.isAbsolute(path) ? path : Path.join(process.cwd(), path)),
98-
mode,
99-
mtime
100-
}
101-
102-
return
103-
}
104-
105-
if (type === 'dir' && !options.recursive) {
106-
throw errCode(
107-
new Error(`'${path}' is a directory and recursive option not set`),
108-
'ERR_DIR_NON_RECURSIVE',
109-
{ path }
110-
)
111-
}
112-
113-
const globOptions = Object.assign({}, options.glob, {
114-
cwd: path,
115-
nodir: false,
116-
realpath: false,
117-
absolute: true
118-
})
119-
120-
for await (const p of glob(path, '**/*', globOptions)) {
121-
const stat = await fsp.stat(p)
122-
123-
if (preserveMode || preserveMtime) {
124-
if (preserveMode) {
125-
mode = stat.mode
126-
}
127-
128-
if (preserveMtime) {
129-
mtime = stat.mtime
130-
}
131-
}
132-
13361
yield {
134-
path: toPosix(p.replace(prefix, '')),
62+
path: toPosix(p.replace(cwd, '')),
13563
content: stat.isFile() ? fs.createReadStream(p) : undefined,
13664
mode,
13765
mtime

0 commit comments

Comments
 (0)