From 3b3fb81bd4b9c9027d3d5e5d46d6c4aaae2d8dac Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 18:43:44 +0100 Subject: [PATCH 01/20] actions: Update actions and configuration --- .github/workflows/json-structural-diff.yml | 91 ++++++++++------------ 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/.github/workflows/json-structural-diff.yml b/.github/workflows/json-structural-diff.yml index ea31545..65a6e85 100644 --- a/.github/workflows/json-structural-diff.yml +++ b/.github/workflows/json-structural-diff.yml @@ -8,67 +8,66 @@ on: branches: - master +env: + GRCOV_VERSION: "0.8.20" + jobs: clippy-rustfmt: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install stable - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: - profile: minimal - toolchain: stable - override: true - components: clippy, rustfmt + components: rustfmt, clippy - name: Run rustfmt - uses: actions-rs/cargo@v1 - with: - command: fmt - args: -- --check --verbose + run: + cargo fmt --all -- --check --verbose - name: Run cargo clippy - uses: actions-rs/clippy-check@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --all-features -- -D warnings + run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic code-coverage: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - override: true - - - uses: actions-rs/cargo@v1 - with: - command: test - args: --all-features --no-fail-fast - env: - CARGO_INCREMENTAL: '0' - RUSTFLAGS: > - -Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code - -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests - RUSTDOCFLAGS: > - -Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code - -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests - - - id: coverage - uses: actions-rs/grcov@v0.1 - - - name: Coveralls upload - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: ${{ steps.coverage.outputs.report }} + + - uses: actions/checkout@v4 + + - name: Install Rust stable + uses: dtolnay/rust-toolchain@stable + with: + components: llvm-tools-preview + + - name: Install grcov + env: + GRCOV_LINK: https://github.com/mozilla/grcov/releases/download + run: | + curl -L "$GRCOV_LINK/v$GRCOV_VERSION/grcov-x86_64-unknown-linux-musl.tar.bz2" | + tar xj -C $HOME/.cargo/bin + + - name: Run tests + env: + RUSTFLAGS: "-Cinstrument-coverage" + LLVM_PROFILE_FILE: "json-structural-diff-%p-%m.profraw" + run: | + cargo test --verbose + + - name: Get coverage data for codecov + run: | + grcov . --binary-path ./target/debug/ -s . -t lcov --branch \ + --ignore-not-existing --ignore "/*" --ignore "../*" -o lcov.info + + - name: Codecov upload + uses: codecov/codecov-action@v4 + with: + files: lcov.info + token: ${{ secrets.CODECOV_TOKEN }} tests: @@ -79,14 +78,10 @@ jobs: runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install stable - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true + uses: dtolnay/rust-toolchain@stable - name: Build run: | From 93120ec5f575702c58a54fc763b7422cdd7dd8c9 Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 18:43:59 +0100 Subject: [PATCH 02/20] misc: Update readme --- README.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 273d5cc..85f712a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # A Rust JSON structural diff -[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) -[![Actions Status](https://github.com/Luni-4/json-structural-diff/workflows/json-structural-diff/badge.svg)](https://github.com/Luni-4/json-structural-diff/actions) -[![Coverage Status](https://coveralls.io/repos/github/Luni-4/json-structural-diff/badge.svg?branch=master)](https://coveralls.io/github/Luni-4/json-structural-diff?branch=master) +[![Actions Status][actions badge]][actions] +[![CodeCov][codecov badge]][codecov] +[![LICENSE][license badge]][license] A pure-Rust JSON structural diff based on [this](https://github.com/andreyvit/json-diff) implementation. @@ -27,3 +27,13 @@ to the commands above. ## License Released under the [MIT License](LICENSE). + + +[actions]: https://github.com/Luni-4/json-structural-diff/actions +[codecov]: https://codecov.io/gh/Luni-4/json-structural-diff +[license]: LICENSE + + +[actions badge]: https://github.com/Luni-4/json-structural-diff/workflows/json-structural-diff/badge.svg +[codecov badge]: https://codecov.io/gh/Luni-4/json-structural-diff/branch/master/graph/badge.svg +[license badge]: https://img.shields.io/badge/license-MIT-blue.svg From 4c7d472834a22648c07f01de0498a04c8bb18fe3 Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 18:47:28 +0100 Subject: [PATCH 03/20] misc: Apply clippy suggestions --- src/colorize.rs | 26 ++++++++++++-------------- src/diff.rs | 24 +++++++++--------------- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/src/colorize.rs b/src/colorize.rs index a3455a9..afd1372 100644 --- a/src/colorize.rs +++ b/src/colorize.rs @@ -6,11 +6,11 @@ where F: FnMut(&str, &str), { let prefix = if let Some(key) = key { - format!("{}: ", key) + format!("{key}: ") } else { - "".to_owned() + String::new() }; - let subindent = &format!("{} ", indent); + let subindent = &format!("{indent} "); match diff { Value::Object(obj) => { @@ -20,7 +20,7 @@ where subcolorize(key, old, output, "-", indent); subcolorize(key, new, output, "+", indent); } else { - output(color, &format!("{}{}{{", indent, prefix)); + output(color, &format!("{indent}{prefix}{{")); let re_delete = Regex::new(r"^(.*)__deleted$").unwrap(); let re_added = Regex::new(r"^(.*)__added$").unwrap(); for (subkey, subvalue) in obj { @@ -44,13 +44,13 @@ where ); continue; } - subcolorize(Some(&subkey), subvalue, output, color, subindent); + subcolorize(Some(subkey), subvalue, output, color, subindent); } - output(color, &format!("{}}}", indent)); + output(color, &format!("{indent}}}")); } } Value::Array(array) => { - output(color, &format!("{}{}[", indent, prefix)); + output(color, &format!("{indent}{prefix}[")); let mut looks_like_diff = true; for item in array { @@ -76,11 +76,9 @@ where let op = subitem[0].as_str().unwrap(); let subvalue = &subitem.get(1); if op == " " && subvalue.is_none() { - output(" ", &format!("{}...", subindent)); + output(" ", &format!("{subindent}...")); } else { - if !([" ", "-", "+", "~"].contains(&op)) { - panic!("Unexpected op '{}'", op); - } + assert!(([" ", "-", "+", "~"].contains(&op)), "Unexpected op '{}'", op); let subvalue = subvalue.unwrap(); let color = if op == "~" { " " } else { op }; subcolorize(None, subvalue, output, color, subindent); @@ -93,7 +91,7 @@ where } } - output(color, &format!("{}]", indent)); + output(color, &format!("{indent}]")); } _ => output(color, &(indent.to_owned() + &prefix + &diff.to_string())), } @@ -102,11 +100,11 @@ where /// Returns the JSON structural difference formatted as a `Vec`. /// /// If `None`, there is no JSON structural difference to be formatted. -pub fn colorize_to_array(diff: &Value) -> Vec { +#[must_use] pub fn colorize_to_array(diff: &Value) -> Vec { let mut output: Vec = Vec::new(); let mut output_func = |color: &str, line: &str| { - output.push(format!("{}{}", color, line)); + output.push(format!("{color}{line}")); }; subcolorize(None, diff, &mut output_func, " ", ""); diff --git a/src/diff.rs b/src/diff.rs index 2efaf0e..77057d6 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -35,19 +35,15 @@ impl BestMatch { impl JsonDiff { /// Finds the JSON structural difference of two JSON files. - pub fn diff(json1: &Value, json2: &Value, keys_only: bool) -> Self { + #[must_use] pub fn diff(json1: &Value, json2: &Value, keys_only: bool) -> Self { Self::diff_with_score(json1, json2, keys_only) } /// Finds the JSON structural difference of two JSON files and /// returns it as a formatted string. - pub fn diff_string(json1: &Value, json2: &Value, keys_only: bool) -> Option { + #[must_use] pub fn diff_string(json1: &Value, json2: &Value, keys_only: bool) -> Option { let Self { score: _, diff } = Self::diff(json1, json2, keys_only); - if let Some(value) = diff { - Some(colorize_to_array(&value).join("\n") + "\n") - } else { - None - } + diff.map(|value| colorize_to_array(&value).join("\n") + "\n") } fn object_diff(obj1: &Map, obj2: &Map, keys_only: bool) -> Self { @@ -56,7 +52,7 @@ impl JsonDiff { for (key, value1) in obj1 { if !obj2.contains_key(key) { - let key_deleted = format!("{}__deleted", key); + let key_deleted = format!("{key}__deleted"); result.insert(key_deleted, value1.clone()); score -= 30.; } @@ -64,7 +60,7 @@ impl JsonDiff { for (key, value2) in obj2 { if !obj1.contains_key(key) { - let key_added = format!("{}__added", key); + let key_added = format!("{key}__added"); result.insert(key_added, value2.clone()); score -= 30.; } @@ -76,11 +72,11 @@ impl JsonDiff { let Self { score: subscore, diff: change, - } = Self::diff_with_score(&value1, &value2, keys_only); + } = Self::diff_with_score(value1, value2, keys_only); if let Some(change) = change { result.insert(key.clone(), change); } - score += ((subscore / 5.).max(-10.)).min(20.); + score += (subscore / 5.).clamp(-10., 20.); } } @@ -117,7 +113,7 @@ impl JsonDiff { for (match_index, (key, candidate)) in fuzzy_originals.into_iter().enumerate() { if key != "__next" { - let index_distance = (match_index as isize - index as isize).abs() as usize; + let index_distance = (match_index as isize - index as isize).unsigned_abs(); if Self::check_type(item, candidate) { let Self { score, diff: _ } = Self::diff(item, candidate, false); if best_match.as_ref().map_or(true, |v| score > v.score) @@ -232,12 +228,10 @@ impl JsonDiff { "equal" => { for key in seq1.iter().take(opcode.first_end).skip(opcode.first_start) { let is_scalarized1 = Self::is_scalarized(key, &originals1); - if is_scalarized1 && !(Self::is_scalarized(key, &originals2)) { - panic!( + assert!(!(is_scalarized1 && !(Self::is_scalarized(key, &originals2))), "Internal bug: the items associated to the key {} are different in the two dictionaries", key ); - } if is_scalarized1 { let item1 = Self::descalarize(key, &scalar_values1, &originals1); let item2 = Self::descalarize(key, &scalar_values2, &originals2); From b5e352a92ead43676f7847be0f95df50b2b8099b Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 18:54:44 +0100 Subject: [PATCH 04/20] misc: Apply clippy suggestions --- src/colorize.rs | 11 ++++++++-- src/diff.rs | 57 +++++++++++++++++++++++++------------------------ 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/src/colorize.rs b/src/colorize.rs index afd1372..614d01c 100644 --- a/src/colorize.rs +++ b/src/colorize.rs @@ -78,7 +78,11 @@ where if op == " " && subvalue.is_none() { output(" ", &format!("{subindent}...")); } else { - assert!(([" ", "-", "+", "~"].contains(&op)), "Unexpected op '{}'", op); + assert!( + ([" ", "-", "+", "~"].contains(&op)), + "Unexpected op '{}'", + op + ); let subvalue = subvalue.unwrap(); let color = if op == "~" { " " } else { op }; subcolorize(None, subvalue, output, color, subindent); @@ -100,7 +104,9 @@ where /// Returns the JSON structural difference formatted as a `Vec`. /// /// If `None`, there is no JSON structural difference to be formatted. -#[must_use] pub fn colorize_to_array(diff: &Value) -> Vec { +#[must_use] +#[allow(clippy::module_name_repetitions)] +pub fn colorize_to_array(diff: &Value) -> Vec { let mut output: Vec = Vec::new(); let mut output_func = |color: &str, line: &str| { @@ -116,6 +122,7 @@ where /// /// If `None`, there is no JSON structural difference to be formatted. #[cfg(feature = "colorize")] +#[allow(clippy::module_name_repetitions)] pub fn colorize(diff: &Value, is_color: bool) -> String { use console::Style; diff --git a/src/diff.rs b/src/diff.rs index 77057d6..777ac6c 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -5,6 +5,7 @@ use crate::colorize::colorize_to_array; /// Auxiliary structure to encapsulate data about the structural difference /// of two JSON files. +#[allow(clippy::module_name_repetitions)] pub struct JsonDiff { /// Quantifies the difference between two JSON files. /// @@ -35,13 +36,15 @@ impl BestMatch { impl JsonDiff { /// Finds the JSON structural difference of two JSON files. - #[must_use] pub fn diff(json1: &Value, json2: &Value, keys_only: bool) -> Self { + #[must_use] + pub fn diff(json1: &Value, json2: &Value, keys_only: bool) -> Self { Self::diff_with_score(json1, json2, keys_only) } /// Finds the JSON structural difference of two JSON files and /// returns it as a formatted string. - #[must_use] pub fn diff_string(json1: &Value, json2: &Value, keys_only: bool) -> Option { + #[must_use] + pub fn diff_string(json1: &Value, json2: &Value, keys_only: bool) -> Option { let Self { score: _, diff } = Self::diff(json1, json2, keys_only); diff.map(|value| colorize_to_array(&value).join("\n") + "\n") } @@ -81,6 +84,7 @@ impl JsonDiff { } if result.is_empty() { + #[allow(clippy::cast_precision_loss)] Self { score: 100. * (obj1.len() as f64).max(0.5), diff: None, @@ -94,7 +98,6 @@ impl JsonDiff { } } - #[inline(always)] fn check_type(item1: &Value, item2: &Value) -> bool { item1.is_null() == item2.is_null() || item1.is_boolean() == item2.is_boolean() @@ -113,7 +116,7 @@ impl JsonDiff { for (match_index, (key, candidate)) in fuzzy_originals.into_iter().enumerate() { if key != "__next" { - let index_distance = (match_index as isize - index as isize).unsigned_abs(); + let index_distance = (match_index).wrapping_sub(index); if Self::check_type(item, candidate) { let Self { score, diff: _ } = Self::diff(item, candidate, false); if best_match.as_ref().map_or(true, |v| score > v.score) @@ -173,17 +176,14 @@ impl JsonDiff { output_array } - #[inline(always)] fn is_scalarized(key: &str, originals: &Map) -> bool { originals.contains_key(key) } - #[inline(always)] fn get_scalar(key: &str, scalar_values: &Map) -> Value { scalar_values.get(key).unwrap().clone() } - #[inline(always)] fn descalarize( key: &str, scalar_values: &Map, @@ -196,6 +196,7 @@ impl JsonDiff { } } + #[allow(clippy::too_many_lines)] fn array_diff(array1: &[Value], array2: &[Value], keys_only: bool) -> Self { let mut originals1 = Map::new(); let mut scalar_values1 = Map::new(); @@ -228,7 +229,7 @@ impl JsonDiff { "equal" => { for key in seq1.iter().take(opcode.first_end).skip(opcode.first_start) { let is_scalarized1 = Self::is_scalarized(key, &originals1); - assert!(!(is_scalarized1 && !(Self::is_scalarized(key, &originals2))), + assert!(!is_scalarized1 || (Self::is_scalarized(key, &originals2)), "Internal bug: the items associated to the key {} are different in the two dictionaries", key ); @@ -275,26 +276,7 @@ impl JsonDiff { } } "replace" => { - if !keys_only { - for key in seq1.iter().take(opcode.first_end).skip(opcode.first_start) { - result.push(json!([ - json!('-'), - Self::descalarize(key, &scalar_values1, &originals1) - ])); - score -= 5.; - } - for key in seq2 - .iter() - .take(opcode.second_end) - .skip(opcode.second_start) - { - result.push(json!([ - json!('+'), - Self::descalarize(key, &scalar_values2, &originals2) - ])); - score -= 5.; - } - } else { + if keys_only { for (key1, key2) in seq1 .iter() .take(opcode.first_end) @@ -322,6 +304,25 @@ impl JsonDiff { result.push(json!(' ')); } } + } else { + for key in seq1.iter().take(opcode.first_end).skip(opcode.first_start) { + result.push(json!([ + json!('-'), + Self::descalarize(key, &scalar_values1, &originals1) + ])); + score -= 5.; + } + for key in seq2 + .iter() + .take(opcode.second_end) + .skip(opcode.second_start) + { + result.push(json!([ + json!('+'), + Self::descalarize(key, &scalar_values2, &originals2) + ])); + score -= 5.; + } } } _ => all_equal = true, From 21cb39d162cb9914d39fcbe1152f5640d87113cf Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 19:30:30 +0100 Subject: [PATCH 05/20] misc: Update Rust edition --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b8c0db8..3f5be69 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ description = "A Rust JSON structural diff library" repository = "https://github.com/Luni-4/json-structural-diff" keywords = ["json-structural-diff", "json-diff"] license = "MIT" -edition = "2018" +edition = "2021" [features] colorize = ["console"] From 9e01547445b9ebb826e647ad2af15b92aba11f51 Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 19:30:58 +0100 Subject: [PATCH 06/20] misc: Apply clippy suggestions --- src/colorize.rs | 3 +-- src/diff.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/colorize.rs b/src/colorize.rs index 614d01c..7fee3b0 100644 --- a/src/colorize.rs +++ b/src/colorize.rs @@ -80,8 +80,7 @@ where } else { assert!( ([" ", "-", "+", "~"].contains(&op)), - "Unexpected op '{}'", - op + "Unexpected op '{op}'" ); let subvalue = subvalue.unwrap(); let color = if op == "~" { " " } else { op }; diff --git a/src/diff.rs b/src/diff.rs index 777ac6c..381de40 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -230,8 +230,7 @@ impl JsonDiff { for key in seq1.iter().take(opcode.first_end).skip(opcode.first_start) { let is_scalarized1 = Self::is_scalarized(key, &originals1); assert!(!is_scalarized1 || (Self::is_scalarized(key, &originals2)), - "Internal bug: the items associated to the key {} are different in the two dictionaries", - key + "Internal bug: the items associated to the key {key} are different in the two dictionaries" ); if is_scalarized1 { let item1 = Self::descalarize(key, &scalar_values1, &originals1); From 8eeb7424fa8e2e60ac1edaf69d8bf82562fc067f Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 19:32:06 +0100 Subject: [PATCH 07/20] misc: Format code --- src/colorize.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/colorize.rs b/src/colorize.rs index 7fee3b0..4b27f77 100644 --- a/src/colorize.rs +++ b/src/colorize.rs @@ -78,10 +78,7 @@ where if op == " " && subvalue.is_none() { output(" ", &format!("{subindent}...")); } else { - assert!( - ([" ", "-", "+", "~"].contains(&op)), - "Unexpected op '{op}'" - ); + assert!(([" ", "-", "+", "~"].contains(&op)), "Unexpected op '{op}'"); let subvalue = subvalue.unwrap(); let color = if op == "~" { " " } else { op }; subcolorize(None, subvalue, output, color, subindent); From f18fc5fe4368de1f4dcaeecf39399862d2d93ee0 Mon Sep 17 00:00:00 2001 From: Luper Rouch Date: Mon, 9 Dec 2024 17:58:38 +0100 Subject: [PATCH 08/20] Update console This fixes build errors on wasm targets: error[E0659]: `wants_emoji` is ambiguous --> /home/flupke/.cargo/registry/src/index.crates.io-6f17d22bba15001f/console-0.13.0/src/utils.rs:7:19 | 7 | use crate::term::{wants_emoji, Term}; | ^^^^^^^^^^^ ambiguous name | = note: ambiguous because of multiple glob imports of a name in the same module note: `wants_emoji` could refer to the function imported here --> /home/flupke/.cargo/registry/src/index.crates.io-6f17d22bba15001f/console-0.13.0/src/term.rs:560:9 | 560 | pub use crate::unix_term::*; | ^^^^^^^^^^^^^^^^^^^ = help: consider adding an explicit import of `wants_emoji` to disambiguate note: `wants_emoji` could also refer to the function imported here --> /home/flupke/.cargo/registry/src/index.crates.io-6f17d22bba15001f/console-0.13.0/src/term.rs:562:9 | 562 | pub use crate::wasm_term::*; | ^^^^^^^^^^^^^^^^^^^ = help: consider adding an explicit import of `wants_emoji` to disambiguate --- Cargo.lock | 471 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 +- 2 files changed, 472 insertions(+), 1 deletion(-) create mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c673349 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,471 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "console" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a50aab2529019abfabfa93f1e6c41ef392f91fbf179b347a7e96abb524884a08" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "regex", + "terminal_size", + "unicode-width", + "winapi", + "winapi-util", +] + +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.52.0", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "json-structural-diff" +version = "0.1.0" +dependencies = [ + "console 0.15.8", + "difflib", + "regex", + "serde_json", +] + +[[package]] +name = "json-structural-diff-cli" +version = "0.1.0" +dependencies = [ + "clap", + "console 0.13.0", + "json-structural-diff", + "rayon", + "serde_json", + "walkdir", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.168" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "serde" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "terminal_size" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml index 3f5be69..32225d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ regex = "^1" serde_json = "^1.0" [dependencies.console] -version = "^0.13" +version = "^0.15.8" default-features = true optional = true From edb4200427cbf47d5ad7d46036d5a1b785df16c2 Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 21:14:32 +0100 Subject: [PATCH 09/20] actions: Remove old directory --- .github/actions-rs/grcov.yml | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .github/actions-rs/grcov.yml diff --git a/.github/actions-rs/grcov.yml b/.github/actions-rs/grcov.yml deleted file mode 100644 index 75492cb..0000000 --- a/.github/actions-rs/grcov.yml +++ /dev/null @@ -1,4 +0,0 @@ -ignore-not-existing: true -ignore: - - "/*" - - "../*" From ffd0f2385b3f0b2d444f5ea9bd84b3dbb598e0df Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 21:14:54 +0100 Subject: [PATCH 10/20] actions: Update deploy --- .github/workflows/deploy.yml | 181 ++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 87 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 4e8669b..23b1e3a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -7,126 +7,133 @@ on: jobs: - windows-binaries: + create-windows-binaries: runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install stable - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true + uses: dtolnay/rust-toolchain@stable - - name: Build json-diff + - name: Build jsons-structural-diff run: | cargo build --release --workspace - - name: Create zip + - name: Get the version + shell: bash + id: tagName run: | - cd target/release - 7z a ../../json-structural-diff-windows-msvc.zip ` - "json-structural-diff-cli.exe" + VERSION=$(cargo pkgid | cut -d# -f2) + echo "tag=$VERSION" >> $GITHUB_OUTPUT - - name: Upload binaries - uses: actions/upload-artifact@v2 + - name: Build package + id: package + shell: bash + run: | + ARCHIVE_TARGET="x86_64-pc-windows-msvc" + ARCHIVE_NAME="json-structural-diff-${{ steps.tagName.outputs.tag }}-$ARCHIVE_TARGET" + ARCHIVE_FILE="${ARCHIVE_NAME}.zip" + 7z a ${ARCHIVE_FILE} ./target/release/json-structural-diff-cli.exe + echo "file=$ARCHIVE_FILE" >> $GITHUB_OUTPUT + echo "name=$ARCHIVE_NAME.zip" >> $GITHUB_OUTPUT + + - name: Upload artifacts + uses: actions/upload-artifact@v3 with: - name: json-diff-windows-msvc-binaries - path: json-structural-diff-windows-msvc.zip + name: ${{ steps.package.outputs.name }} + path: ${{ steps.package.outputs.file }} - linux-binaries: + create-unix-binaries: - runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-musl + - os: macos-latest + target: x86_64-apple-darwin - steps: - - uses: actions/checkout@v2 + runs-on: ${{ matrix.os }} - - name: Install musl-tools - run: | - sudo apt-get install musl-tools + steps: + - uses: actions/checkout@v4 - - name: Install Rust stable and musl target - uses: actions-rs/toolchain@v1 + - name: Install Rust stable + uses: dtolnay/rust-toolchain@stable with: - profile: minimal - toolchain: stable - target: x86_64-unknown-linux-musl - override: true + target: ${{ matrix.target }} - - name: Build json-diff + - name: Install musl + if: contains(matrix.target, 'linux-musl') run: | - cargo build --workspace --release --target x86_64-unknown-linux-musl + sudo apt-get install musl-tools - - name: Create zip + - name: Build json-structural-diff run: | - cd target/x86_64-unknown-linux-musl/release - strip json-structural-diff-cli - tar -czvf $GITHUB_WORKSPACE/json-structural-diff-linux.tar.gz \ - json-structural-diff-cli - - - name: Upload binaries - uses: actions/upload-artifact@v2 - with: - name: json-diff-linux-binaries - path: json-structural-diff-linux.tar.gz - - macos-binaries: - - runs-on: macos-latest + cargo build --workspace --release --target ${{ matrix.target }} - steps: - - uses: actions/checkout@v2 - - - name: Install stable - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - name: Build json-diff + - name: Strip binary run: | - cargo build --workspace --release + strip target/${{ matrix.target }}/release/json-structural-diff-cli - - name: Create zip + - name: Get the version + id: tagName run: | - cd target/release - strip json-structural-diff-cli - zip $GITHUB_WORKSPACE/json-structural-diff-macos.zip \ - json-structural-diff-cli + VERSION=$(cargo pkgid | cut -d# -f2) + echo "tag=$VERSION" >> $GITHUB_OUTPUT - - name: Upload binaries - uses: actions/upload-artifact@v2 + - name: Build package + id: package + run: | + TAR_FILE=json-structural-diff-${{ steps.tagName.outputs.tag }}-${{ matrix.target }} + cd target/${{ matrix.target }}/release + tar -czvf $GITHUB_WORKSPACE/$TAR_FILE.tar.gz json-structural-diff-cli + echo "name=$TAR_FILE" >> $GITHUB_OUTPUT + echo "file=$TAR_FILE.tar.gz" >> $GITHUB_OUTPUT + + - name: Upload artifacts + uses: actions/upload-artifact@v3 with: - name: json-diff-macos-binaries - path: json-structural-diff-macos.zip + name: ${{ steps.package.outputs.name }} + path: ${{ steps.package.outputs.file }} + deploy: - needs: [windows-binaries, linux-binaries, macos-binaries] + needs: [create-windows-binaries, create-unix-binaries] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - - name: Download zip files - uses: actions/download-artifact@v2 - - - name: Create Cargo.lock - run: | - cargo update - - - name: Create a release - uses: softprops/action-gh-release@v1 - with: - files: | - Cargo.lock - json-diff-linux-binaries/json-structural-diff-linux.tar.gz - json-diff-macos-binaries/json-structural-diff-macos.zip - json-diff-windows-msvc-binaries/json-structural-diff-windows-msvc.zip - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/checkout@v4 + + - name: Install Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: Create Cargo.lock + run: | + cargo update + + - name: Get version + id: tagName + run: | + VERSION=$(cargo pkgid | cut -d# -f2) + echo "tag=$VERSION" >> $GITHUB_OUTPUT + + - name: Download artifacts + uses: actions/download-artifact@v2 + with: + path: ./binaries + + - name: Create a release + uses: softprops/action-gh-release@v1 + with: + name: v${{ steps.tagName.outputs.tag }} + files: | + ./binaries/**/*.zip + ./binaries/**/*.tar.gz + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 1cd86911df1ca912a2e2a6cbdac0d2c58b0eea64 Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 21:20:32 +0100 Subject: [PATCH 11/20] readme: Remove useless badges --- json-structural-diff-cli/README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/json-structural-diff-cli/README.md b/json-structural-diff-cli/README.md index f3da572..0240eb9 100644 --- a/json-structural-diff-cli/README.md +++ b/json-structural-diff-cli/README.md @@ -1,9 +1,5 @@ # A Rust JSON structural diff CLI -[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) -[![Actions Status](https://github.com/Luni-4/json-structural-diff/workflows/json-structural-diff/badge.svg)](https://github.com/Luni-4/json-structural-diff/actions) -[![Coverage Status](https://coveralls.io/repos/github/Luni-4/json-structural-diff/badge.svg?branch=master)](https://coveralls.io/github/Luni-4/json-structural-diff?branch=master) - A pure-Rust JSON structural diff CLI based on the JSON structural diff library. ## Building CLI From 3afea077ed668bb3be4b560e89a196d7f8a4dd3d Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 21:25:05 +0100 Subject: [PATCH 12/20] misc: Remove a duplicate crate --- .../json-diff-cli/Cargo.toml | 24 --- .../json-diff-cli/README.md | 25 --- .../json-diff-cli/src/main.rs | 186 ------------------ 3 files changed, 235 deletions(-) delete mode 100644 json-structural-diff-cli/json-diff-cli/Cargo.toml delete mode 100644 json-structural-diff-cli/json-diff-cli/README.md delete mode 100644 json-structural-diff-cli/json-diff-cli/src/main.rs diff --git a/json-structural-diff-cli/json-diff-cli/Cargo.toml b/json-structural-diff-cli/json-diff-cli/Cargo.toml deleted file mode 100644 index f3ad605..0000000 --- a/json-structural-diff-cli/json-diff-cli/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "json-diff-cli" -version = "0.1.0" -authors = ["Luni-4 "] -description = "A Rust JSON structural diff cli" -repository = "https://github.com/Luni-4/json-structural-diff" -keywords = [ - "json-diff", - "json-diff-cli", - "json-structural-diff" -] -license = "MIT" -edition = "2018" - -[[bin]] -name = "json-diff-cli" - -[dependencies] -clap = "^2.33" -console = "^0.13" -json-structural-diff = { path = "..", version = "0.1.0", features=["colorize"]} -rayon = "^1.5" -serde_json = "^1.0" -walkdir = "^2.3" diff --git a/json-structural-diff-cli/json-diff-cli/README.md b/json-structural-diff-cli/json-diff-cli/README.md deleted file mode 100644 index 790d00b..0000000 --- a/json-structural-diff-cli/json-diff-cli/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# A Rust JSON structural diff CLI - -[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) -[![Actions Status](https://github.com/Luni-4/json-structural-diff/workflows/json-structural-diff/badge.svg)](https://github.com/Luni-4/json-structural-diff/actions) -[![Coverage Status](https://coveralls.io/repos/github/Luni-4/json-structural-diff/badge.svg?branch=master)](https://coveralls.io/github/Luni-4/json-structural-diff?branch=master) - -A pure-Rust JSON structural diff CLI based on the JSON structural diff library. - -## Building CLI - -```bash -cargo build --workspace -``` - -If you want to build the cli in release mode, add the `--release` option -to the command above. - -## Installing CLI - -Run `cargo install json-diff-cli` or download the binaries contained in the -[release](https://github.com/Luni-4/json-structural-diff/releases/) page. - -## License - -Released under the [MIT License](../LICENSE). diff --git a/json-structural-diff-cli/json-diff-cli/src/main.rs b/json-structural-diff-cli/json-diff-cli/src/main.rs deleted file mode 100644 index 72d1c8b..0000000 --- a/json-structural-diff-cli/json-diff-cli/src/main.rs +++ /dev/null @@ -1,186 +0,0 @@ -#[macro_use] -extern crate clap; - -use std::fs::File; -use std::io::Write; -use std::path::PathBuf; -use std::process; - -use clap::{App, Arg}; -use console::Term; -use rayon::prelude::*; -use serde_json::Value; -use walkdir::{DirEntry, WalkDir}; - -use json_structural_diff::{colorize, JsonDiff}; - -struct Config { - raw: bool, - only_keys: bool, - color: bool, -} - -fn act_on_file( - path1: &PathBuf, - path2: &PathBuf, - output_path: &Option, - cfg: &Config, -) -> std::io::Result<()> { - let buffer1 = std::fs::read(&path1).unwrap(); - let json1: Value = serde_json::from_slice(&buffer1).unwrap(); - let buffer2 = std::fs::read(path2).unwrap(); - let json2: Value = serde_json::from_slice(&buffer2).unwrap(); - - if json1 != json2 { - let json_diff = JsonDiff::diff(&json1, &json2, cfg.only_keys); - let result = json_diff.diff.unwrap(); - let json_string = if cfg.raw { - serde_json::to_string_pretty(&result)? - } else { - colorize(&result, cfg.color) - }; - if let Some(output_path) = output_path { - let output_filename = path1.file_name().unwrap().to_str().unwrap(); - let mut output_file = File::create(output_path.join(output_filename))?; - writeln!(&mut output_file, "{}", json_string)?; - } else { - let mut term = Term::stdout(); - term.write_all(json_string.as_bytes())?; - } - } - Ok(()) -} - -fn is_hidden(entry: &DirEntry) -> bool { - entry - .file_name() - .to_str() - .map(|s| s.starts_with('.')) - .unwrap_or(false) -} - -fn explore( - path1: &PathBuf, - path2: &PathBuf, - output_path: &Option, - cfg: &Config, -) -> std::io::Result<()> { - WalkDir::new(&path1) - .into_iter() - .filter_entry(|e| !is_hidden(e)) - .zip( - WalkDir::new(&path2) - .into_iter() - .filter_entry(|e| !is_hidden(e)), - ) - .par_bridge() - .for_each(|(entry1, entry2)| { - let entry1 = entry1.as_ref().unwrap(); - let path1_file: PathBuf = entry1.path().to_path_buf(); - let entry2 = entry2.as_ref().unwrap(); - let path2_file: PathBuf = entry2.path().to_path_buf(); - if path1_file.is_file() - && path2_file.is_file() - && path1_file.extension().unwrap() == "json" - && path2_file.extension().unwrap() == "json" - { - act_on_file(&path1_file, &path2_file, &output_path, &cfg).unwrap(); - } - }); - - Ok(()) -} - -#[inline(always)] -fn exist_or_exit(path: &PathBuf, which_path: &str) { - if !(path.exists()) { - eprintln!( - "The {} path `{}` is not correct", - which_path, - path.to_str().unwrap() - ); - process::exit(1); - } -} - -fn main() { - let matches = App::new("json-diff") - .version(crate_version!()) - .author(&*env!("CARGO_PKG_AUTHORS").replace(':', "\n")) - .about("Find the differences between two input json files") - .arg( - Arg::with_name("color") - .help("Colored output") - .short("c") - .long("--[no-]color"), - ) - .arg( - Arg::with_name("raw") - .help("Display raw JSON encoding of the diff") - .short("j") - .long("raw-json"), - ) - .arg( - Arg::with_name("keys") - .help("Compare only the keys, ignore the differences in values") - .short("k") - .long("keys-only"), - ) - .arg( - Arg::with_name("output") - .help("Output directory") - .short("o") - .long("output") - .takes_value(true), - ) - .arg( - Arg::with_name("first-json") - .help("Old json file") - .required(true) - .takes_value(true), - ) - .arg( - Arg::with_name("second-json") - .help("New json file") - .required(true) - .takes_value(true), - ) - .get_matches(); - - let path1 = PathBuf::from(matches.value_of("first-json").unwrap()); - let path2 = PathBuf::from(matches.value_of("second-json").unwrap()); - - let output_path = if let Some(path) = matches.value_of("output") { - let path = PathBuf::from(path); - exist_or_exit(&path, "output"); - Some(path) - } else { - None - }; - - exist_or_exit(&path1, "first"); - exist_or_exit(&path2, "second"); - - let color = if output_path.is_none() { - matches.is_present("color") - } else { - false - }; - let raw = matches.is_present("raw"); - let only_keys = matches.is_present("keys"); - - let cfg = Config { - raw, - only_keys, - color, - }; - - if path1.is_dir() && path2.is_dir() { - explore(&path1, &path2, &output_path, &cfg).unwrap(); - } else if (path1.is_dir() && !path2.is_dir()) || (!path1.is_dir() && path2.is_dir()) { - eprintln!("Both paths should be a directory or a file",); - process::exit(1); - } else { - act_on_file(&path1, &path2, &output_path, &cfg).unwrap(); - } -} From dc1bd16517e68576dec002077449b6c1da9cf842 Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 21:25:45 +0100 Subject: [PATCH 13/20] cli: Remove json-structural-diff version --- json-structural-diff-cli/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json-structural-diff-cli/Cargo.toml b/json-structural-diff-cli/Cargo.toml index 35fa9a8..51789ea 100644 --- a/json-structural-diff-cli/Cargo.toml +++ b/json-structural-diff-cli/Cargo.toml @@ -18,7 +18,7 @@ name = "json-structural-diff-cli" [dependencies] clap = "^2.33" console = "^0.13" -json-structural-diff = { path = "..", version = "0.1.0", features=["colorize"]} +json-structural-diff = { path = "..", features=["colorize"]} rayon = "^1.5" serde_json = "^1.0" walkdir = "^2.3" From ac3fa7796ae732cb7fb7b369d0de9edbb7690687 Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 21:27:03 +0100 Subject: [PATCH 14/20] cli: Update Rust version --- json-structural-diff-cli/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json-structural-diff-cli/Cargo.toml b/json-structural-diff-cli/Cargo.toml index 51789ea..5d04132 100644 --- a/json-structural-diff-cli/Cargo.toml +++ b/json-structural-diff-cli/Cargo.toml @@ -10,7 +10,7 @@ keywords = [ "json-diff" ] license = "MIT" -edition = "2018" +edition = "2021" [[bin]] name = "json-structural-diff-cli" From 89cfd34ac312bf9289e49d6b5accd74e0a68ca4a Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 21:31:27 +0100 Subject: [PATCH 15/20] cli: Apply clippy lints --- json-structural-diff-cli/src/main.rs | 33 ++++++++++------------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/json-structural-diff-cli/src/main.rs b/json-structural-diff-cli/src/main.rs index 1b5e6cc..b953683 100644 --- a/json-structural-diff-cli/src/main.rs +++ b/json-structural-diff-cli/src/main.rs @@ -3,7 +3,7 @@ extern crate clap; use std::fs::File; use std::io::Write; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process; use clap::{App, Arg}; @@ -22,10 +22,10 @@ struct Config { fn act_on_file( path1: &PathBuf, path2: &PathBuf, - output_path: &Option, + output_path: Option<&PathBuf>, cfg: &Config, ) -> std::io::Result<()> { - let buffer1 = std::fs::read(&path1).unwrap(); + let buffer1 = std::fs::read(path1).unwrap(); let buffer2 = std::fs::read(path2).unwrap(); if let (Ok(json1), Ok(json2)) = ( @@ -43,7 +43,7 @@ fn act_on_file( if let Some(output_path) = output_path { let output_filename = path1.file_name().unwrap().to_str().unwrap(); let mut output_file = File::create(output_path.join(output_filename))?; - writeln!(&mut output_file, "{}", json_string)?; + writeln!(&mut output_file, "{json_string}")?; } else { let mut term = Term::stdout(); term.write_all(json_string.as_bytes())?; @@ -57,21 +57,15 @@ fn is_hidden(entry: &DirEntry) -> bool { entry .file_name() .to_str() - .map(|s| s.starts_with('.')) - .unwrap_or(false) + .is_some_and(|s| s.starts_with('.')) } -fn explore( - path1: &PathBuf, - path2: &PathBuf, - output_path: &Option, - cfg: &Config, -) -> std::io::Result<()> { - WalkDir::new(&path1) +fn explore(path1: &PathBuf, path2: &PathBuf, output_path: Option<&PathBuf>, cfg: &Config) { + WalkDir::new(path1) .into_iter() .filter_entry(|e| !is_hidden(e)) .zip( - WalkDir::new(&path2) + WalkDir::new(path2) .into_iter() .filter_entry(|e| !is_hidden(e)), ) @@ -86,15 +80,12 @@ fn explore( && path1_file.extension().unwrap() == "json" && path2_file.extension().unwrap() == "json" { - act_on_file(&path1_file, &path2_file, &output_path, &cfg).unwrap(); + act_on_file(&path1_file, &path2_file, output_path, cfg).unwrap(); } }); - - Ok(()) } -#[inline(always)] -fn exist_or_exit(path: &PathBuf, which_path: &str) { +fn exist_or_exit(path: &Path, which_path: &str) { if !(path.exists()) { eprintln!( "The {} path `{}` is not correct", @@ -178,11 +169,11 @@ fn main() { }; if path1.is_dir() && path2.is_dir() { - explore(&path1, &path2, &output_path, &cfg).unwrap(); + explore(&path1, &path2, output_path.as_ref(), &cfg); } else if (path1.is_dir() && !path2.is_dir()) || (!path1.is_dir() && path2.is_dir()) { eprintln!("Both paths should be a directory or a file",); process::exit(1); } else { - act_on_file(&path1, &path2, &output_path, &cfg).unwrap(); + act_on_file(&path1, &path2, output_path.as_ref(), &cfg).unwrap(); } } From 2b6d27da4303df522f90705287d0f03266de0846 Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 21:43:37 +0100 Subject: [PATCH 16/20] misc: Apply clippy lints --- src/colorize.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/colorize.rs b/src/colorize.rs index 4b27f77..fb542c7 100644 --- a/src/colorize.rs +++ b/src/colorize.rs @@ -118,6 +118,7 @@ pub fn colorize_to_array(diff: &Value) -> Vec { /// /// If `None`, there is no JSON structural difference to be formatted. #[cfg(feature = "colorize")] +#[must_use] #[allow(clippy::module_name_repetitions)] pub fn colorize(diff: &Value, is_color: bool) -> String { use console::Style; @@ -125,7 +126,7 @@ pub fn colorize(diff: &Value, is_color: bool) -> String { let mut output: Vec = Vec::new(); let mut output_func = |color: &str, line: &str| { - let color_line = format!("{}{}", color, line); + let color_line = format!("{color}{line}"); let str_output = if is_color { match color { "+" => format!("{}", Style::new().green().apply_to(color_line)), From 155aad7c2f12d7751dbd4e2fbd7fb755bf5a3866 Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 21:45:50 +0100 Subject: [PATCH 17/20] misc: Update license --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index c12e0eb..9f3b6c0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Luni-4 +Copyright (c) 2020 Luni-4, json-structural-diff contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From acbd6a9f49a95c059418320c89134b12ca7f9754 Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 21:55:23 +0100 Subject: [PATCH 18/20] actions: Fix deploy script --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 23b1e3a..7ae2ac1 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -124,7 +124,7 @@ jobs: echo "tag=$VERSION" >> $GITHUB_OUTPUT - name: Download artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: path: ./binaries From 345af63ba50ae234c7a2429c72ac8dbfb7145fb1 Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 21:55:33 +0100 Subject: [PATCH 19/20] misc: Update version --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- json-structural-diff-cli/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c673349..c245be4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -141,7 +141,7 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "json-structural-diff" -version = "0.1.0" +version = "0.2.0" dependencies = [ "console 0.15.8", "difflib", @@ -151,7 +151,7 @@ dependencies = [ [[package]] name = "json-structural-diff-cli" -version = "0.1.0" +version = "0.2.0" dependencies = [ "clap", "console 0.13.0", diff --git a/Cargo.toml b/Cargo.toml index 32225d1..6feda9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "json-structural-diff" -version = "0.1.0" +version = "0.2.0" authors = ["Luni-4 "] description = "A Rust JSON structural diff library" repository = "https://github.com/Luni-4/json-structural-diff" diff --git a/json-structural-diff-cli/Cargo.toml b/json-structural-diff-cli/Cargo.toml index 5d04132..312ff0a 100644 --- a/json-structural-diff-cli/Cargo.toml +++ b/json-structural-diff-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "json-structural-diff-cli" -version = "0.1.0" +version = "0.2.0" authors = ["Luni-4 "] description = "A Rust JSON structural diff cli" repository = "https://github.com/Luni-4/json-structural-diff" From e0d170eb2178c53803bab1547250c69de19deb29 Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Mon, 9 Dec 2024 22:05:57 +0100 Subject: [PATCH 20/20] cli: Use latest version --- json-structural-diff-cli/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json-structural-diff-cli/Cargo.toml b/json-structural-diff-cli/Cargo.toml index 312ff0a..d792fa6 100644 --- a/json-structural-diff-cli/Cargo.toml +++ b/json-structural-diff-cli/Cargo.toml @@ -18,7 +18,7 @@ name = "json-structural-diff-cli" [dependencies] clap = "^2.33" console = "^0.13" -json-structural-diff = { path = "..", features=["colorize"]} +json-structural-diff = { path = "..", version = "0.2.0", features=["colorize"]} rayon = "^1.5" serde_json = "^1.0" walkdir = "^2.3"