diff --git a/lib/citgm.js b/lib/citgm.js index d45e4723..33a22806 100644 --- a/lib/citgm.js +++ b/lib/citgm.js @@ -1,7 +1,5 @@ -import { createHash } from 'crypto'; import { EventEmitter } from 'events'; -import npa from 'npm-package-arg'; import BufferList from 'bl'; import which from 'which'; @@ -15,6 +13,7 @@ import { } from './package-manager/index.js'; import * as tempDirectory from './temp-directory.js'; import { unpack } from './unpack.js'; +import { parsePackageArg } from './utils.js'; export const windows = process.platform === 'win32'; @@ -53,18 +52,6 @@ function init(context) { ); } -function sha1(mod) { - const shasum = createHash('sha1'); - shasum.update(mod); - return shasum.digest('hex'); -} - -function extractDetail(mod) { - const detail = npa(mod); // Will throw if mod is invalid - detail.name = detail.name || `noname-${sha1(mod)}`; - return detail; -} - /** * The Tester will emit specific events once it is run: * - end = emitted when the test is complete @@ -75,7 +62,7 @@ function extractDetail(mod) { export class Tester extends EventEmitter { constructor(mod, options) { super(); - this.module = extractDetail(mod); + this.module = parsePackageArg(mod); this.options = options; this.testOutput = new BufferList(); this.testError = new BufferList(); diff --git a/lib/utils.js b/lib/utils.js index 4d28d20b..c1805623 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,5 +1,8 @@ +import { createHash } from 'node:crypto'; import fs from 'node:fs/promises'; +import npa from 'npm-package-arg'; + /** * Remove directory recursively with retries for Windows. * @param path @@ -12,3 +15,18 @@ export async function removeDirectory(path) { retryDelay: 50 }); } + +function sha1(mod) { + const shasum = createHash('sha1'); + shasum.update(mod); + return shasum.digest('hex'); +} + +export function parsePackageArg(mod) { + const detail = npa(mod); // Will throw if mod is invalid + detail.name = detail.name || `noname-${sha1(mod)}`; + if (detail.fetchSpec === '*') { + detail.fetchSpec = 'latest'; + } + return detail; +} diff --git a/test/test-lookup.js b/test/test-lookup.js index 4c821edb..aff7fb2f 100644 --- a/test/test-lookup.js +++ b/test/test-lookup.js @@ -4,9 +4,35 @@ import { readFileSync } from 'fs'; import tap from 'tap'; import { getLookupTable, makeUrl, lookup } from '../lib/lookup.js'; +import { parsePackageArg } from '../lib/utils.js'; const { test } = tap; +function createFakeMeta(config) { + const { name, version = '1.0.0', repository, gitHead } = config; + if (!name) { + throw new Error('name is required'); + } + const now = new Date().toISOString(); + return { + _id: `${name}@${version}`, + name, + description: 'Some module', + 'dist-tags': { + latest: version + }, + versions: [version], + time: { + created: now, + modified: now, + [version]: now + }, + repository, + version, + gitHead + }; +} + test('lookup: makeUrl', (t) => { t.plan(5); const repo = 'https://github.com/nodejs/citgm'; @@ -103,19 +129,18 @@ test('lookup: module not in table', (t) => { t.plan(1); const context = { lookup: null, - module: { - name: 'omg-i-pass', - raw: null - }, - meta: {}, + module: parsePackageArg('omg-i-pass'), + meta: createFakeMeta({ name: 'omg-i-pass' }), options: {}, emit: function () {} }; + const rawBefore = context.module.raw; lookup(context); - t.notOk( + t.equal( context.module.raw, - 'raw should remain falsey if module is not in lookup' + rawBefore, + 'raw should remain unchanged if module is not in lookup' ); t.end(); }); @@ -124,16 +149,14 @@ test('lookup: module not in table with gitHead', (t) => { t.plan(1); const context = { lookup: null, - module: { + module: parsePackageArg('omg-i-pass'), + meta: createFakeMeta({ name: 'omg-i-pass', - raw: null - }, - meta: { repository: { url: 'https://github.com/nodejs/omg-i-pass' }, gitHead: 'abc123' - }, + }), options: {}, emit: function () {} }; @@ -151,15 +174,13 @@ test('lookup: module in table', (t) => { t.plan(1); const context = { lookup: null, - module: { + module: parsePackageArg('lodash'), + meta: createFakeMeta({ name: 'lodash', - raw: null - }, - meta: { repository: { url: 'https://github.com/lodash/lodash' } - }, + }), options: {}, emit: function () {} }; @@ -167,7 +188,7 @@ test('lookup: module in table', (t) => { lookup(context); t.equal( context.module.raw, - 'https://github.com/lodash/lodash/archive/HEAD.tar.gz', + 'https://github.com/lodash/lodash/archive/1.0.0.tar.gz', 'raw should be truthy if the module was in the list' ); t.end(); @@ -177,16 +198,14 @@ test('lookup: module in table with gitHead', (t) => { t.plan(1); const context = { lookup: null, - module: { + module: parsePackageArg('lodash'), + meta: createFakeMeta({ name: 'lodash', - raw: null - }, - meta: { repository: { url: 'https://github.com/lodash/lodash' }, gitHead: 'abc123' - }, + }), options: {}, emit: function () {} }; @@ -203,16 +222,13 @@ test('lookup: module in table with gitHead', (t) => { test('lookup: module in table with scripts', (t) => { t.plan(1); const context = { - module: { + module: parsePackageArg('omg-i-pass-with-scripts'), + meta: createFakeMeta({ name: 'omg-i-pass-with-scripts', - raw: null - }, - meta: { repository: { url: 'git+https://github.com/nodejs/citgm' - }, - version: '1.0.0' - }, + } + }), options: { lookup: 'test/fixtures/custom-lookup-scripts.json' }, @@ -232,17 +248,14 @@ test('lookup: module in table with useGitClone', (t) => { t.plan(2); const context = { lookup: null, - module: { - fetchSpec: 'latest', + module: parsePackageArg('lodash'), + meta: createFakeMeta({ name: 'lodash', - raw: null - }, - meta: { - 'dist-tags': { latest: '1.2.3' }, + version: '1.2.3', repository: { url: 'https://github.com/lodash/lodash' } - }, + }), options: { lookup: 'test/fixtures/custom-lookup-useGitClone.json' }, @@ -278,14 +291,11 @@ test('lookup: no table', (t) => { test('lookup: replace with no repo', (t) => { t.plan(1); const context = { - module: { + module: parsePackageArg('omg-i-pass'), + meta: createFakeMeta({ name: 'omg-i-pass', - raw: null - }, - meta: { - repository: undefined, version: '1.2.3' - }, + }), options: { lookup: 'test/fixtures/custom-lookup-no-repo.json' }, @@ -304,15 +314,14 @@ test('lookup: not found in lookup.json with --sha', (t) => { t.plan(1); const context = { lookup: null, - module: { - name: 'test' - }, - meta: { - gitHead: 'metaGitHead', + module: parsePackageArg('test'), + meta: createFakeMeta({ + name: 'test', repository: { url: 'https://github.com/test-org/test-repo' - } - }, + }, + gitHead: 'metaGitHead' + }), options: { sha: 'customsha' }, @@ -331,15 +340,13 @@ test('lookup: --fail-flaky', (t) => { t.plan(1); const context = { lookup: null, - module: { + module: parsePackageArg('lodash'), + meta: createFakeMeta({ name: 'lodash', - raw: null - }, - meta: { repository: { url: 'https://github.com/lodash/lodash' } - }, + }), options: { failFlaky: true }, @@ -372,14 +379,12 @@ test('lookup: ensure lookup works', (t) => { test('lookup: lookup with install', (t) => { t.plan(1); const context = { - module: { + module: parsePackageArg('omg-i-pass-with-install-param'), + meta: createFakeMeta({ name: 'omg-i-pass-with-install-param', - raw: null - }, - meta: { - repository: '/dev/null', - version: '0.1.1' - }, + version: '0.1.1', + repository: '/dev/null' + }), options: { lookup: 'test/fixtures/custom-lookup-install.json' },