logfmt: collapse the rootless chown EPERM flood into one digest line
A rules chown failing for the unprivileged build user is expected and harmless (see the revert of the build-step fakeroot wrap), but a sysroot tree can print thousands of 'chown: changing ownership of ...: Operation not permitted' lines. MakeClassifier now shows one warning digest for the flood and hides the rest; every other line, make errors included, keeps its classification. The full tee in the record's build.log is untouched.
This commit is contained in:
+73
-2
@@ -227,9 +227,17 @@ impl Classifier for QuiltClassifier {
|
|||||||
///
|
///
|
||||||
/// Detects `[ 42%]`-style progress markers, hides directory enter/leave
|
/// Detects `[ 42%]`-style progress markers, hides directory enter/leave
|
||||||
/// noise, and shows compile/link/dh lines as well as kbuild status-tag
|
/// noise, and shows compile/link/dh lines as well as kbuild status-tag
|
||||||
/// lines and warnings.
|
/// lines and warnings. Collapses the per-file `chown: ... Operation not
|
||||||
|
/// permitted` flood of a rootless build into one digest line: a rules
|
||||||
|
/// chown failing for the unprivileged build user is expected and harmless
|
||||||
|
/// (the .deb is assembled in the binary step's fakeroot session, which
|
||||||
|
/// records root ownership anyway), but a sysroot can emit thousands of
|
||||||
|
/// lines.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct MakeClassifier {}
|
pub struct MakeClassifier {
|
||||||
|
/// How many chown-EPERM lines were collapsed so far.
|
||||||
|
suppressed_chown: usize,
|
||||||
|
}
|
||||||
|
|
||||||
impl MakeClassifier {
|
impl MakeClassifier {
|
||||||
/// Create a new classifier
|
/// Create a new classifier
|
||||||
@@ -255,6 +263,11 @@ impl Classifier for MakeClassifier {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
static CHOWN_EPERM_RE: LazyLock<Regex> = LazyLock::new(|| {
|
||||||
|
Regex::new(r"^chown: (changing ownership|cannot read directory|cannot operate on)")
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(caps) = percent_re.captures(line) {
|
if let Some(caps) = percent_re.captures(line) {
|
||||||
let pct: u64 = caps[1].parse().unwrap_or(0);
|
let pct: u64 = caps[1].parse().unwrap_or(0);
|
||||||
return vec![
|
return vec![
|
||||||
@@ -266,6 +279,18 @@ impl Classifier for MakeClassifier {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if CHOWN_EPERM_RE.is_match(line) {
|
||||||
|
self.suppressed_chown += 1;
|
||||||
|
return if self.suppressed_chown == 1 {
|
||||||
|
vec![Action::Warning(truncate(
|
||||||
|
"chown: ownership changes skipped by the unprivileged build user \
|
||||||
|
(harmless for the .deb; further messages collapsed)",
|
||||||
|
))]
|
||||||
|
} else {
|
||||||
|
vec![Action::Hidden]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if line.contains("error:")
|
if line.contains("error:")
|
||||||
|| line.contains("Error ")
|
|| line.contains("Error ")
|
||||||
|| line.contains("*** [")
|
|| line.contains("*** [")
|
||||||
@@ -538,6 +563,52 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A rootless build's per-file chown failures collapse into one
|
||||||
|
/// digest warning; every other line keeps its normal classification.
|
||||||
|
#[test]
|
||||||
|
fn test_make_collapses_chown_eperm_flood() {
|
||||||
|
let mut c = MakeClassifier::new();
|
||||||
|
let first = "chown: changing ownership of \
|
||||||
|
'/tmp/pkh-build/k3/demos/sysroot/usr/share/zoneinfo/Asia/Sao_Paulo': \
|
||||||
|
Operation not permitted";
|
||||||
|
assert_eq!(
|
||||||
|
feed_one(&mut c, first),
|
||||||
|
vec![Action::Warning(
|
||||||
|
"chown: ownership changes skipped by the unprivileged build user \
|
||||||
|
(harmless for the .deb; further messages collapsed)"
|
||||||
|
.to_string()
|
||||||
|
)]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
feed_one(
|
||||||
|
&mut c,
|
||||||
|
"chown: changing ownership of \
|
||||||
|
'/tmp/pkh-build/k3/demos/sysroot/usr/share/zoneinfo/Asia/Tokyo': \
|
||||||
|
Operation not permitted"
|
||||||
|
),
|
||||||
|
vec![Action::Hidden]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
feed_one(
|
||||||
|
&mut c,
|
||||||
|
"chown: cannot read directory '/tmp/pkh-build/k3/demos': Permission denied"
|
||||||
|
),
|
||||||
|
vec![Action::Hidden]
|
||||||
|
);
|
||||||
|
// A non-chown line keeps its own classification after the flood.
|
||||||
|
assert_eq!(
|
||||||
|
feed_one(&mut c, " CC [M] drivers/net/foo.o"),
|
||||||
|
vec![Action::Shown(" CC [M] drivers/net/foo.o".to_string())]
|
||||||
|
);
|
||||||
|
// The digest must not swallow real make errors.
|
||||||
|
assert_eq!(
|
||||||
|
feed_one(&mut c, "make[1]: *** [Makefile:531: all] Error 2"),
|
||||||
|
vec![Action::Error(
|
||||||
|
"make[1]: *** [Makefile:531: all] Error 2".to_string()
|
||||||
|
)]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_make_shows_kbuild_status_tags() {
|
fn test_make_shows_kbuild_status_tags() {
|
||||||
let mut c = MakeClassifier::new();
|
let mut c = MakeClassifier::new();
|
||||||
|
|||||||
Reference in New Issue
Block a user