-
Notifications
You must be signed in to change notification settings - Fork 2.7k
/
Copy pathcache.js
147 lines (125 loc) · 4.68 KB
/
cache.js
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* @flow */
import type {Reporter} from '../../reporters/index.js';
import type Config from '../../config.js';
import buildSubCommands from './_build-sub-commands.js';
import * as fs from '../../util/fs.js';
const invariant = require('invariant');
const path = require('path');
const micromatch = require('micromatch');
export function hasWrapper(flags: Object, args: Array<string>): boolean {
return args[0] !== 'dir';
}
export async function getCachedPackagesDirs(config: Config, currentPath: string): Object {
const results = [];
const stat = await fs.lstat(currentPath);
if (!stat.isDirectory()) {
return results;
}
const folders = await fs.readdir(currentPath);
for (const folder of folders) {
if (folder[0] === '.') {
continue;
}
const packageParentPath = path.join(currentPath, folder, 'node_modules');
const candidates = await fs.readdir(packageParentPath);
invariant(
candidates.length === 1,
`There should only be one folder in a package cache (got ${candidates.join(',')} in ${packageParentPath})`,
);
for (const candidate of candidates) {
const candidatePath = path.join(packageParentPath, candidate);
if (candidate.charAt(0) === '@') {
const subCandidates = await fs.readdir(candidatePath);
invariant(
subCandidates.length === 1,
`There should only be one folder in a package cache (got ${subCandidates.join(',')} in ${candidatePath})`,
);
for (const subCandidate of subCandidates) {
const subCandidatePath = path.join(candidatePath, subCandidate);
results.push(subCandidatePath);
}
} else {
results.push(candidatePath);
}
}
}
return results;
}
function _getMetadataWithPath(getMetadataFn: Function, paths: Array<String>): Promise<Array<Object>> {
return Promise.all(
paths.map(path =>
getMetadataFn(path)
.then(r => {
r._path = path;
return r;
})
.catch(error => undefined),
),
);
}
async function getCachedPackages(config): Object {
const paths = await getCachedPackagesDirs(config, config.cacheFolder);
return _getMetadataWithPath(config.readPackageMetadata.bind(config), paths).then(packages =>
packages.filter(p => !!p),
);
}
async function list(config: Config, reporter: Reporter, flags: Object, args: Array<string>): Promise<void> {
const filterOut = ({registry, package: manifest, remote} = {}) => {
if (flags.pattern && !micromatch.contains(manifest.name, flags.pattern)) {
return false;
}
return true;
};
const forReport = ({registry, package: manifest, remote} = {}) => [
manifest.name,
manifest.version,
registry,
(remote && remote.resolved) || '',
];
const packages = await getCachedPackages(config);
const body = packages.filter(filterOut).map(forReport);
reporter.table(['Name', 'Version', 'Registry', 'Resolved'], body);
}
async function clean(config: Config, reporter: Reporter, flags: Object, args: Array<string>): Promise<void> {
if (config.cacheFolder) {
const activity = reporter.activity();
if (args.length > 0) {
// Clear named packages from cache
const packages = await getCachedPackages(config);
const shouldDelete = ({registry, package: manifest, remote} = {}) => args.indexOf(manifest.name) !== -1;
const packagesToDelete = packages.filter(shouldDelete);
for (const manifest of packagesToDelete) {
let relativePath = path.relative(config.cacheFolder, manifest._path);
while (relativePath && relativePath !== '.') {
await fs.unlink(path.resolve(config.cacheFolder, relativePath));
relativePath = path.dirname(relativePath);
}
}
activity.end();
reporter.success(reporter.lang('clearedPackageFromCache', args[0]));
} else {
// Clear all cache
await fs.unlink(config._cacheRootFolder);
await fs.mkdirp(config.cacheFolder);
activity.end();
reporter.success(reporter.lang('clearedCache'));
}
}
}
const {run, setFlags: _setFlags, examples} = buildSubCommands('cache', {
async ls(config: Config, reporter: Reporter, flags: Object, args: Array<string>): Promise<void> {
reporter.warn(`\`yarn cache ls\` is deprecated. Please use \`yarn cache list\`.`);
await list(config, reporter, flags, args);
},
list,
clean,
dir(config: Config, reporter: Reporter) {
reporter.log(config.cacheFolder, {force: true});
},
});
export {run, examples};
export function setFlags(commander: Object) {
_setFlags(commander);
commander.description('Yarn cache list will print out every cached package.');
commander.option('--pattern [pattern]', 'filter cached packages by pattern');
}