Skip to content

Commit

Permalink
Merge pull request #80 from SocketDev/lenient-args
Browse files Browse the repository at this point in the history
make argv parsing more tolerant and align with GH
  • Loading branch information
bmeck authored Aug 23, 2023
2 parents 6b68ea1 + cb71763 commit 6b2f6a1
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 95 deletions.
129 changes: 54 additions & 75 deletions lib/utils/path-resolve.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { globby } from 'globby'
import ignore from 'ignore'
// @ts-ignore This package provides no types
import { directories } from 'ignore-by-default'
import micromatch from 'micromatch'
import { ErrorWithCause } from 'pony-cause'

import { InputError } from './errors.js'
Expand Down Expand Up @@ -94,85 +93,65 @@ export async function mapGlobResultToFiles (entries, supportedFiles) {
* @throws {InputError}
*/
export async function mapGlobEntryToFiles (entry, supportedFiles) {
/** @type {string|undefined} */
let pkgJSFile
/** @type {string[]} */
let jsLockFiles = []
/** @type {string[]} */
let pyFiles = []
/** @type {string|undefined} */
let pkgGoFile
/** @type {string[]} */
let goExtraFiles = []

const jsSupported = supportedFiles['npm'] || {}
const jsLockFilePatterns = Object.keys(jsSupported)
.filter(key => key !== 'packagejson')
.map(key => /** @type {{ pattern: string }} */ (jsSupported[key]).pattern)
const jsLockFilePatterns = Object.values(jsSupported)
// .filter(key => key !== 'packagejson')
.map(p => `**/${/** @type {{ pattern: string }} */ (p).pattern}`)

const pyFilePatterns = Object.values(supportedFiles['pypi'] || {})
.map(p => /** @type {{ pattern: string }} */ (p).pattern)
.map(p => `**/${/** @type {{ pattern: string }} */ (p).pattern}`)

const goSupported = supportedFiles['go'] || {}
const goSupplementalPatterns = Object.keys(goSupported)
.filter(key => key !== 'gomod')
.map(key => /** @type {{ pattern: string }} */ (goSupported[key]).pattern)

if (entry.endsWith('/')) {
// If the match is a folder and that folder contains a package.json file, then include it
const jsPkg = path.resolve(entry, 'package.json')
if (await fileExists(jsPkg)) pkgJSFile = jsPkg

const goPkg = path.resolve(entry, 'go.mod')
if (await fileExists(goPkg)) pkgGoFile = goPkg

pyFiles = await globby(pyFilePatterns, {
...BASE_GLOBBY_OPTS,
cwd: entry
})
} else {
const entryFile = path.basename(entry)

if (entryFile === 'package.json') {
// If the match is a package.json file, then include it
pkgJSFile = entry
} else if (micromatch.isMatch(entryFile, jsLockFilePatterns)) {
jsLockFiles = [entry]
pkgJSFile = path.resolve(path.dirname(entry), 'package.json')
if (!(await fileExists(pkgJSFile))) return []
} else if (entryFile === 'go.mod') {
pkgGoFile = entry
} else if (micromatch.isMatch(entryFile, goSupplementalPatterns)) {
goExtraFiles = [entry]
pkgGoFile = path.resolve(path.dirname(entry), 'go.mod')
} else if (micromatch.isMatch(entryFile, pyFilePatterns)) {
pyFiles = [entry]
}
}

// If we will include a package.json file but don't already have a corresponding lockfile, then look for one
if (!jsLockFiles.length && pkgJSFile) {
const pkgDir = path.dirname(pkgJSFile)

jsLockFiles = await globby(jsLockFilePatterns, {
...BASE_GLOBBY_OPTS,
cwd: pkgDir
})
}

if (!goExtraFiles.length && pkgGoFile) {
// get go.sum whenever possible
const pkgDir = path.dirname(pkgGoFile)

goExtraFiles = await globby(goSupplementalPatterns, {
...BASE_GLOBBY_OPTS,
cwd: pkgDir
})
}

return [...jsLockFiles, ...pyFiles, ...goExtraFiles]
.concat(pkgJSFile ? [pkgJSFile] : [])
.concat(pkgGoFile ? [pkgGoFile] : [])
const goSupplementalPatterns = Object.values(goSupported)
// .filter(key => key !== 'gomod')
.map(p => `**/${/** @type {{ pattern: string }} */ (p).pattern}`)

const files = await globby([
...jsLockFilePatterns,
...pyFilePatterns,
...goSupplementalPatterns
], {
...BASE_GLOBBY_OPTS,
onlyFiles: true,
cwd: path.resolve((await stat(entry)).isDirectory() ? entry : path.dirname(entry))
})
return files

// if (entry.endsWith('/')) {
// // If the match is a folder and that folder contains a package.json file, then include it
// const jsPkg = path.resolve(entry, 'package.json')
// if (await fileExists(jsPkg)) pkgJSFile = jsPkg

// const goPkg = path.resolve(entry, 'go.mod')
// if (await fileExists(goPkg)) pkgGoFile = goPkg

// pyFiles = await globby(pyFilePatterns, {
// ...BASE_GLOBBY_OPTS,
// cwd: entry
// })
// } else {
// const entryFile = path.basename(entry)

// if (entryFile === 'package.json') {
// // If the match is a package.json file, then include it
// pkgJSFile = entry
// } else if (micromatch.isMatch(entryFile, jsLockFilePatterns)) {
// jsLockFiles = [entry]
// pkgJSFile = path.resolve(path.dirname(entry), 'package.json')
// if (!(await fileExists(pkgJSFile))) return []
// } else if (entryFile === 'go.mod') {
// pkgGoFile = entry
// } else if (micromatch.isMatch(entryFile, goSupplementalPatterns)) {
// goExtraFiles = [entry]
// pkgGoFile = path.resolve(path.dirname(entry), 'go.mod')
// } else if (micromatch.isMatch(entryFile, pyFilePatterns)) {
// pyFiles = [entry]
// }
// }

// return [...jsLockFiles, ...pyFiles, ...goExtraFiles]
// .concat(pkgJSFile ? [pkgJSFile] : [])
// .concat(pkgGoFile ? [pkgGoFile] : [])
}

/**
Expand Down
5 changes: 2 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@
"is-interactive": "^2.0.0",
"is-unicode-supported": "^1.3.0",
"meow": "^12.0.1",
"micromatch": "^4.0.5",
"ora": "^6.1.2",
"pony-cause": "^2.1.8",
"prompts": "^2.4.2",
Expand Down
22 changes: 6 additions & 16 deletions test/path-resolve.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,11 @@ describe('Path Resolve', () => {
assert.deepEqual(await sortedMapGlobEntry('/foo.txt', globPatterns), [])
})

it('should throw on errors', async () => {
it('should be lenient on oddities', async () => {
mockFs({
'/package.json': { /* Empty directory */ },
})
await assert.rejects(sortedMapGlobEntry('/', globPatterns), (e) => {
return e instanceof InputError && e.message.includes('Expected \'/package.json\' to be a file')
})
await assert.deepEqual(await sortedMapGlobEntry('/', globPatterns), [])
})
})

