mirror of
https://github.com/Noratrieb/cargo-minimize.git
synced 2026-01-15 00:45:02 +01:00
add tracing
This commit is contained in:
parent
1cb5114557
commit
e1fd83b4d9
8 changed files with 264 additions and 33 deletions
78
src/build.rs
78
src/build.rs
|
|
@ -1,9 +1,9 @@
|
|||
use anyhow::{Context, Result};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use rustfix::diagnostics::Diagnostic;
|
||||
use serde::Deserialize;
|
||||
use std::{collections::HashSet, fmt::Display, path::PathBuf, process::Command, rc::Rc};
|
||||
|
||||
use crate::Options;
|
||||
use crate::{EnvVar, Options};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Build {
|
||||
|
|
@ -15,6 +15,7 @@ struct BuildInner {
|
|||
mode: BuildMode,
|
||||
input_path: PathBuf,
|
||||
no_verify: bool,
|
||||
env: Vec<EnvVar>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -38,11 +39,13 @@ impl Build {
|
|||
.map(|cmd| cmd.split_whitespace().map(ToString::to_string).collect()),
|
||||
}
|
||||
};
|
||||
|
||||
Self {
|
||||
inner: Rc::new(BuildInner {
|
||||
mode,
|
||||
input_path: options.path.clone(),
|
||||
no_verify: options.no_verify,
|
||||
env: options.env.clone(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
@ -52,10 +55,11 @@ impl Build {
|
|||
return Ok(BuildResult {
|
||||
reproduces_issue: false,
|
||||
no_verify: true,
|
||||
output: String::new(),
|
||||
});
|
||||
}
|
||||
|
||||
let reproduces_issue = match &self.inner.mode {
|
||||
let (reproduces_issue, output) = match &self.inner.mode {
|
||||
BuildMode::Cargo { args } => {
|
||||
let mut cmd = Command::new("cargo");
|
||||
cmd.arg("build");
|
||||
|
|
@ -64,33 +68,58 @@ impl Build {
|
|||
cmd.arg(arg);
|
||||
}
|
||||
|
||||
let output =
|
||||
String::from_utf8(cmd.output().context("spawning rustc process")?.stderr)
|
||||
.unwrap();
|
||||
for env in &self.inner.env {
|
||||
cmd.env(&env.key, &env.value);
|
||||
}
|
||||
|
||||
output.contains("internal compiler error")
|
||||
let outputs = cmd.output().context("spawning rustc process")?;
|
||||
|
||||
let output = String::from_utf8(outputs.stderr)?;
|
||||
|
||||
(
|
||||
outputs.status.code() == Some(101)
|
||||
|| output.contains("internal compiler error"),
|
||||
output,
|
||||
)
|
||||
}
|
||||
BuildMode::Script(script_path) => {
|
||||
let mut cmd = Command::new(script_path);
|
||||
|
||||
cmd.output().context("spawning script")?.status.success()
|
||||
for env in &self.inner.env {
|
||||
cmd.env(&env.key, &env.value);
|
||||
}
|
||||
|
||||
let outputs = cmd.output().context("spawning script")?;
|
||||
|
||||
let output = String::from_utf8(outputs.stderr)?;
|
||||
|
||||
(outputs.status.success(), output)
|
||||
}
|
||||
BuildMode::Rustc => {
|
||||
let mut cmd = Command::new("rustc");
|
||||
cmd.args(["--edition", "2018"]);
|
||||
cmd.args(["--edition", "2021"]);
|
||||
cmd.arg(&self.inner.input_path);
|
||||
|
||||
cmd.output()
|
||||
.context("spawning rustc process")?
|
||||
.status
|
||||
.code()
|
||||
== Some(101)
|
||||
for env in &self.inner.env {
|
||||
cmd.env(&env.key, &env.value);
|
||||
}
|
||||
|
||||
let outputs = cmd.output().context("spawning rustc process")?;
|
||||
|
||||
let output = String::from_utf8(outputs.stderr)?;
|
||||
|
||||
(
|
||||
outputs.status.code() == Some(101)
|
||||
|| output.contains("internal compiler error"),
|
||||
output,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
Ok(BuildResult {
|
||||
reproduces_issue,
|
||||
no_verify: self.inner.no_verify,
|
||||
output,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -104,6 +133,10 @@ impl Build {
|
|||
cmd.arg(arg);
|
||||
}
|
||||
|
||||
for env in &self.inner.env {
|
||||
cmd.env(&env.key, &env.value);
|
||||
}
|
||||
|
||||
let cmd_output = cmd.output()?;
|
||||
let output = String::from_utf8(cmd_output.stdout.clone())?;
|
||||
|
||||
|
|
@ -121,9 +154,13 @@ impl Build {
|
|||
}
|
||||
BuildMode::Rustc => {
|
||||
let mut cmd = std::process::Command::new("rustc");
|
||||
cmd.args(["--edition", "2018", "--error-format=json"]);
|
||||
cmd.args(["--edition", "2021", "--error-format=json"]);
|
||||
cmd.arg(&self.inner.input_path);
|
||||
|
||||
for env in &self.inner.env {
|
||||
cmd.env(&env.key, &env.value);
|
||||
}
|
||||
|
||||
let output = cmd.output()?.stderr;
|
||||
let output = String::from_utf8(output)?;
|
||||
|
||||
|
|
@ -153,9 +190,20 @@ impl Build {
|
|||
pub struct BuildResult {
|
||||
reproduces_issue: bool,
|
||||
no_verify: bool,
|
||||
output: String,
|
||||
}
|
||||
|
||||
impl BuildResult {
|
||||
pub fn require_reproduction(&self, build: &str) -> Result<()> {
|
||||
if !self.reproduces_issue() {
|
||||
bail!(
|
||||
"{build} build must reproduce issue. Output:\n{}",
|
||||
self.output
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn reproduces_issue(&self) -> bool {
|
||||
self.reproduces_issue || self.no_verify
|
||||
}
|
||||
|
|
|
|||
30
src/lib.rs
30
src/lib.rs
|
|
@ -1,4 +1,7 @@
|
|||
use std::path::PathBuf;
|
||||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
||||
use std::{path::PathBuf, str::FromStr};
|
||||
|
||||
mod build;
|
||||
mod everybody_loops;
|
||||
|
|
@ -31,10 +34,35 @@ pub struct Options {
|
|||
#[arg(long)]
|
||||
no_verify: bool,
|
||||
|
||||
#[arg(long)]
|
||||
env: Vec<EnvVar>,
|
||||
|
||||
#[arg(default_value = "src")]
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct EnvVar {
|
||||
key: String,
|
||||
value: String,
|
||||
}
|
||||
|
||||
impl FromStr for EnvVar {
|
||||
type Err = &'static str;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut split = s.split("=");
|
||||
let key = split
|
||||
.next()
|
||||
.ok_or("env var must have KEY=VALUE format")?
|
||||
.to_string();
|
||||
let value = split
|
||||
.next()
|
||||
.ok_or("env var must have KEY=VALUE format")?
|
||||
.to_string();
|
||||
Ok(Self { key, value })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn minimize() -> Result<()> {
|
||||
let Cargo::Minimize(options) = Cargo::parse();
|
||||
|
||||
|
|
|
|||
12
src/main.rs
12
src/main.rs
|
|
@ -1,6 +1,18 @@
|
|||
use anyhow::Result;
|
||||
use tracing::info;
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Registry};
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let registry = Registry::default().with(EnvFilter::from_default_env());
|
||||
|
||||
info!("Starting cargo-minimize");
|
||||
|
||||
let tree_layer = tracing_tree::HierarchicalLayer::new(2)
|
||||
.with_targets(true)
|
||||
.with_bracketed_fields(true);
|
||||
|
||||
registry.with(tree_layer).init();
|
||||
|
||||
cargo_minimize::minimize()?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
mod files;
|
||||
mod reaper;
|
||||
|
||||
use std::{borrow::Borrow, collections::HashSet, ffi::OsStr, mem, path::Path};
|
||||
use std::{borrow::Borrow, collections::HashSet, ffi::OsStr, fmt::Debug, mem, path::Path};
|
||||
|
||||
use anyhow::{ensure, Context, Result};
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
use crate::{build::Build, processor::files::Changes};
|
||||
|
||||
|
|
@ -27,6 +27,12 @@ pub trait Processor {
|
|||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
impl Debug for dyn Processor {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(self.name())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ProcessState {
|
||||
NoChange,
|
||||
|
|
@ -71,10 +77,7 @@ impl Minimizer {
|
|||
) -> Result<()> {
|
||||
let inital_build = self.build.build()?;
|
||||
println!("Initial build: {}", inital_build);
|
||||
ensure!(
|
||||
inital_build.reproduces_issue(),
|
||||
"Initial build must reproduce issue"
|
||||
);
|
||||
inital_build.require_reproduction("Initial")?;
|
||||
|
||||
for mut pass in passes {
|
||||
self.run_pass(&mut *pass)?;
|
||||
|
|
@ -89,7 +92,9 @@ impl Minimizer {
|
|||
let mut refresh_and_try_again = false;
|
||||
|
||||
loop {
|
||||
println!("Starting a round of {}", pass.name());
|
||||
let span = info_span!("Starting round of pass", name = pass.name());
|
||||
let _enter = span.enter();
|
||||
|
||||
let mut changes = Changes::default();
|
||||
|
||||
for file in &self.files {
|
||||
|
|
@ -176,7 +181,7 @@ impl Minimizer {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
struct AstPath(Vec<String>);
|
||||
|
||||
impl Borrow<[String]> for AstPath {
|
||||
|
|
@ -185,6 +190,12 @@ impl Borrow<[String]> for AstPath {
|
|||
}
|
||||
}
|
||||
|
||||
impl Debug for AstPath {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "AstPath({:?})", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PassController {
|
||||
state: PassControllerState,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use crate::build::Build;
|
|||
use super::{
|
||||
files::Changes, tracking, Minimizer, PassController, ProcessState, Processor, SourceFile,
|
||||
};
|
||||
use anyhow::{ensure, Context, Result};
|
||||
use anyhow::{Context, Result};
|
||||
use proc_macro2::Span;
|
||||
use quote::ToTokens;
|
||||
use rustfix::{diagnostics::Diagnostic, Suggestion};
|
||||
|
|
@ -24,10 +24,8 @@ impl Minimizer {
|
|||
pub fn delete_dead_code(&mut self) -> Result<()> {
|
||||
let inital_build = self.build.build()?;
|
||||
println!("Before reaper: {}", inital_build);
|
||||
ensure!(
|
||||
inital_build.reproduces_issue(),
|
||||
"Initial build must reproduce issue"
|
||||
);
|
||||
|
||||
inital_build.require_reproduction("Initial")?;
|
||||
|
||||
let (diags, suggestions) = self
|
||||
.build
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue