Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds detection for yarn, and '--no-yarn' to suppress detection #492

Merged
merged 4 commits into from
Oct 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ trigger:
steps:
- task: NodeTool@0
inputs:
versionSpec: '8.x'
versionSpec: '10.x'

- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
Expand Down
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