diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2020-12-10 08:54:02 +0100 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2020-12-11 10:58:29 +0100 |
commit | b25131ed65496c9cf0f616f761517590aa16d120 (patch) | |
tree | bf0076fe1dc29e87ac4ea7b7b46ecd1339d47173 /src/package/script.rs | |
parent | b7f6276b1d3b9678f9cafa377ec8307845c3446b (diff) |
Add feature: script linting
This patch adds script linting via a configurable script.
With this patch, the configuration can point to a script or program that
gets the packaging script on STDIN and might exit with a nonzero value
on error.
The simplest script I can think of that adds value is:
#!/bin/bash
shellcheck -
to run the packaging script through shellcheck.
stdout and stderr of the linting script are printed in case of non-zero
return value.
Linting can be disabled by not setting the script in the config or by
passing a commandline flag to skip linting (a warning will be printed in
this case).
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
Diffstat (limited to 'src/package/script.rs')
-rw-r--r-- | src/package/script.rs | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/src/package/script.rs b/src/package/script.rs index 4988e0e..f37dde8 100644 --- a/src/package/script.rs +++ b/src/package/script.rs @@ -1,13 +1,18 @@ -use anyhow::anyhow; +use std::process::ExitStatus; + use anyhow::Error; +use anyhow::Context as AnyhowContext; use anyhow::Result; +use anyhow::anyhow; use handlebars::{Handlebars, HelperDef, RenderContext, Helper, Context, JsonRender, HelperResult, Output, RenderError}; +use log::trace; use serde::Deserialize; use serde::Serialize; use syntect::easy::HighlightLines; use syntect::highlighting::{ThemeSet, Style}; use syntect::parsing::SyntaxSet; use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings}; +use tokio::process::Command; use crate::package::Package; use crate::phase::Phase; @@ -40,6 +45,43 @@ impl Script { pub fn lines_numbered(&self) -> impl Iterator<Item = (usize, &str)> { self.0.lines().enumerate() } + + pub async fn lint(&self, mut cmd: Command) -> Result<(ExitStatus, String, String)> { + use tokio::io::AsyncWriteExt; + use tokio::io::BufWriter; + + let mut child = cmd + .stderr(std::process::Stdio::piped()) + .stdout(std::process::Stdio::piped()) + .stdin(std::process::Stdio::piped()) + .spawn() + .context("Spawning subprocess for linting package script")?; + + trace!("Child = {:?}", child); + + { + let stdin = child.stdin.take().ok_or_else(|| anyhow!("No stdin"))?; + let mut writer = BufWriter::new(stdin); + let _ = writer + .write_all(self.0.as_bytes()) + .await + .context("Writing package script to STDIN of subprocess")?; + + let _ = writer + .flush() + .await + .context("Flushing STDIN of subprocess")?; + trace!("Script written"); + } + + trace!("Waiting for child..."); + let out = child.wait_with_output() + .await + .context("Waiting for subprocess")?; + + Ok((out.status, String::from_utf8(out.stdout)?, String::from_utf8(out.stderr)?)) + } + } #[derive(Debug)] @@ -87,6 +129,7 @@ impl<'a> HighlightedScript<'a> { pub fn lines_numbered(&'a self) -> Result<impl Iterator<Item = (usize, String)> + 'a> { self.lines().map(|iter| iter.enumerate()) } + } impl From<String> for Shebang { |