build: add basic linting for the patches folder to ensure that .patches match the state on disk (#18615)

This commit is contained in:
Samuel Attard 2019-06-19 10:48:15 -07:00 committed by GitHub
parent ae49aa4a03
commit 00d18917d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -133,12 +133,60 @@ const LINTERS = [ {
process.exit(1)
}
}
}, {
key: 'patches',
roots: ['patches'],
test: () => true,
run: () => {
const patchesDir = path.resolve(__dirname, '../patches')
for (const patchTarget of fs.readdirSync(patchesDir)) {
const targetDir = path.resolve(patchesDir, patchTarget)
// If the config does not exist that is OK, we just skip this dir
const targetConfig = path.resolve(targetDir, 'config.json')
if (!fs.existsSync(targetConfig)) continue
const config = JSON.parse(fs.readFileSync(targetConfig, 'utf8'))
for (const key of Object.keys(config)) {
// The directory the config points to should exist
const targetPatchesDir = path.resolve(__dirname, '../../..', key)
if (!fs.existsSync(targetPatchesDir)) throw new Error(`target patch directory: "${targetPatchesDir}" does not exist`)
// We need a .patches file
const dotPatchesPath = path.resolve(targetPatchesDir, '.patches')
if (!fs.existsSync(dotPatchesPath)) throw new Error(`.patches file: "${dotPatchesPath}" does not exist`)
// Read the patch list
const patchFileList = fs.readFileSync(dotPatchesPath, 'utf8').trim().split('\n')
const patchFileSet = new Set(patchFileList)
patchFileList.reduce((seen, file) => {
if (seen.has(file)) {
throw new Error(`'${file}' is listed in ${dotPatchesPath} more than once`)
}
return seen.add(file)
}, new Set())
if (patchFileList.length !== patchFileSet.size) throw new Error('each patch file should only be in the .patches file once')
for (const file of fs.readdirSync(targetPatchesDir)) {
// Ignore the .patches file and READMEs
if (file === '.patches' || file === 'README.md') continue
if (!patchFileSet.has(file)) {
throw new Error(`Expected the .patches file at "${dotPatchesPath}" to contain a patch file ("${file}") present in the directory but it did not`)
}
patchFileSet.delete(file)
}
// If anything is left in this set, it means it did not exist on disk
if (patchFileSet.size > 0) {
throw new Error(`Expected all the patch files listed in the .patches file at "${dotPatchesPath}" to exist but some did not:\n${JSON.stringify([...patchFileSet.values()], null, 2)}`)
}
}
}
}
}]
function parseCommandLine () {
let help
const opts = minimist(process.argv.slice(2), {
boolean: [ 'c++', 'objc', 'javascript', 'python', 'gn', 'help', 'changed', 'fix', 'verbose', 'only' ],
boolean: [ 'c++', 'objc', 'javascript', 'python', 'gn', 'patches', 'help', 'changed', 'fix', 'verbose', 'only' ],
alias: { 'c++': ['cc', 'cpp', 'cxx'], javascript: ['js', 'es'], python: 'py', changed: 'c', help: 'h', verbose: 'v' },
unknown: arg => { help = true }
})
@ -221,8 +269,8 @@ async function main () {
const opts = parseCommandLine()
// no mode specified? run 'em all
if (!opts['c++'] && !opts.javascript && !opts.python && !opts.gn) {
opts['c++'] = opts.javascript = opts.python = opts.gn = true
if (!opts['c++'] && !opts.javascript && !opts.python && !opts.gn && !opts.patches) {
opts['c++'] = opts.javascript = opts.python = opts.gn = opts.patches = true
}
const linters = LINTERS.filter(x => opts[x.key])