Last active
July 8, 2021 17:15
-
-
Save n8jadams/a14c5526cb834cfe908ca1f12ce9b336 to your computer and use it in GitHub Desktop.
Run eslint against your staged changes (Assumes this is placed at the top level of your repo)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const path = require('path') | |
const { execSync, spawnSync } = require('child_process') | |
const fs = require('fs') | |
const micromatch = require('micromatch') | |
const lockfile = path.resolve(__dirname, 'linter-script-lockfile') | |
const eslintFileTypes = ['js', 'jsx', 'ts', 'tsx'] | |
function readGlobsFromFile(filename) { | |
if (!fs.existsSync(filename)) { | |
return [] | |
} | |
return fs | |
.readFileSync(filename, 'utf-8') | |
.split('\n') | |
.map((f) => f.trim()) | |
.filter(Boolean) | |
} | |
function deleteLockfile() { | |
fs.unlinkSync(lockfile) | |
} | |
function killFunction() { | |
console.log('Halting the lint/format script. Cleaning up...') | |
deleteLockfile() | |
process.exit(0) | |
} | |
process.on('SIGINT', killFunction) | |
process.on('SIGTERM', killFunction) | |
;(function main() { | |
// Ensure this script isn't being run already | |
if (fs.existsSync(lockfile)) { | |
console.error( | |
'ERROR! Cannot run linter script if it is already running elsewhere' | |
) | |
process.exit(1) | |
} | |
fs.writeFileSync(lockfile, '') | |
// Read in staged files | |
const gitStatus = execSync('git status --porcelain').toString() | |
const stagedFiles = [] | |
const partiallyUnstagedCache = [] | |
for (const line of gitStatus.split('\n')) { | |
const extention = line.split('.').pop() | |
if (/^A {2}/.test(line)) { | |
// Staged new file | |
stagedFiles.push(line.split('A ')[1]) | |
} else if (/^M {2}/.test(line)) { | |
// Staged modification | |
stagedFiles.push(line.split('M ')[1]) | |
} else if (/^R {2}/.test(line)) { | |
// Staged rename | |
const fileNames = line.replace('R ', '').split(' -> ') | |
stagedFiles.push(fileNames[1]) | |
} else if (/^(M|A)M /.test(line) && eslintFileTypes.includes(extention)) { | |
// A partially staged lintable file | |
// Read in the unstaged filecontents | |
const filename = line.replace(/^(M|A)M /, '') | |
const unstagedFileContents = fs.readFileSync(filename, 'utf-8') | |
partiallyUnstagedCache.push({ | |
filename, | |
filecontents: unstagedFileContents, | |
}) | |
// Get the staged contents | |
const stagedFileContents = execSync(`git show :${filename}`).toString() | |
// Write the staged contents to the actual file | |
fs.writeFileSync(path.resolve(__dirname, filename), stagedFileContents) | |
stagedFiles.push(filename) | |
} | |
} | |
// Filter out eslint ignored files | |
const eslintIgnoreGlobs = readGlobsFromFile(path.resolve(__dirname, './.eslintignore')) | |
const stagedLintableFiles = stagedFiles.filter((f) => { | |
const ext = f.split('.').pop() | |
return ( | |
eslintFileTypes.includes(ext) && !micromatch.isMatch(f, eslintIgnoreGlobs) | |
) | |
}) | |
// Run the eslint command! | |
if (stagedLintableFiles.length > 0) { | |
const eslintCmd = `${path.resolve(__dirname, './node_modules/.bin/eslint')} --fix --max-warnings=0 --no-error-on-unmatched-pattern ${stagedLintableFiles.join( | |
' ' | |
)}` | |
console.log(eslintCmd) | |
const eslint = spawnSync( | |
eslintCmd.split(' ')[0], | |
eslintCmd.split(' ').slice(1), | |
{ stdio: 'inherit', shell: true, cwd: __dirname } | |
) | |
if (eslint.status !== 0) { | |
// Restore the partiallyUnstagedCache | |
partiallyUnstagedCache.forEach(({ filename, filecontents }) => { | |
fs.writeFileSync(filename, filecontents) | |
}) | |
deleteLockfile() | |
process.exit(1) | |
} | |
} | |
// Final step, move the unstaged changes back | |
partiallyUnstagedCache.forEach(({ filename, filecontents }) => { | |
fs.writeFileSync(filename, filecontents) | |
}) | |
deleteLockfile() | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment