Skip to content

Commit 3baa44c

Browse files
committed
feat(json)!: add optional shared-inodes
1 parent 807321e commit 3baa44c

4 files changed

Lines changed: 44 additions & 20 deletions

File tree

src/app.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ impl App {
8686
}
8787

8888
let visualization = match unit_and_tree {
89-
UnitAndTree::Bytes(reflection) => visualize!(reflection, bytes_format),
90-
UnitAndTree::Blocks(reflection) => visualize!(reflection, ()),
89+
UnitAndTree::Bytes(tree) => visualize!(tree.data, bytes_format),
90+
UnitAndTree::Blocks(tree) => visualize!(tree.data, ()),
9191
};
9292

9393
print!("{visualization}"); // it already ends with "\n", println! isn't needed here.

src/app/sub.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use crate::{
22
args::Fraction,
3-
data_tree::{DataTree, DataTreeReflection},
3+
data_tree::DataTree,
44
fs_tree_builder::FsTreeBuilder,
55
get_size::GetSize,
66
hook,
7-
json_data::{BinaryVersion, JsonData, SchemaVersion, UnitAndTree},
7+
json_data::{BinaryVersion, JsonData, JsonTree, SchemaVersion, UnitAndTree},
88
os_string_display::OsStringDisplay,
99
reporter::ParallelReporter,
1010
runtime_error::RuntimeError,
@@ -22,7 +22,7 @@ where
2222
Size: size::Size + Into<u64> + Serialize + Send + Sync,
2323
SizeGetter: GetSize<Size = Size> + Copy + Sync,
2424
Hook: hook::Hook<Size, Report> + DeduplicateHardlinkSizes<Size> + Copy + Sync,
25-
DataTreeReflection<String, Size>: Into<UnitAndTree>,
25+
JsonTree<Size>: Into<UnitAndTree>,
2626
{
2727
/// List of files and/or directories.
2828
pub files: Vec<PathBuf>,
@@ -58,7 +58,7 @@ where
5858
Report: ParallelReporter<Size> + Sync,
5959
SizeGetter: GetSize<Size = Size> + Copy + Sync,
6060
Hook: hook::Hook<Size, Report> + DeduplicateHardlinkSizes<Size> + Copy + Sync,
61-
DataTreeReflection<String, Size>: Into<UnitAndTree>,
61+
JsonTree<Size>: Into<UnitAndTree>,
6262
{
6363
/// Run the sub program.
6464
pub fn run(self) -> Result<(), RuntimeError> {
@@ -140,15 +140,18 @@ where
140140
GLOBAL_STATUS_BOARD.clear_line(0);
141141

142142
if json_output {
143-
let unit_and_tree: UnitAndTree = data_tree
143+
let data = data_tree
144144
.into_reflection() // I really want to use std::mem::transmute here but can't.
145145
.par_convert_names_to_utf8() // TODO: allow non-UTF8 somehow.
146-
.expect("convert all names from raw string to UTF-8")
147-
.into();
146+
.expect("convert all names from raw string to UTF-8");
147+
let json_tree = JsonTree {
148+
data,
149+
shared_inodes: None, // TODO: somehow get data from `deduplication_record` above
150+
};
148151
let json_data = JsonData {
149152
schema_version: SchemaVersion,
150153
binary_version: Some(BinaryVersion::current()),
151-
unit_and_tree,
154+
unit_and_tree: json_tree.into(),
152155
};
153156
return serde_json::to_writer(stdout(), &json_data)
154157
.map_err(RuntimeError::SerializationFailure);

src/json_data.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,40 @@ pub use binary_version::BinaryVersion;
55
pub use schema_version::SchemaVersion;
66

77
use crate::{
8-
data_tree::Reflection,
9-
size::{Blocks, Bytes},
8+
data_tree,
9+
hardlink::hardlink_list,
10+
size::{self, Blocks, Bytes},
1011
};
11-
use derive_more::{From, TryInto};
12+
use derive_more::{Deref, DerefMut, From, TryInto};
1213

1314
#[cfg(feature = "json")]
1415
use serde::{Deserialize, Serialize};
1516

17+
/// The `"tree"` field of [`JsonData`].
18+
#[derive(Debug, Clone, Deref, DerefMut)]
19+
#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
20+
#[cfg_attr(feature = "json", serde(rename_all = "kebab-case"))]
21+
pub struct JsonTree<Size: size::Size> {
22+
/// The main data of the tree.
23+
#[deref]
24+
#[deref_mut]
25+
#[cfg_attr(feature = "json", serde(flatten))]
26+
pub data: data_tree::Reflection<String, Size>,
27+
/// Optional list of shared inodes, their sizes, and their many links.
28+
#[cfg_attr(feature = "json", serde(skip_serializing_if = "Option::is_none"))]
29+
pub shared_inodes: Option<hardlink_list::Reflection<Size>>,
30+
}
31+
1632
/// The `"unit"` field and the `"tree"` field of [`JsonData`].
1733
#[derive(Debug, Clone, From, TryInto)]
1834
#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
1935
#[cfg_attr(feature = "json", serde(tag = "unit", content = "tree"))]
2036
#[cfg_attr(feature = "json", serde(rename_all = "kebab-case"))]
2137
pub enum UnitAndTree {
2238
/// Tree where size is [bytes](Bytes).
23-
Bytes(Reflection<String, Bytes>),
39+
Bytes(JsonTree<Bytes>),
2440
/// Tree where size is [blocks](Blocks).
25-
Blocks(Reflection<String, Blocks>),
41+
Blocks(JsonTree<Blocks>),
2642
}
2743

2844
/// Output of the program with `--json-output` flag as well as

tests/json.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ pub use _utils::*;
77
use command_extra::CommandExtra;
88
use parallel_disk_usage::{
99
bytes_format::BytesFormat,
10-
data_tree::{DataTree, Reflection},
10+
data_tree::DataTree,
1111
fs_tree_builder::FsTreeBuilder,
1212
get_size::GetApparentSize,
1313
hook,
14-
json_data::{JsonData, SchemaVersion},
14+
json_data::{JsonData, JsonTree, SchemaVersion},
1515
reporter::{ErrorOnlyReporter, ErrorReport},
1616
size::Bytes,
1717
visualizer::{BarAlignment, ColumnWidthDistribution, Direction, Visualizer},
@@ -26,7 +26,7 @@ use std::{
2626

2727
type SampleName = String;
2828
type SampleData = Bytes;
29-
type SampleReflection = Reflection<SampleName, SampleData>;
29+
type SampleJsonTree = JsonTree<SampleData>;
3030
type SampleTree = DataTree<SampleName, SampleData>;
3131

3232
fn sample_tree() -> SampleTree {
@@ -75,8 +75,9 @@ fn json_output() {
7575
.pipe_as_ref(serde_json::from_str::<JsonData>)
7676
.expect("parse stdout as JsonData")
7777
.unit_and_tree
78-
.pipe(TryInto::<SampleReflection>::try_into)
78+
.pipe(TryInto::<SampleJsonTree>::try_into)
7979
.expect("extract reflection")
80+
.data
8081
.pipe(sanitize_tree_reflection);
8182
dbg!(&actual);
8283
let builder = FsTreeBuilder {
@@ -98,10 +99,14 @@ fn json_output() {
9899

99100
#[test]
100101
fn json_input() {
102+
let json_tree = JsonTree {
103+
data: sample_tree().into_reflection(),
104+
shared_inodes: None,
105+
};
101106
let json_data = JsonData {
102107
schema_version: SchemaVersion,
103108
binary_version: None,
104-
unit_and_tree: sample_tree().into_reflection().into(),
109+
unit_and_tree: json_tree.into(),
105110
};
106111
let json = serde_json::to_string_pretty(&json_data).expect("convert sample tree to JSON");
107112
eprintln!("JSON: {json}\n");

0 commit comments

Comments
 (0)