Skip to content

Commit

Permalink
Merge branch 'main' into new_csv_tokenizer
Browse files Browse the repository at this point in the history
# Conflicts:
#	README.md
#	src/report/mod.rs
  • Loading branch information
Christopher Regali committed Jan 23, 2023
2 parents e50e24a + 313c60f commit c0da15c
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 26 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,15 @@ Currently we only support SHA-256 but more checks can be added easily.
- Deletion of columns will no longer really delete them but replace every value with "DELETED"
- Expose config struct to library API
- Fixed a bug regarding wrong handling of multiple empty lines
- Reworked CSV reporting to have an interleaved and more compact view
- Made header-extraction fallible but uncritical - can now always be enabled
- Reworked CSV reporting to have an interleaved and more compact view
- Display the relative path of compared files instead of file name in the report index.html
- Made header-extraction fallible but uncritical - can now always be enabled
- Wrote a completely new csv parser:
- Respects escaping with '\'
- Allows string-literals containing unescaped field separators (field1, "field2, but as literal", field3)
- Allows multi-line string literals
- Multi quote escapes work
- CSVs with non-rectangular format will now fail

### 0.1.4
- Add multiple includes and excludes - warning, this will break yamls from 0.1.3 and earlier
Expand Down
122 changes: 100 additions & 22 deletions src/report/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ mod template;
use crate::csv::{DiffType, Position, Table};
use serde::Serialize;
use std::borrow::Cow;
use std::ffi::OsStr;
use std::fs;
use std::fs::File;
use std::iter::zip;
use std::path::{Path, PathBuf};
use tera::{Context, Tera};
use thiserror::Error;
use tracing::{debug, info, span};
use tracing::{debug, error, info, span};
use vg_errortools::{fat_io_wrap_std, FatIOError};

