Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

check_diff function rewrite #6390

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
50 changes: 49 additions & 1 deletion check_diff/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions check_diff/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ clap = { version = "4.4.2", features = ["derive"] }
tracing = "0.1.37"
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
tempfile = "3"
walkdir = "2.5.0"
diffy = "0.4.0"
98 changes: 95 additions & 3 deletions check_diff/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use diffy;
use std::env;
use std::fmt::Debug;
use std::io;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::Utf8Error;
use tracing::info;
use walkdir::WalkDir;

pub enum CheckDiffError {
/// Git related errors
Expand All @@ -18,9 +21,18 @@ pub enum CheckDiffError {
FailedBinaryVersioning(PathBuf),
/// Error when obtaining cargo version
FailedCargoVersion(&'static str),
/// Error when trying to find rust files
FailedFindingRustFiles(&'static str),
FailedWritingToFile(&'static str),
IO(std::io::Error),
}

impl Debug for CheckDiffError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CheckDiffError").finish()
}
}
benluiwj marked this conversation as resolved.
Show resolved Hide resolved

impl From<io::Error> for CheckDiffError {
fn from(error: io::Error) -> Self {
CheckDiffError::IO(error)
Expand Down Expand Up @@ -54,17 +66,31 @@ impl From<io::Error> for GitError {
}

// will be used in future PRs, just added to make the compiler happy
#[allow(dead_code)]
pub struct CheckDiffRunners {
feature_runner: RustfmtRunner,
src_runner: RustfmtRunner,
pub feature_runner: RustfmtRunner,
pub src_runner: RustfmtRunner,
benluiwj marked this conversation as resolved.
Show resolved Hide resolved
}

pub struct RustfmtRunner {
ld_library_path: String,
binary_path: PathBuf,
}

impl CheckDiffRunners {
/// Creates a diff generated by running the source and feature binaries on the same file path
pub fn create_diff(
&self,
path: &Path,
additional_configs: &Option<Vec<String>>,
) -> Result<String, CheckDiffError> {
let code = std::fs::read_to_string(path)?;
let src_format = self.src_runner.format_code(&code, additional_configs)?;
let feature_format = self.feature_runner.format_code(&code, additional_configs)?;
let diff = diffy::create_patch(src_format.as_str(), feature_format.as_str());
Ok(format!("{diff}"))
benluiwj marked this conversation as resolved.
Show resolved Hide resolved
}
}

impl RustfmtRunner {
fn get_binary_version(&self) -> Result<String, CheckDiffError> {
let Ok(command) = Command::new(&self.binary_path)
Expand All @@ -80,6 +106,50 @@ impl RustfmtRunner {
let binary_version = std::str::from_utf8(&command.stdout)?.trim();
return Ok(binary_version.to_string());
}

// Run rusfmt with the --check flag to see if a diff is produced. Runs on the code specified
//
// Parameters:
// binary_path: Path to a rustfmt binary
// code: Code to run the binary on
// config: Any additional configuration options to pass to rustfmt
//
benluiwj marked this conversation as resolved.
Show resolved Hide resolved
fn format_code<'a>(
&self,
code: &'a str,
config: &Option<Vec<String>>,
) -> Result<String, CheckDiffError> {
let config_arg: String = match config {
Some(configs) => {
let mut result = String::new();
result.push(',');
for arg in configs.iter() {
result.push_str(arg.as_str());
result.push(',');
}
result.pop();
result
}
None => String::new(),
};
let config = format!(
"error_on_line_overflow=false,error_on_unformatted=false{}",
config_arg.as_str()
);

let output = Command::new(&self.binary_path)
.env("LD_LIBRARY_PATH", &self.ld_library_path)
.args([
"--unstable-features",
"--skip-children",
"--emit=stdout",
config.as_str(),
code,
])
.output()?;
benluiwj marked this conversation as resolved.
Show resolved Hide resolved

Ok(std::str::from_utf8(&output.stdout)?.to_string())
}
}

/// Clone a git repository
Expand Down Expand Up @@ -270,3 +340,25 @@ pub fn compile_rustfmt(
feature_runner,
});
}

pub fn check_diff(config: Option<Vec<String>>, runners: CheckDiffRunners) -> i32 {
let mut errors = 0;
for entry in WalkDir::new(".").into_iter().filter_map(|e| e.ok()) {
let path = entry.path();
if path.is_file() && path.extension().map_or(false, |ext| ext == "rs") {
benluiwj marked this conversation as resolved.
Show resolved Hide resolved
match runners.create_diff(path, &config) {
Ok(diff) => {
if !diff.is_empty() {
benluiwj marked this conversation as resolved.
Show resolved Hide resolved
eprint!("diff");
errors += 1;
}
}
Err(e) => {
eprintln!("Error creating diff for {:?}: {:?}", path.display(), e);
errors += 1;
}
}
}
}
return errors;
}
12 changes: 8 additions & 4 deletions check_diff/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use check_diff::compile_rustfmt;
use check_diff::{check_diff, compile_rustfmt, CheckDiffError};
use clap::Parser;
use tempfile::Builder;
use tracing::info;
Expand All @@ -19,17 +19,21 @@ struct CliInputs {
rustfmt_config: Option<Vec<String>>,
}

fn main() {
fn main() -> Result<(), CheckDiffError> {
tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_env("CHECK_DIFF_LOG"))
.init();
let args = CliInputs::parse();
let tmp_dir = Builder::new().tempdir_in("").unwrap();
info!("Created tmp_dir {:?}", tmp_dir);
let _ = compile_rustfmt(
let check_diff_runners = compile_rustfmt(
tmp_dir.path(),
args.remote_repo_url,
args.feature_branch,
args.commit_hash,
);
)?;

let _ = check_diff(args.rustfmt_config, check_diff_runners);

Ok(())
}
Loading