deb: print raw build output again with --verbose
The record-log wrapper provides a sink for every command, which removed the runner's subprocess-inherit fallback -- and with it the raw output of --verbose runs (and of piped stdout, where the live view disables itself): Quiet's None sink got wrapped inside, every line went to build.log, and the terminal showed nothing but pkh's own logs, breaking what --help still promises. When the caller's view has no sink of its own, a raw terminal sink (stdout/stderr writers, one per stream) now takes its place inside the record-log wrapper: the terminal shows the raw lines again while build.log keeps the full tee. A view that consumes lines itself (the live view on a tty) is wrapped exactly as before.
This commit is contained in:
@@ -1524,6 +1524,49 @@ impl LineSink for RecordLogSink {
|
||||
}
|
||||
}
|
||||
|
||||
/// A sink writing captured lines to two raw writers, one per stream:
|
||||
/// stdout lines to the first, stderr lines to the second.
|
||||
///
|
||||
/// This is the record-log view's stand-in for the subprocess-inherit
|
||||
/// fallback: with `--verbose` (or a piped stdout, where the live view
|
||||
/// disables itself) the caller's view is [`crate::report::Quiet`], whose
|
||||
/// sink is `None` — the runner would let the subprocess inherit the
|
||||
/// terminal — but the record-log wrapper always provides a sink, so
|
||||
/// the fallback is never reached anymore. Wrapping this sink in its
|
||||
/// place keeps the raw lines on the terminal while the record's
|
||||
/// build.log keeps the full tee.
|
||||
pub(crate) struct RawWriterSink {
|
||||
stdout: Mutex<Box<dyn Write + Send>>,
|
||||
stderr: Mutex<Box<dyn Write + Send>>,
|
||||
}
|
||||
|
||||
impl RawWriterSink {
|
||||
/// A sink over explicit writer pairs (tests capture into memory).
|
||||
pub(crate) fn new(stdout: Box<dyn Write + Send>, stderr: Box<dyn Write + Send>) -> Self {
|
||||
Self {
|
||||
stdout: Mutex::new(stdout),
|
||||
stderr: Mutex::new(stderr),
|
||||
}
|
||||
}
|
||||
|
||||
/// A sink over the real terminal: the process's stdout and stderr.
|
||||
pub(crate) fn terminal() -> Self {
|
||||
Self::new(Box::new(io::stdout()), Box::new(io::stderr()))
|
||||
}
|
||||
}
|
||||
|
||||
impl LineSink for RawWriterSink {
|
||||
fn line(&self, stream: Stream, line: &str) {
|
||||
let writer = match stream {
|
||||
Stream::Stdout => &self.stdout,
|
||||
Stream::Stderr => &self.stderr,
|
||||
};
|
||||
if let Ok(mut out) = writer.lock() {
|
||||
let _ = writeln!(out, "{line}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Host-tree snapshot and overlay upperdir sync
|
||||
//
|
||||
@@ -1854,6 +1897,34 @@ pub(crate) fn sync_upper_for_resume(session: &Session, host_parent: &Path) -> io
|
||||
pub(crate) mod record_fixtures {
|
||||
use super::*;
|
||||
|
||||
/// A writer copying everything it receives into a shared buffer:
|
||||
/// lets tests observe what a `Box<dyn Write + Send>` sink wrote.
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct SharedWriter(pub Arc<parking_lot::Mutex<Vec<u8>>>);
|
||||
|
||||
impl SharedWriter {
|
||||
/// A fresh empty capture buffer.
|
||||
pub(crate) fn new() -> Self {
|
||||
Self(Arc::new(parking_lot::Mutex::new(Vec::new())))
|
||||
}
|
||||
|
||||
/// What has been written so far.
|
||||
pub(crate) fn contents(&self) -> String {
|
||||
String::from_utf8_lossy(&self.0.lock()).into_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::io::Write for SharedWriter {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
self.0.lock().extend_from_slice(buf);
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test_identity() -> SessionIdentity {
|
||||
SessionIdentity {
|
||||
package: "pkh".to_string(),
|
||||
@@ -2739,6 +2810,33 @@ mod tests {
|
||||
assert_eq!(out.len(), 0);
|
||||
}
|
||||
|
||||
/// The raw writer sink routes each stream to its own writer,
|
||||
/// newline-terminated: this is what keeps --verbose (and piped
|
||||
/// runs) showing raw output under the record-log wrapper.
|
||||
#[test]
|
||||
fn raw_writer_sink_routes_streams_to_their_writers() {
|
||||
use record_fixtures::SharedWriter;
|
||||
|
||||
let stdout = SharedWriter::new();
|
||||
let stderr = SharedWriter::new();
|
||||
let sink = RawWriterSink::new(Box::new(stdout.clone()), Box::new(stderr.clone()));
|
||||
|
||||
sink.line(Stream::Stdout, "from stdout");
|
||||
sink.line(Stream::Stderr, "from stderr");
|
||||
sink.line(Stream::Stdout, "second line");
|
||||
|
||||
assert_eq!(
|
||||
stdout.contents(),
|
||||
"from stdout\nsecond line\n",
|
||||
"stdout lines land in order, newline-terminated"
|
||||
);
|
||||
assert_eq!(
|
||||
stderr.contents(),
|
||||
"from stderr\n",
|
||||
"stderr lines land on their own writer only"
|
||||
);
|
||||
}
|
||||
|
||||
/// Ages render in the coarse units the list promises.
|
||||
#[test]
|
||||
fn age_rendering() {
|
||||
|
||||
Reference in New Issue
Block a user