Expand All @@ -157,7 +155,7 @@ describe('Path Resolve', () => {
mockFs({
'/package-lock.json': '{}',
})
assert.deepEqual(await sortedMapGlobEntry('/', globPatterns), [])
assert.deepEqual(await sortedMapGlobEntry('/', globPatterns), ['/package-lock.json'])
})

it('should support alternative lock files', async () => {
Expand Down Expand Up @@ -191,19 +189,11 @@ describe('Path Resolve', () => {
assert.strict.deepEqual(await sortedMapGlobEntry('/package.json', globPatterns), ['/package.json'])
})

it('should not validate the input file', async () => {
it('should validate the input file', async () => {
mockFs({})
assert.deepEqual(await sortedMapGlobEntry('/package.json', globPatterns), ['/package.json'])
})

it('should not validate the input file, but still add a complementary lock file', async () => {
mockFs({
'/package-lock.json': '{}',
return assert.rejects(sortedMapGlobEntry('/package.json', globPatterns), (err) => {
return err instanceof Error && err.message.includes('ENOENT')
})
assert.deepEqual(await sortedMapGlobEntry('/package.json', globPatterns), [
'/package-lock.json',
'/package.json'
])
})

it('should support alternative lock files', async () => {
Expand Down

0 comments on commit 6b2f6a1

Please sign in to comment.