update
This commit is contained in:
118
package/node_modules/libnpmdiff/lib/format-diff.js
generated
vendored
Normal file
118
package/node_modules/libnpmdiff/lib/format-diff.js
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
const jsDiff = require('diff')
|
||||
|
||||
const shouldPrintPatch = require('./should-print-patch.js')
|
||||
|
||||
const colors = {
|
||||
// red
|
||||
removed: { open: '\x1B[31m', close: '\x1B[39m' },
|
||||
// green
|
||||
added: { open: '\x1B[32m', close: '\x1B[39m' },
|
||||
// blue
|
||||
header: { open: '\x1B[34m', close: '\x1B[39m' },
|
||||
// cyan
|
||||
section: { open: '\x1B[36m', close: '\x1B[39m' },
|
||||
}
|
||||
|
||||
const color = (colorStr, colorId) => {
|
||||
const { open, close } = colors[colorId]
|
||||
// avoid highlighting the "\n" (would highlight till the end of the line)
|
||||
return colorStr.replace(/[^\n\r]+/g, open + '$&' + close)
|
||||
}
|
||||
|
||||
const formatDiff = ({ files, opts = {}, refs, versions }) => {
|
||||
let res = ''
|
||||
const srcPrefix = opts.diffNoPrefix ? '' : opts.diffSrcPrefix || 'a/'
|
||||
const dstPrefix = opts.diffNoPrefix ? '' : opts.diffDstPrefix || 'b/'
|
||||
|
||||
for (const filename of files.values()) {
|
||||
const names = {
|
||||
a: `${srcPrefix}${filename}`,
|
||||
b: `${dstPrefix}${filename}`,
|
||||
}
|
||||
|
||||
let fileMode = ''
|
||||
const filenames = {
|
||||
a: refs.get(`a/${filename}`),
|
||||
b: refs.get(`b/${filename}`),
|
||||
}
|
||||
const contents = {
|
||||
a: filenames.a && filenames.a.content,
|
||||
b: filenames.b && filenames.b.content,
|
||||
}
|
||||
const modes = {
|
||||
a: filenames.a && filenames.a.mode,
|
||||
b: filenames.b && filenames.b.mode,
|
||||
}
|
||||
|
||||
if (contents.a === contents.b && modes.a === modes.b) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (opts.diffNameOnly) {
|
||||
res += `${filename}\n`
|
||||
continue
|
||||
}
|
||||
|
||||
let patch = ''
|
||||
let headerLength = 0
|
||||
const header = str => {
|
||||
headerLength++
|
||||
patch += `${str}\n`
|
||||
}
|
||||
|
||||
// manually build a git diff-compatible header
|
||||
header(`diff --git ${names.a} ${names.b}`)
|
||||
if (modes.a === modes.b) {
|
||||
fileMode = filenames.a.mode
|
||||
} else {
|
||||
if (modes.a && !modes.b) {
|
||||
header(`deleted file mode ${modes.a}`)
|
||||
} else if (!modes.a && modes.b) {
|
||||
header(`new file mode ${modes.b}`)
|
||||
} else {
|
||||
header(`old mode ${modes.a}`)
|
||||
header(`new mode ${modes.b}`)
|
||||
}
|
||||
}
|
||||
/* eslint-disable-next-line max-len */
|
||||
header(`index ${opts.tagVersionPrefix || 'v'}${versions.a}..${opts.tagVersionPrefix || 'v'}${versions.b} ${fileMode}`)
|
||||
|
||||
if (shouldPrintPatch(filename)) {
|
||||
patch += jsDiff.createTwoFilesPatch(
|
||||
names.a,
|
||||
names.b,
|
||||
contents.a || '',
|
||||
contents.b || '',
|
||||
'',
|
||||
'',
|
||||
{
|
||||
context: opts.diffUnified === 0 ? 0 : opts.diffUnified || 3,
|
||||
ignoreWhitespace: opts.diffIgnoreAllSpace,
|
||||
}
|
||||
).replace(
|
||||
'===================================================================\n',
|
||||
''
|
||||
).replace(/\t\n/g, '\n') // strip trailing tabs
|
||||
headerLength += 2
|
||||
} else {
|
||||
header(`--- ${names.a}`)
|
||||
header(`+++ ${names.b}`)
|
||||
}
|
||||
|
||||
if (opts.color) {
|
||||
// this RegExp will include all the `\n` chars into the lines, easier to join
|
||||
const lines = patch.split(/^/m)
|
||||
res += color(lines.slice(0, headerLength).join(''), 'header')
|
||||
res += lines.slice(headerLength).join('')
|
||||
.replace(/^-.*/gm, color('$&', 'removed'))
|
||||
.replace(/^\+.*/gm, color('$&', 'added'))
|
||||
.replace(/^@@.+@@/gm, color('$&', 'section'))
|
||||
} else {
|
||||
res += patch
|
||||
}
|
||||
}
|
||||
|
||||
return res.trim()
|
||||
}
|
||||
|
||||
module.exports = formatDiff
|
||||
62
package/node_modules/libnpmdiff/lib/index.js
generated
vendored
Normal file
62
package/node_modules/libnpmdiff/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
const pacote = require('pacote')
|
||||
|
||||
const formatDiff = require('./format-diff.js')
|
||||
const getTarball = require('./tarball.js')
|
||||
const untar = require('./untar.js')
|
||||
|
||||
// TODO: we test this condition in the diff command
|
||||
// so this error probably doesnt need to be here. Or
|
||||
// if it does we should figure out a standard code
|
||||
// so we can catch it in the cli and display it consistently
|
||||
const argsError = () =>
|
||||
Object.assign(
|
||||
new TypeError('libnpmdiff needs two arguments to compare'),
|
||||
{ code: 'EDIFFARGS' }
|
||||
)
|
||||
const diff = async (specs, opts = {}) => {
|
||||
if (specs.length !== 2) {
|
||||
throw argsError()
|
||||
}
|
||||
|
||||
const [
|
||||
aManifest,
|
||||
bManifest,
|
||||
] =
|
||||
await Promise.all(specs.map(spec => pacote.manifest(spec, opts)))
|
||||
|
||||
const versions = {
|
||||
a: aManifest.version,
|
||||
b: bManifest.version,
|
||||
}
|
||||
|
||||
// fetches tarball using pacote
|
||||
const [a, b] = await Promise.all([
|
||||
getTarball(aManifest, opts),
|
||||
getTarball(bManifest, opts),
|
||||
])
|
||||
|
||||
// read all files
|
||||
// populates `files` and `refs`
|
||||
const {
|
||||
files,
|
||||
refs,
|
||||
} = await untar([
|
||||
{
|
||||
prefix: 'a/',
|
||||
item: a,
|
||||
},
|
||||
{
|
||||
prefix: 'b/',
|
||||
item: b,
|
||||
},
|
||||
], opts)
|
||||
|
||||
return formatDiff({
|
||||
files,
|
||||
opts,
|
||||
refs,
|
||||
versions,
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = diff
|
||||
22
package/node_modules/libnpmdiff/lib/should-print-patch.js
generated
vendored
Normal file
22
package/node_modules/libnpmdiff/lib/should-print-patch.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
const { basename, extname } = require('node:path')
|
||||
|
||||
const binaryExtensions = require('binary-extensions')
|
||||
|
||||
// we should try to print patches as long as the
|
||||
// extension is not identified as binary files
|
||||
const shouldPrintPatch = (path, opts = {}) => {
|
||||
if (opts.diffText) {
|
||||
return true
|
||||
}
|
||||
|
||||
const filename = basename(path)
|
||||
const extension = (
|
||||
filename.startsWith('.')
|
||||
? filename
|
||||
: extname(filename)
|
||||
).slice(1)
|
||||
|
||||
return !binaryExtensions.includes(extension)
|
||||
}
|
||||
|
||||
module.exports = shouldPrintPatch
|
||||
38
package/node_modules/libnpmdiff/lib/tarball.js
generated
vendored
Normal file
38
package/node_modules/libnpmdiff/lib/tarball.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
const { relative } = require('node:path')
|
||||
|
||||
const Arborist = require('@npmcli/arborist')
|
||||
const npa = require('npm-package-arg')
|
||||
const pkgContents = require('@npmcli/installed-package-contents')
|
||||
const pacote = require('pacote')
|
||||
const { tarCreateOptions } = pacote.DirFetcher
|
||||
const tar = require('tar')
|
||||
|
||||
// returns a simplified tarball when reading files from node_modules folder,
|
||||
// thus avoiding running the prepare scripts and the extra logic from packlist
|
||||
const nodeModulesTarball = (manifest) =>
|
||||
pkgContents({ path: manifest._resolved, depth: 1 })
|
||||
.then(files =>
|
||||
files.map(file => relative(manifest._resolved, file))
|
||||
)
|
||||
.then(files =>
|
||||
tar.c(tarCreateOptions(manifest), files).concat()
|
||||
)
|
||||
|
||||
const tarball = (manifest, opts) => {
|
||||
const resolved = manifest._resolved
|
||||
const where = opts.where || process.cwd()
|
||||
|
||||
const fromNodeModules = npa(resolved).type === 'directory'
|
||||
&& /node_modules[\\/](@[^\\/]+\/)?[^\\/]+[\\/]?$/.test(relative(where, resolved))
|
||||
|
||||
if (fromNodeModules) {
|
||||
return nodeModulesTarball(manifest, opts)
|
||||
}
|
||||
|
||||
return pacote.tarball(manifest._resolved, {
|
||||
...opts,
|
||||
Arborist,
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = tarball
|
||||
96
package/node_modules/libnpmdiff/lib/untar.js
generated
vendored
Normal file
96
package/node_modules/libnpmdiff/lib/untar.js
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
const tar = require('tar')
|
||||
const { minimatch } = require('minimatch')
|
||||
|
||||
const normalizeMatch = str => str
|
||||
.replace(/\\+/g, '/')
|
||||
.replace(/^\.\/|^\./, '')
|
||||
|
||||
// files and refs are mutating params
|
||||
// filterFiles, item, prefix and opts are read-only options
|
||||
const untar = ({ files, refs }, { filterFiles, item, prefix }) => {
|
||||
tar.list({
|
||||
filter: (path, entry) => {
|
||||
const fileMatch = () =>
|
||||
(!filterFiles.length ||
|
||||
filterFiles.some(f => {
|
||||
const pattern = normalizeMatch(f)
|
||||
return minimatch(
|
||||
normalizeMatch(path),
|
||||
`{package/,}${pattern}`,
|
||||
{ matchBase: pattern.startsWith('*') }
|
||||
)
|
||||
}))
|
||||
|
||||
// expands usage of simple path filters, e.g: lib or src/
|
||||
const folderMatch = () =>
|
||||
filterFiles.some(f =>
|
||||
normalizeMatch(path).startsWith(normalizeMatch(f)) ||
|
||||
normalizeMatch(path).startsWith(`package/${normalizeMatch(f)}`))
|
||||
|
||||
if (
|
||||
entry.type === 'File' &&
|
||||
(fileMatch() || folderMatch())
|
||||
) {
|
||||
const key = path.replace(/^[^/]+\/?/, '')
|
||||
files.add(key)
|
||||
|
||||
// should skip reading file when using --name-only option
|
||||
let content
|
||||
try {
|
||||
entry.setEncoding('utf8')
|
||||
content = entry.concat()
|
||||
} catch (e) {
|
||||
/* istanbul ignore next */
|
||||
throw Object.assign(
|
||||
new Error('failed to read files'),
|
||||
{ code: 'EDIFFUNTAR' }
|
||||
)
|
||||
}
|
||||
|
||||
refs.set(`${prefix}${key}`, {
|
||||
content,
|
||||
mode: `100${entry.mode.toString(8)}`,
|
||||
})
|
||||
return true
|
||||
}
|
||||
},
|
||||
})
|
||||
.on('error', /* istanbul ignore next */ e => {
|
||||
throw e
|
||||
})
|
||||
.end(item)
|
||||
}
|
||||
|
||||
const readTarballs = async (tarballs, opts = {}) => {
|
||||
const files = new Set()
|
||||
const refs = new Map()
|
||||
const arr = [].concat(tarballs)
|
||||
|
||||
const filterFiles = opts.diffFiles || []
|
||||
|
||||
for (const i of arr) {
|
||||
untar({
|
||||
files,
|
||||
refs,
|
||||
}, {
|
||||
item: i.item,
|
||||
prefix: i.prefix,
|
||||
filterFiles,
|
||||
})
|
||||
}
|
||||
|
||||
// await to read all content from included files
|
||||
const allRefs = [...refs.values()]
|
||||
const contents = await Promise.all(allRefs.map(async ref => ref.content))
|
||||
|
||||
contents.forEach((content, index) => {
|
||||
allRefs[index].content = content
|
||||
})
|
||||
|
||||
return {
|
||||
files,
|
||||
refs,
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = readTarballs
|
||||
Reference in New Issue
Block a user