shellcheck

This commit is contained in:
2019-09-16 00:00:03 -04:00
parent 54254dbf5f
commit 702bf94014
3 changed files with 77 additions and 20 deletions
+3
View File
@@ -11,3 +11,6 @@ system-install: @confirm
pypi-upload: python-dev-deps
pipenv run setup.py upload
test:
echo $@
+31 -11
View File
@@ -1,8 +1,12 @@
import sys
import os
import json
import os
import stat
import sys
from random import randint
from shlex import quote as shlex_quote
from tempfile import mkstemp
import delegator
import click
from .bash import Bash
@@ -140,11 +144,7 @@ class TaskScript(BaseAction):
if line.startswith(indent_style):
return line[len(indent_style) :]
def execute(self, *, blocking=False, debug=False, silent=False, **kwargs):
from tempfile import mkstemp
import stat
from shlex import quote as shlex_quote
def temp_source(self):
tf = mkstemp(suffix=".sh", prefix="bashf-")[1]
with open(tf, "w") as f:
@@ -154,6 +154,12 @@ class TaskScript(BaseAction):
st = os.stat(tf)
os.chmod(tf, st.st_mode | stat.S_IEXEC)
return tf
def execute(self, *, blocking=False, debug=False, silent=False, **kwargs):
tf = self.temp_source()
stdlib_path = os.path.join(os.path.dirname(__file__), "scripts", "stdlib.sh")
args = [shlex_quote(a) for a in self.bashfile.args]
@@ -163,11 +169,19 @@ class TaskScript(BaseAction):
else:
script = shlex_quote(f"{tf} {args} 2>&1 | bake-indent")
cmd = f"bash --init-file {shlex_quote(stdlib_path)} -i -c {script}"
if debug:
print(cmd)
click.echo(f"$ {cmd}", err=True)
return os.system(cmd)
def shellcheck(self, *, silent=False, debug=False, **kwargs):
tf = self.temp_source()
cmd = f"shellcheck {shlex_quote(tf)} --external-sources --format=json"
if debug:
click.echo(f"$ {cmd}", err=True)
return delegator.run(cmd)
@property
def name(self):
return self.chunk[0].split(":")[0].strip()
@@ -177,6 +191,14 @@ class TaskScript(BaseAction):
return self.bashfile.chunks[self._chunk_index]
def _iter_source(self):
try:
has_shebang = self.chunk[2].startswith("#!")
except IndexError:
has_shebang = False
if not has_shebang:
yield "#!/usr/bin/env bash"
for line in self.chunk[1:]:
line = self._transform_line(line)
if line:
@@ -188,9 +210,7 @@ class TaskScript(BaseAction):
@property
def source_lines(self):
def gen():
for line in self.bashfile.source_lines:
pass
return [s for s in self._iter_source()]
class Bakefile:
+43 -9
View File
@@ -11,7 +11,7 @@ import pygments.lexers
import pygments.formatters
SAFE_ENVIRONS = ["HOME", "PATH"]
SAFE_ENVIRONS = ["HOME", "PATH", "LANG", "LOCALE", "TERM", "VIRTUAL_ENV"]
def indent(line):
@@ -171,7 +171,7 @@ def entrypoint(
bakefile.add_args(*argv)
if _list:
if _list and not shellcheck:
__list_json = {"tasks": {}}
for _task in bakefile.tasks:
@@ -202,6 +202,45 @@ def entrypoint(
sys.exit(0)
if shellcheck:
__shellcheck_statuses = []
for _task in bakefile.tasks:
_task = bakefile[_task]
c = _task.shellcheck(silent=silent, debug=debug)
__shellcheck_statuses.append(c.return_code)
if not c.ok:
# click.echo(click.style("Shellcheck failed!", fg="red"), err=True)
if _json:
echo_json(json.loads(c.out))
for report in json.loads(c.out):
level = report["level"]
code = report["code"]
message = report["message"]
line = report["line"]
column = (report["column"], report["endColumn"])
colored_line_n = click.style(
str(line).zfill(3), bg="black", fg="cyan", bold=True
)
colored_task = click.style(str(_task), fg="yellow", bold=True)
actual_line = _task.source_lines[line - 1]
click.echo(f"In {colored_task} line {line}:", err=True)
click.echo(f"{colored_line_n} {actual_line}", err=True)
length = column[1] - column[0]
if not length:
length = len(actual_line)
underline = (" " * 4) + (" " * column[0]) + "^" + "-" * (length - 1)
underline += f"SC{code}: {message}"
underline = click.style(level, fg="magenta") + click.style(
underline[len(level) :], fg="red", bold=True
)
click.echo(underline, err=True)
sys.exit(max(__shellcheck_statuses))
if task:
try:
task = bakefile[task]
@@ -209,7 +248,7 @@ def entrypoint(
click.echo(click.style(f"Task {task} does not exist!", fg="red"))
sys.exit(1)
def execute_task(task, *, next_task=None, silent=False):
def execute_task(task, *, silent=False):
if not silent:
click.echo(
click.style(" + ", fg="white")
@@ -217,7 +256,7 @@ def entrypoint(
+ click.style(":", fg="white"),
err=True,
)
return_code = task.execute(yes=yes, next_task=next_task, silent=silent)
return_code = task.execute(yes=yes, silent=silent)
if not _continue:
if not return_code == 0:
@@ -226,11 +265,6 @@ def entrypoint(
tasks = task.depends_on(recursive=True) + [task]
for task in tasks:
try:
next_task = tasks[tasks.index(task) + 1]
except IndexError:
next_task = None
execute_task(task, next_task=next_task, silent=silent)
if not silent: