-
Notifications
You must be signed in to change notification settings - Fork 251
/
crawlfs.ts
55 lines (50 loc) · 1.63 KB
/
crawlfs.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import { promisify } from 'util';
import { glob as _glob, IOptions } from 'glob';
import fs from './wrapped-fs';
import { Stats } from 'fs';
const glob = promisify(_glob);
export type CrawledFileType = {
type: 'file' | 'directory' | 'link';
stat: Stats;
transformed?: {
path: string;
stat: Stats;
};
};
export async function determineFileType(filename: string): Promise<CrawledFileType | null> {
const stat = await fs.lstat(filename);
if (stat.isFile()) {
return { type: 'file', stat };
} else if (stat.isDirectory()) {
return { type: 'directory', stat };
} else if (stat.isSymbolicLink()) {
return { type: 'link', stat };
}
return null;
}
export async function crawl(dir: string, options: IOptions) {
const metadata: Record<string, CrawledFileType> = {};
const crawled = await glob(dir, options);
const results = await Promise.all(
crawled.map(async (filename) => <const>[filename, await determineFileType(filename)]),
);
const links: string[] = [];
const filenames = results
.map(([filename, type]) => {
if (type) {
metadata[filename] = type;
if (type.type === 'link') links.push(filename);
}
return filename;
})
.filter((filename) => {
// Newer glob can return files inside symlinked directories, to avoid
// those appearing in archives we need to manually exclude theme here
const exactLinkIndex = links.findIndex((link) => filename === link);
return links.every((link, index) => {
if (index === exactLinkIndex) return true;
return !filename.startsWith(link);
});
});
return <const>[filenames, metadata];
}