expose yarn in listFiles api

This commit is contained in:
Joao Moreno 2017-11-14 18:09:37 +01:00
parent 0c6e28cd8c
commit d7734cd10b
3 changed files with 89 additions and 8 deletions

View file

@ -54,12 +54,25 @@ export interface IPublishOptions {
baseImagesUrl?: string;
}
/**
* The supported list of package managers.
*/
export enum PackageManager {
Npm,
Yarn
}
export interface IListFilesOptions {
/**
* The working directory of the extension. Defaults to `process.cwd()`.
*/
cwd?: string;
/**
* The package manager to use. Defaults to `PackageManager.Npm`.
*/
packageManager?: PackageManager;
}
export interface IPublishVSIXOptions {
@ -100,7 +113,7 @@ export function publish(options: IPublishOptions = {}): Promise<any> {
* Lists the files included in the extension's package.
*/
export function listFiles(options: IListFilesOptions = {}): Promise<string[]> {
return _listFiles(options.cwd);
return _listFiles(options.cwd, options.packageManager === PackageManager.Yarn);
}
/**

View file

@ -1,5 +1,7 @@
import * as path from 'path';
import * as cp from 'child_process';
import * as semver from 'semver';
import * as _ from 'lodash';
import { CancellationToken } from './util';
interface IOptions {
@ -49,7 +51,7 @@ function checkNPM(cancellationToken?: CancellationToken): Promise<void> {
});
}
export function getDependencies(cwd: string): Promise<string[]> {
function getNpmDependencies(cwd: string): Promise<string[]> {
return checkNPM()
.then(() => exec('npm list --production --parseable --depth=99999', { cwd }))
.then(({ stdout }) => stdout
@ -57,6 +59,72 @@ export function getDependencies(cwd: string): Promise<string[]> {
.filter(dir => path.isAbsolute(dir)));
}
interface YarnTreeNode {
name: string;
children: YarnTreeNode[];
}
export interface YarnDependency {
name: string;
version: string;
path: string;
children: YarnDependency[];
}
function asYarnDependency(prefix: string, tree: YarnTreeNode): YarnDependency | null {
if (/@[\^~]/.test(tree.name)) {
return null;
}
const version = tree.name.replace(/^[^@]+@/, '');
if (!semver.valid(version)) {
return null;
}
const name = tree.name.replace(/@[^@]+$/, '');
const dependencyPath = path.join(prefix, name);
const children: YarnDependency[] = [];
for (const child of (tree.children || [])) {
const dep = asYarnDependency(path.join(prefix, name, 'node_modules'), child);
if (dep) {
children.push(dep);
}
}
return { name, version, path: dependencyPath, children };
}
async function getYarnProductionDependencies(cwd: string): Promise<YarnDependency[]> {
const raw = await new Promise<string>((c, e) => cp.exec('yarn list --json', { cwd, encoding: 'utf8', env: { ...process.env, NODE_ENV: 'production' } }, (err, stdout) => err ? e(err) : c(stdout)));
const match = /^{"type":"tree".*$/m.exec(raw);
if (!match || match.length !== 1) {
throw new Error('Could not parse result of `yarn list --json`');
}
const trees = JSON.parse(match[0]).data.trees as YarnTreeNode[];
return trees
.map(tree => asYarnDependency(path.join(cwd, 'node_modules'), tree))
.filter(dep => !!dep);
}
async function getYarnDependencies(cwd: string): Promise<string[]> {
const deps = await getYarnProductionDependencies(cwd);
const result: string[] = [cwd];
const flatten = (dep: YarnDependency) => { result.push(dep.path); dep.children.forEach(flatten); };
deps.forEach(flatten);
return _.uniq(result);
}
export function getDependencies(cwd: string, useYarn = false): Promise<string[]> {
return useYarn ? getYarnDependencies(cwd) : getNpmDependencies(cwd);
}
export function getLatestVersion(name: string, cancellationToken?: CancellationToken): Promise<string> {
return checkNPM(cancellationToken)
.then(() => exec(`npm show ${name} version`, {}, cancellationToken))

View file

@ -612,8 +612,8 @@ const defaultIgnore = [
'**/*.vsixmanifest'
];
function collectAllFiles(cwd: string): Promise<string[]> {
return getDependencies(cwd).then(deps => {
function collectAllFiles(cwd: string, useYarn = false): Promise<string[]> {
return getDependencies(cwd, useYarn).then(deps => {
const promises = deps.map(dep => {
return glob('**', { cwd: dep, nodir: true, dot: true, ignore: 'node_modules/**' })
.then(files => files
@ -625,8 +625,8 @@ function collectAllFiles(cwd: string): Promise<string[]> {
});
}
function collectFiles(cwd: string): Promise<string[]> {
return collectAllFiles(cwd).then(files => {
function collectFiles(cwd: string, useYarn = false): Promise<string[]> {
return collectAllFiles(cwd, useYarn).then(files => {
files = files.filter(f => !/\r$/m.test(f));
return readFile(path.join(cwd, '.vscodeignore'), 'utf8')
@ -736,9 +736,9 @@ export function packageCommand(options: IPackageOptions = {}): Promise<any> {
/**
* Lists the files included in the extension's package. Does not run prepublish.
*/
export function listFiles(cwd = process.cwd()): Promise<string[]> {
export function listFiles(cwd = process.cwd(), useYarn = false): Promise<string[]> {
return readManifest(cwd)
.then(manifest => collectFiles(cwd));
.then(manifest => collectFiles(cwd, useYarn));
}
/**