Skip to content

Commit

Permalink
Merge pull request #492 from rbuckton/detectYarn
Browse files Browse the repository at this point in the history
Adds detection for yarn, and '--no-yarn' to suppress detection
  • Loading branch information
joaomoreno authored Oct 1, 2020
2 parents 32ff623 + 6987ca5 commit 4b02d71
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 18 deletions.
9 changes: 6 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ module.exports = function (argv: string[]): void {
program
.command('ls')
.description('Lists all the files that will be published')
.option('--yarn', 'Use yarn instead of npm')
.option('--yarn', 'Use yarn instead of npm (default inferred from presense of yarn.lock or .yarnrc)')
.option('--no-yarn', 'Use npm instead of yarn (default inferred from lack of yarn.lock or .yarnrc)')
.option(
'--packagedDependencies <path>',
'Select packages that should be published only (includes dependencies)',
Expand All @@ -83,7 +84,8 @@ module.exports = function (argv: string[]): void {
)
.option('--baseContentUrl [url]', 'Prepend all relative links in README.md with this url.')
.option('--baseImagesUrl [url]', 'Prepend all relative image links in README.md with this url.')
.option('--yarn', 'Use yarn instead of npm')
.option('--yarn', 'Use yarn instead of npm (default inferred from presense of yarn.lock or .yarnrc)')
.option('--no-yarn', 'Use npm instead of yarn (default inferred from lack of yarn.lock or .yarnrc)')
.option('--ignoreFile [path]', 'Indicate alternative .vscodeignore')
.option('--noGitHubIssueLinking', 'Prevent automatic expansion of GitHub-style issue syntax into links')
.option(
Expand Down Expand Up @@ -117,7 +119,8 @@ module.exports = function (argv: string[]): void {
)
.option('--baseContentUrl [url]', 'Prepend all relative links in README.md with this url.')
.option('--baseImagesUrl [url]', 'Prepend all relative image links in README.md with this url.')
.option('--yarn', 'Use yarn instead of npm while packing extension files')
.option('--yarn', 'Use yarn instead of npm (default inferred from presense of yarn.lock or .yarnrc)')
.option('--no-yarn', 'Use npm instead of yarn (default inferred from lack of yarn.lock or .yarnrc)')
.option('--noVerify')
.option('--ignoreFile [path]', 'Indicate alternative .vscodeignore')
.option(
Expand Down
34 changes: 30 additions & 4 deletions src/npm.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import * as path from 'path';
import * as fs from 'fs';
import * as denodeify from 'denodeify';
import * as cp from 'child_process';
import * as parseSemver from 'parse-semver';
import * as _ from 'lodash';
import { CancellationToken } from './util';
import { CancellationToken, log } from './util';

const stat = denodeify(fs.stat);
const exists = (file: string) =>
stat(file).then(
_ => true,
_ => false
);

interface IOptions {
cwd?: string;
Expand Down Expand Up @@ -181,7 +189,7 @@ async function getYarnProductionDependencies(cwd: string, packagedDependencies?:
async function getYarnDependencies(cwd: string, packagedDependencies?: string[]): Promise<string[]> {
const result: string[] = [cwd];

if (await new Promise(c => fs.exists(path.join(cwd, 'yarn.lock'), c))) {
if (await exists(path.join(cwd, 'yarn.lock'))) {
const deps = await getYarnProductionDependencies(cwd, packagedDependencies);
const flatten = (dep: YarnDependency) => {
result.push(dep.path);
Expand All @@ -193,8 +201,26 @@ async function getYarnDependencies(cwd: string, packagedDependencies?: string[])
return _.uniq(result);
}

export function getDependencies(cwd: string, useYarn = false, packagedDependencies?: string[]): Promise<string[]> {
return useYarn ? getYarnDependencies(cwd, packagedDependencies) : getNpmDependencies(cwd);
export async function detectYarn(cwd: string) {
for (const file of ['yarn.lock', '.yarnrc']) {
if (await exists(path.join(cwd, file))) {
log.info(
`Detected presense of ${file}. Using 'yarn' instead of 'npm' (to override this pass '--no-yarn' on the command line).`
);
return true;
}
}
return false;
}

export async function getDependencies(
cwd: string,
useYarn?: boolean,
packagedDependencies?: string[]
): Promise<string[]> {
return (useYarn !== undefined ? useYarn : await detectYarn(cwd))
? await getYarnDependencies(cwd, packagedDependencies)
: await getNpmDependencies(cwd);
}

export function getLatestVersion(name: string, cancellationToken?: CancellationToken): Promise<string> {
Expand Down
26 changes: 15 additions & 11 deletions src/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
validateEngineCompatibility,
validateVSCodeTypesCompatibility,
} from './validation';
import { getDependencies } from './npm';
import { detectYarn, getDependencies } from './npm';
import { IExtensionsReport } from './publicgalleryapi';

const readFile = denodeify<string, string, string>(fs.readFile);
Expand Down Expand Up @@ -984,7 +984,7 @@ const defaultIgnore = [
'**/.vscode-test/**',
];

function collectAllFiles(cwd: string, useYarn = false, dependencyEntryPoints?: string[]): Promise<string[]> {
function collectAllFiles(cwd: string, useYarn?: boolean, dependencyEntryPoints?: string[]): Promise<string[]> {
return getDependencies(cwd, useYarn, dependencyEntryPoints).then(deps => {
const promises: Promise<string[]>[] = deps.map(dep => {
return glob('**', { cwd: dep, nodir: true, dot: true, ignore: 'node_modules/**' }).then(files =>
Expand All @@ -998,7 +998,7 @@ function collectAllFiles(cwd: string, useYarn = false, dependencyEntryPoints?: s

function collectFiles(
cwd: string,
useYarn = false,
useYarn?: boolean,
dependencyEntryPoints?: string[],
ignoreFile?: string
): Promise<string[]> {
Expand Down Expand Up @@ -1084,12 +1084,11 @@ export function createDefaultProcessors(manifest: Manifest, options: IPackageOpt

export function collect(manifest: Manifest, options: IPackageOptions = {}): Promise<IFile[]> {
const cwd = options.cwd || process.cwd();
const useYarn = options.useYarn || false;
const packagedDependencies = options.dependencyEntryPoints || undefined;
const ignoreFile = options.ignoreFile || undefined;
const processors = createDefaultProcessors(manifest, options);

return collectFiles(cwd, useYarn, packagedDependencies, ignoreFile).then(fileNames => {
return collectFiles(cwd, options.useYarn, packagedDependencies, ignoreFile).then(fileNames => {
const files = fileNames.map(f => ({ path: `extension/${f}`, localPath: path.join(cwd, f) }));

return processFiles(processors, files);
Expand Down Expand Up @@ -1124,14 +1123,18 @@ function getDefaultPackageName(manifest: Manifest): string {
return `${manifest.name}-${manifest.version}.vsix`;
}

async function prepublish(cwd: string, manifest: Manifest, useYarn: boolean = false): Promise<void> {
async function prepublish(cwd: string, manifest: Manifest, useYarn?: boolean): Promise<void> {
if (!manifest.scripts || !manifest.scripts['vscode:prepublish']) {
return;
}

if (useYarn === undefined) {
useYarn = await detectYarn(cwd);
}

console.log(`Executing prepublish script '${useYarn ? 'yarn' : 'npm'} run vscode:prepublish'...`);

await new Promise((c, e) => {
await new Promise<void>((c, e) => {
const tool = useYarn ? 'yarn' : 'npm';
const child = cp.spawn(tool, ['run', 'vscode:prepublish'], { cwd, shell: true, stdio: 'inherit' });
child.on('exit', code => (code === 0 ? c() : e(`${tool} failed with exit code ${code}`)));
Expand Down Expand Up @@ -1200,21 +1203,22 @@ export async function packageCommand(options: IPackageOptions = {}): Promise<any
/**
* Lists the files included in the extension's package. Does not run prepublish.
*/
export function listFiles(
export async function listFiles(
cwd = process.cwd(),
useYarn = false,
useYarn?: boolean,
packagedDependencies?: string[],
ignoreFile?: string
): Promise<string[]> {
return readManifest(cwd).then(() => collectFiles(cwd, useYarn, packagedDependencies, ignoreFile));
await readManifest(cwd);
return await collectFiles(cwd, useYarn, packagedDependencies, ignoreFile);
}

/**
* Lists the files included in the extension's package. Runs prepublish.
*/
export function ls(
cwd = process.cwd(),
useYarn = false,
useYarn?: boolean,
packagedDependencies?: string[],
ignoreFile?: string
): Promise<void> {
Expand Down
17 changes: 17 additions & 0 deletions src/test/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,23 @@ describe('collect', function () {
});
});

it('should detect yarn', () => {
const cwd = fixture('packagedDependencies');

return readManifest(cwd)
.then(manifest => collect(manifest, { cwd, dependencyEntryPoints: ['isexe'] }))
.then(files => {
let seenWhich: boolean;
let seenIsexe: boolean;
files.forEach(file => {
seenWhich = file.path.indexOf('/node_modules/which/') >= 0;
seenIsexe = file.path.indexOf('/node_modules/isexe/') >= 0;
});
assert.equal(seenWhich, false);
assert.equal(seenIsexe, true);
});
});

it('should include all node_modules when dependencyEntryPoints is not defined', () => {
const cwd = fixture('packagedDependencies');

Expand Down

0 comments on commit 4b02d71

Please sign in to comment.