Skip to content

Commit

Permalink
feat: Add shebangs to all ignored executable files
Browse files Browse the repository at this point in the history
  • Loading branch information
scagood committed Jan 26, 2024
1 parent 5ad657c commit 8d0442b
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 9 deletions.
46 changes: 37 additions & 9 deletions lib/rules/shebang.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
"use strict"

const path = require("path")
const { accessSync, constants } = require("node:fs")

const getConvertPath = require("../util/get-convert-path")
const getPackageJson = require("../util/get-package-json")
const getNpmignore = require("../util/get-npmignore")

const NODE_SHEBANG = "#!/usr/bin/env node\n"
const SHEBANG_PATTERN = /^(#!.+?)?(\r)?\n/u
Expand All @@ -21,6 +24,15 @@ function simulateNodeResolutionAlgorithm(filePath, binField) {
return possibilities.includes(binField)
}

function isExecutable(path) {
try {
accessSync(path, constants.X_OK)
return true
} catch (error) {
return false
}
}

/**
* Checks whether or not a given path is a `bin` file.
*
Expand Down Expand Up @@ -95,26 +107,42 @@ module.exports = {
},
create(context) {
const sourceCode = context.sourceCode ?? context.getSourceCode() // TODO: just use context.sourceCode when dropping eslint < v9
let filePath = context.filename ?? context.getFilename()
const filePath = context.filename ?? context.getFilename()
if (filePath === "<input>") {
return {}
}
filePath = path.resolve(filePath)

const p = getPackageJson(filePath)
if (!p) {
return {}
}

const basedir = path.dirname(p.filePath)
filePath = path.join(
basedir,
getConvertPath(context)(
path.relative(basedir, filePath).replace(/\\/gu, "/")
)
const packageDirectory = path.dirname(p.filePath)

const originalAbsolutePath = path.resolve(filePath)
const originalRelativePath = path.posix.relative(
packageDirectory,
originalAbsolutePath
)

const convertedRelativePath =
getConvertPath(context)(originalRelativePath)
const convertedAbsolutePath = path.posix.resolve(
packageDirectory,
convertedRelativePath
)

const npmignore = getNpmignore(convertedAbsolutePath)

const isFileBin = isBinFile(
convertedAbsolutePath,
p.bin,
packageDirectory
)
const isFileIgnored = npmignore.match(convertedRelativePath)
const isFileExecutable = isExecutable(originalAbsolutePath)

const needsShebang = isBinFile(filePath, p.bin, basedir)
const needsShebang = isFileBin || (isFileIgnored && isFileExecutable)
const info = getShebangInfo(sourceCode)

return {
Expand Down
2 changes: 2 additions & 0 deletions tests/fixtures/shebang/ignored/executable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env node
module.exports = {}
1 change: 1 addition & 0 deletions tests/fixtures/shebang/ignored/normal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = {}
7 changes: 7 additions & 0 deletions tests/fixtures/shebang/ignored/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "test",
"version": "0.0.0",
"files": [
"./bin/test.js"
]
}
24 changes: 24 additions & 0 deletions tests/lib/rules/shebang.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,16 @@ ruleTester.run("shebang", rule, {
filename: fixture("object-bin/bin/index.js"),
code: "#!/usr/bin/env node\nhello();",
},

// ignored files are executable
{
filename: fixture("ignored/executable.js"),
code: "#!/usr/bin/env node\nhello();",
},
{
filename: fixture("ignored/normal.js"),
code: "hello();",
},
],
invalid: [
{
Expand Down Expand Up @@ -319,5 +329,19 @@ ruleTester.run("shebang", rule, {
output: "#!/usr/bin/env node\nhello();",
errors: ['This file needs shebang "#!/usr/bin/env node".'],
},

// ignored files are executable
{
filename: fixture("ignored/executable.js"),
code: "hello();",
output: "#!/usr/bin/env node\nhello();",
errors: ['This file needs shebang "#!/usr/bin/env node".'],
},
{
filename: fixture("ignored/normal.js"),
code: "#!/usr/bin/env node\nhello();",
output: "hello();",
errors: ["This file needs no shebang."],
},
],
})

0 comments on commit 8d0442b

Please sign in to comment.