Skip to content
This repository has been archived by the owner on Jan 20, 2022. It is now read-only.

Commit

Permalink
feat: add option to override recorded registry
Browse files Browse the repository at this point in the history
  • Loading branch information
Caleb ツ Everett committed Dec 23, 2021
1 parent 37ad149 commit 151a31f
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 23 deletions.
3 changes: 3 additions & 0 deletions lib/arborist/build-ideal-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const optionalSet = require('../optional-set.js')
const { checkEngine, checkPlatform } = require('npm-install-checks')

const relpath = require('../relpath.js')
const { resolveOptions } = require('../override-resolves')

// note: some of these symbols are shared so we can hit
// them with unit tests and reuse them across mixins
Expand Down Expand Up @@ -311,6 +312,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
? Shrinkwrap.reset({
path: this.path,
lockfileVersion: this.options.lockfileVersion,
resolveOptions: resolveOptions(this.options),
}).then(meta => Object.assign(root, { meta }))
: this.loadVirtual({ root }))

Expand Down Expand Up @@ -354,6 +356,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
const meta = new Shrinkwrap({
path: this.path,
lockfileVersion: this.options.lockfileVersion,
resolveOptions: resolveOptions(this.options),
})
meta.reset()
root.meta = meta
Expand Down
3 changes: 3 additions & 0 deletions lib/arborist/load-actual.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const readdir = promisify(require('readdir-scoped-modules'))
const walkUp = require('walk-up-path')
const ancestorPath = require('common-ancestor-path')
const treeCheck = require('../tree-check.js')
const { resolveOptions } = require('../override-resolves')

const Shrinkwrap = require('../shrinkwrap.js')
const calcDepFlags = require('../calc-dep-flags.js')
Expand Down Expand Up @@ -147,6 +148,7 @@ module.exports = cls => class ActualLoader extends cls {
const meta = await Shrinkwrap.load({
path: this[_actualTree].path,
hiddenLockfile: true,
resolveOptions: resolveOptions(this.options),
})
if (meta.loadedFromDisk) {
this[_actualTree].meta = meta
Expand All @@ -155,6 +157,7 @@ module.exports = cls => class ActualLoader extends cls {
const meta = await Shrinkwrap.load({
path: this[_actualTree].path,
lockfileVersion: this.options.lockfileVersion,
resolveOptions: resolveOptions(this.options),
})
this[_actualTree].meta = meta
return this[_loadActualActually]({ root, ignoreMissing })
Expand Down
2 changes: 2 additions & 0 deletions lib/arborist/load-virtual.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const relpath = require('../relpath.js')
const calcDepFlags = require('../calc-dep-flags.js')
const rpj = require('read-package-json-fast')
const treeCheck = require('../tree-check.js')
const { resolveOptions } = require('../override-resolves')

const loadFromShrinkwrap = Symbol('loadFromShrinkwrap')
const resolveNodes = Symbol('resolveNodes')
Expand Down Expand Up @@ -57,6 +58,7 @@ module.exports = cls => class VirtualLoader extends cls {
const s = await Shrinkwrap.load({
path: this.path,
lockfileVersion: this.options.lockfileVersion,
resolveOptions: resolveOptions(this.options),
})
if (!s.loadedFromDisk && !options.root) {
const er = new Error('loadVirtual requires existing shrinkwrap file')
Expand Down
21 changes: 21 additions & 0 deletions lib/override-resolves.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

function resolveOptions (opts) {
return {
omitLockfileRegistryResolved: opts.omitLockfileRegistryResolved,
registry: opts.registry,
recordResolvedRegistry: opts.recordResolvedRegistry,
}
}

function overrideResolves (resolved, opts) {
if (opts.omitLockfileRegistryResolved) {
return undefined
}
if (opts.registry && opts.recordResolvedRegistry && resolved.startsWith(opts.registry)) {
// TODO handle scoped packages with their own registries.
return opts.recordResolvedRegistry + resolved.slice(opts.registry.length)
}
return resolved
}

module.exports = { overrideResolves, resolveOptions }
24 changes: 13 additions & 11 deletions lib/shrinkwrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ const specFromResolved = resolved => {
const relpath = require('./relpath.js')

const consistentResolve = require('./consistent-resolve.js')
const { overrideResolves } = require('./override-resolves.js')

const maybeReadFile = file => {
return readFile(file, 'utf8').then(d => d, er => {
Expand Down Expand Up @@ -300,8 +301,11 @@ class Shrinkwrap {

const resolved = consistentResolve(node.resolved, node.path, path, true)
// hide resolved from registry dependencies.
if (resolved &&
!(options.omitLockfileRegistryResolved && node.isRegistryDependency)) {
if (!resolved) {
// no-op
} else if (node.isRegistryDependency) {
meta.resolved = overrideResolves(resolved, options)
} else {
meta.resolved = resolved
}

Expand Down Expand Up @@ -333,7 +337,7 @@ class Shrinkwrap {
hiddenLockfile = false,
log = procLog,
lockfileVersion,
omitLockfileRegistryResolved = false,
resolveOptions = {},
} = options

this.lockfileVersion = hiddenLockfile ? 3
Expand All @@ -352,7 +356,7 @@ class Shrinkwrap {
this.yarnLock = null
this.hiddenLockfile = hiddenLockfile
this.loadingError = null
this.resolvedOptions = { omitLockfileRegistryResolved }
this.resolveOptions = resolveOptions
// only load npm-shrinkwrap.json in dep trees, not package-lock
this.shrinkwrapOnly = shrinkwrapOnly
}
Expand Down Expand Up @@ -827,7 +831,7 @@ class Shrinkwrap {
resolved,
integrity,
hasShrinkwrap,
} = Shrinkwrap.metaFromNode(node, this.path, this.resolvedOptions)
} = Shrinkwrap.metaFromNode(node, this.path, this.resolveOptions)
node.resolved = node.resolved || resolved || null
node.integrity = node.integrity || integrity || null
node.hasShrinkwrap = node.hasShrinkwrap || hasShrinkwrap || false
Expand Down Expand Up @@ -886,7 +890,7 @@ class Shrinkwrap {
this.data.packages[loc] = Shrinkwrap.metaFromNode(
node,
this.path,
this.resolvedOptions)
this.resolveOptions)
}

commit () {
Expand All @@ -897,7 +901,7 @@ class Shrinkwrap {
const root = Shrinkwrap.metaFromNode(
this.tree.target,
this.path,
this.resolvedOptions)
this.resolveOptions)
this.data.packages = {}
if (Object.keys(root).length) {
this.data.packages[''] = root
Expand All @@ -911,7 +915,7 @@ class Shrinkwrap {
this.data.packages[loc] = Shrinkwrap.metaFromNode(
node,
this.path,
this.resolvedOptions)
this.resolveOptions)
}
} else if (this[_awaitingUpdate].size > 0) {
for (const loc of this[_awaitingUpdate].keys()) {
Expand Down Expand Up @@ -1012,16 +1016,14 @@ class Shrinkwrap {
// git, file, dir, or remote, then the resolved value is necessary.
if (node.resolved &&
!node.isLink &&
!(node.isRegistryDependency &&
this.resolvedOptions.omitLockfileRegistryResolved) &&
rSpec.type !== 'git' &&
rSpec.type !== 'file' &&
rSpec.type !== 'directory' &&
spec.type !== 'directory' &&
spec.type !== 'git' &&
spec.type !== 'file' &&
spec.type !== 'remote') {
lock.resolved = node.resolved
lock.resolved = overrideResolves(node.resolved, this.resolveOptions)
}

if (node.integrity) {
Expand Down
56 changes: 44 additions & 12 deletions test/shrinkwrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,19 +227,22 @@ t.test('throws when attempting to access data before loading', t => {
t.end()
})

t.test('omitLockfileRegistryResolved', async t => {
const url = 'https://registry.npmjs.org/registry/-/registry-1.2.3.tgz'
const getData = async (omitLockfileRegistryResolved) => {
t.test('resolveOptions', async t => {
const url = 'https://private.registry.org/deadbeef/registry/-/registry-1.2.3.tgz'
const someOtherRegistry = 'https://someother.registry.org/registry/-/registry-1.2.3.tgz'
const getData = async (resolveOptions) => {
const dir = t.testdir()
const meta = await Shrinkwrap.load({
path: dir,
omitLockfileRegistryResolved})
resolveOptions,
})

const root = new Node({
pkg: {
name: 'root',
dependencies: {
registry: '^1.0.0',
'some-other-registry': '^1.0.0',
tar: url,
},
},
Expand All @@ -249,26 +252,55 @@ t.test('omitLockfileRegistryResolved', async t => {
})

const registry = new Node({
pkg: {name: 'registry', version: '1.2.3' },
pkg: { name: 'registry', version: '1.2.3' },
resolved: url,
integrity: 'sha512-registry',
parent: root,
})

const otherRegistry = new Node({
pkg: { name: 'some-other-registry', version: '1.2.3' },
resolved: someOtherRegistry,
integrity: 'sha512-registry',
parent: root,
})

const tar = new Node({
pkg: {name: 'tar', version: '1.2.3'},
pkg: { name: 'tar', version: '1.2.3' },
resolved: url,
integrity: 'sha512-registry',
parent: root,
})

calcDepFlags(root)
meta.add(root)
return { data: meta.commit(), registry, tar, root }
return { data: meta.commit(), registry, tar, root, otherRegistry }
}

await t.test('true', async t => {
const { data } = await getData(true)
await t.test('with recordResolvedRegistry', async t => {
const { data } = await getData({
registry: 'https://private.registry.org/deadbeef',
recordResolvedRegistry: 'https://registry.npmjs.org',
})

t.strictSame(data.packages['node_modules/registry'].resolved,
'https://registry.npmjs.org/registry/-/registry-1.2.3.tgz')
t.strictSame(data.dependencies.registry.resolved,
'https://registry.npmjs.org/registry/-/registry-1.2.3.tgz')

// some-other-registry is a registry dependency but the registry hosts
// tarballs on another host. we don't know if that url is portable, or what
// part of the url is the registry to replace so we have to leave it as is.
t.strictSame(data.packages['node_modules/some-other-registry'].resolved, someOtherRegistry)
t.strictSame(data.dependencies['some-other-registry'].resolved, someOtherRegistry)

// should not affect url dependencies
t.strictSame(data.packages['node_modules/tar'].resolved, url)
t.strictSame(data.dependencies.tar.resolved, undefined)
})

await t.test('omitLockfileRegistryResolved', async t => {
const { data } = await getData({ omitLockfileRegistryResolved: true })
// registry dependencies in v2 packages and v1 dependencies should
// have resolved stripped.
t.strictSame(data.packages['node_modules/registry'].resolved, undefined)
Expand All @@ -280,8 +312,8 @@ t.test('omitLockfileRegistryResolved', async t => {
t.strictSame(data.dependencies.tar.resolved, undefined)
})

await t.test('false', async t => {
const { data } = await getData(false)
await t.test('omitLockfileRegistryResolved: false', async t => {
const { data } = await getData({ omitLockfileRegistryResolved: false })
t.strictSame(data.packages['node_modules/registry'].resolved, url)
t.strictSame(data.dependencies.registry.resolved, url)

Expand All @@ -292,7 +324,7 @@ t.test('omitLockfileRegistryResolved', async t => {

t.test('metaFromNode default', async t => {
// test to cover options default.
const { registry } = await getData(false)
const { registry } = await getData(undefined)
t.strictSame(Shrinkwrap.metaFromNode(registry, '').resolved, url)
})
})
Expand Down

0 comments on commit 151a31f

Please sign in to comment.