#[derive(Error, Debug)]
Expand All @@ -25,8 +27,7 @@ pub enum Error {

#[derive(Serialize, Debug)]
pub struct FileCompareResult {
pub nominal: String,
pub actual: String,
pub compared_file_name: String,
pub is_error: bool,
pub detail_path: Option<PathBuf>,
}
Expand All @@ -51,17 +52,6 @@ pub struct CSVReportRow {
pub has_error: bool,
}

fn get_file_name(path: &Path) -> Result<Cow<str>, Error> {
path.file_name()
.map(|f| f.to_string_lossy())
.ok_or_else(|| {
Error::FileNameParsing(format!(
"Could not extract filename from {}",
path.to_string_lossy()
))
})
}

pub fn create_sub_folder(
rule_name: &str,
nominal: impl AsRef<Path>,
Expand Down Expand Up @@ -94,9 +84,11 @@ pub fn write_html_detail(
diffs: &[String],
rule_name: &str,
) -> Result<FileCompareResult, Error> {
let compared_file_name = get_relative_path(actual.as_ref(), nominal.as_ref())
.to_string_lossy()
.to_string();
let mut result = FileCompareResult {
nominal: get_file_name(nominal.as_ref())?.to_string(),
actual: get_file_name(actual.as_ref())?.to_string(),
compared_file_name,
is_error: false,
detail_path: None,
};
Expand Down Expand Up @@ -141,9 +133,11 @@ pub(crate) fn write_csv_detail(
diffs: &[DiffType],
rule_name: &str,
) -> Result<FileCompareResult, Error> {
let compared_file_name = get_relative_path(actual.as_ref(), nominal.as_ref())
.to_string_lossy()
.to_string();
let mut result = FileCompareResult {
nominal: get_file_name(nominal.as_ref())?.to_string(),
actual: get_file_name(actual.as_ref())?.to_string(),
compared_file_name,
is_error: false,
detail_path: None,
};
Expand Down Expand Up @@ -274,9 +268,11 @@ pub fn write_image_detail(
diffs: &[String],
rule_name: &str,
) -> Result<FileCompareResult, Error> {
let compared_file_name = get_relative_path(actual.as_ref(), nominal.as_ref())
.to_string_lossy()
.to_string();
let mut result = FileCompareResult {
nominal: get_file_name(nominal.as_ref())?.to_string(),
actual: get_file_name(actual.as_ref())?.to_string(),
compared_file_name,
is_error: false,
detail_path: None,
};
Expand All @@ -299,6 +295,17 @@ pub fn write_image_detail(
ctx.insert("actual", &actual.as_ref().to_string_lossy());
ctx.insert("nominal", &nominal.as_ref().to_string_lossy());

fn get_file_name(path: &Path) -> Result<Cow<str>, Error> {
path.file_name()
.map(|f| f.to_string_lossy())
.ok_or_else(|| {
Error::FileNameParsing(format!(
"Could not extract filename from {}",
path.to_string_lossy()
))
})
}

let actual_image = format!("actual_image_{}", get_file_name(actual.as_ref())?);
let nominal_image = format!("nominal_image_.{}", get_file_name(nominal.as_ref())?);

Expand Down Expand Up @@ -336,9 +343,12 @@ pub fn write_pdf_detail(
diffs: &[(usize, String)],
rule_name: &str,
) -> Result<FileCompareResult, Error> {
let compared_file_name = get_relative_path(actual.as_ref(), nominal.as_ref())
.to_string_lossy()
.to_string();

let mut result = FileCompareResult {
nominal: get_file_name(nominal.as_ref())?.to_string(),
actual: get_file_name(actual.as_ref())?.to_string(),
compared_file_name,
is_error: false,
detail_path: None,
};
Expand Down Expand Up @@ -474,3 +484,71 @@ pub(crate) fn write_index(
debug!("Report.html created");
Ok(())
}

///Find the relative path between two files
/// compare both files n reversed order (from bottom to top), and returns only the part which are the same on both files
fn get_relative_path(actual_path: impl AsRef<Path>, nominal_path: impl AsRef<Path>) -> PathBuf {
let actual_iter = actual_path.as_ref().iter().rev();
let nominal_iter = nominal_path.as_ref().iter().rev();
let zipped_path = zip(nominal_iter, actual_iter);

let mut is_the_same = true;
let mut paths: Vec<&OsStr> = Vec::new();
for (n, a) in zipped_path {
if n != a {
is_the_same = false;
}

if is_the_same {
paths.push(n);
}
}

paths.reverse();

PathBuf::from_iter(paths)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_get_relative_path() {
let result = get_relative_path(
"tests/integ/data/display_of_status_message_in_cm_tables/expected/Volume1.csv",
"tests/integ/data/display_of_status_message_in_cm_tables/actual/Volume1.csv",
);
assert_eq!(PathBuf::from("Volume1.csv"), result);

let result = get_relative_path(
"tests/act/something/csv/test.csv",
"tests/exp/something/csv/test.csv",
);
assert_eq!(PathBuf::from("something/csv/test.csv"), result);

let result = get_relative_path(
"tests/integ/data/display_of_status_message_in_cm_tables/expected/Volume1.csv",
"C:/Users/someuser/Documents/git/havocompare/tests/actual/Volume1.csv",
);
assert_eq!(PathBuf::from("Volume1.csv"), result);

let result = get_relative_path(
"tests/actual/csv/Volume1.csv",
"tests/integ/data/display_of_status_message_in_cm_tables/expected/csv/Volume1.csv",
);
assert_eq!(PathBuf::from("csv/Volume1.csv"), result);

let result = get_relative_path(
"csv/Volume1.csv",
"tests/integ/data/display_of_status_message_in_cm_tables/expected/csv/Volume1.csv",
);
assert_eq!(PathBuf::from("csv/Volume1.csv"), result);

let result = get_relative_path(
"csv/Volume1.csv",
"tests/integ/data/display_of_status_message_in_cm_tables/expected/Volume1.csv",
);
assert_eq!(PathBuf::from("Volume1.csv"), result);
}
}
4 changes: 2 additions & 2 deletions src/report/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ pub const INDEX_TEMPLATE: &str = r###"
<tr {% if file.is_error %} class="error" {% endif %}>
<td>
{% if file.detail_path %}
<a href="./{{ rule_report.rule.name }}/{{ file.detail_path }}/{{ detail_filename }}">{{ file.actual }}</a>
<a href="./{{ rule_report.rule.name }}/{{ file.detail_path }}/{{ detail_filename }}">{{ file.compared_file_name }}</a>
{% else %}
{{ file.actual }}
{{ file.compared_file_name }}
{% endif %}
</td>
<td>{% if file.is_error %} <span>&#10006;</span> {% else %} <span style="color:green;">&#10004;</span> {% endif %}</td>
Expand Down

0 comments on commit c0da15c

Please sign in to comment.