summaryrefslogtreecommitdiffstats
path: root/src/package/script.rs
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2020-12-10 08:54:02 +0100
committerMatthias Beyer <mail@beyermatthias.de>2020-12-11 10:58:29 +0100
commitb25131ed65496c9cf0f616f761517590aa16d120 (patch)
treebf0076fe1dc29e87ac4ea7b7b46ecd1339d47173 /src/package/script.rs
parentb7f6276b1d3b9678f9cafa377ec8307845c3446b (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.rs45
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 {