tangled
alpha
login
or
join now
tgirl.cloud
/
lix-diff
0
fork
atom
this repo has no description
0
fork
atom
overview
issues
pulls
pipelines
refactor: we are now clone free
isabelroses.com
10 months ago
eb77640f
5cf5e272
+71
-51
4 changed files
expand all
collapse all
unified
split
src
diff.rs
main.rs
package.rs
parser.rs
+28
-27
src/diff.rs
···
14
14
longest_name: usize,
15
15
}
16
16
17
17
-
pub fn partition_diff(diff: &DiffRoot) -> PackageListDiff {
18
18
-
let mut added = BTreeMap::new();
19
19
-
let mut removed = BTreeMap::new();
20
20
-
let mut changed = BTreeMap::new();
21
21
-
let mut size_delta: i64 = 0;
22
22
-
let mut longest_name = 0;
17
17
+
impl From<DiffRoot> for PackageListDiff {
18
18
+
fn from(diff: DiffRoot) -> Self {
19
19
+
let mut out = PackageListDiff {
20
20
+
added: BTreeMap::new(),
21
21
+
removed: BTreeMap::new(),
22
22
+
changed: BTreeMap::new(),
23
23
+
size_delta: 0,
24
24
+
longest_name: 0,
25
25
+
};
23
26
24
24
-
for (name, package) in &diff.packages {
25
25
-
match package.diff_type {
26
26
-
DiffType::Added => {
27
27
-
added.insert(name.clone(), package.clone());
28
28
-
}
29
29
-
DiffType::Removed => {
30
30
-
removed.insert(name.clone(), package.clone());
27
27
+
for (name, package) in diff.packages {
28
28
+
out.size_delta += package.size_delta;
29
29
+
out.longest_name = out.longest_name.max(name.len());
30
30
+
31
31
+
match package.diff_type {
32
32
+
DiffType::Added => {
33
33
+
out.added.insert(name, package);
34
34
+
}
35
35
+
DiffType::Removed => {
36
36
+
out.removed.insert(name, package);
37
37
+
}
38
38
+
DiffType::Changed => {
39
39
+
out.changed.insert(name, package);
40
40
+
}
41
41
+
DiffType::Unknown => {
42
42
+
// This should never happen, but just in case
43
43
+
eprintln!("Unknown diff type for package: {name}");
44
44
+
}
31
45
}
32
32
-
DiffType::Changed => {
33
33
-
changed.insert(name.clone(), package.clone());
34
34
-
}
35
35
-
_ => {}
36
46
}
37
47
38
38
-
size_delta += package.size_delta;
39
39
-
longest_name = longest_name.max(name.len());
40
40
-
}
41
41
-
42
42
-
PackageListDiff {
43
43
-
added,
44
44
-
removed,
45
45
-
changed,
46
46
-
size_delta,
47
47
-
longest_name,
48
48
+
out
48
49
}
49
50
}
50
51
+2
-2
src/main.rs
···
2
2
3
3
use argh::FromArgs;
4
4
use color_eyre::Result;
5
5
+
use diff::PackageListDiff;
5
6
use nu_ansi_term::{Color, Style};
6
7
7
8
mod diff;
···
44
45
std::process::exit(1);
45
46
}
46
47
47
47
-
let diff = parser::diff(&before, &after)?;
48
48
-
let packages = diff::partition_diff(&diff);
48
48
+
let packages: PackageListDiff = parser::diff(&before, &after)?.into();
49
49
50
50
let arrow_style = Style::new().bold().fg(Color::LightGray);
51
51
+6
-4
src/package.rs
···
1
1
+
use std::borrow::Cow;
2
2
+
1
3
use nu_ansi_term::Color::{Green, Red};
2
4
use serde::de::Deserializer;
3
5
use serde::Deserialize;
4
6
5
5
-
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
7
7
+
#[derive(Default, Debug, PartialEq, Eq)]
6
8
pub enum DiffType {
7
9
Added,
8
10
Removed,
···
12
14
Unknown,
13
15
}
14
16
15
15
-
#[derive(Deserialize, Clone, Debug)]
17
17
+
#[derive(Deserialize, Debug)]
16
18
#[serde(rename_all = "camelCase")]
17
19
pub struct Package {
18
20
pub size_delta: i64,
···
32
34
where
33
35
D: Deserializer<'de>,
34
36
{
35
35
-
let vec = Vec::<String>::deserialize(deserializer)?;
37
37
+
let vec = Vec::<Cow<'de, str>>::deserialize(deserializer)?;
36
38
Ok(vec
37
39
.into_iter()
38
40
.map(|s| {
39
41
if s.is_empty() {
40
42
"<none>".to_string()
41
43
} else {
42
42
-
s
44
44
+
s.into_owned()
43
45
}
44
46
})
45
47
.collect())
+35
-18
src/parser.rs
···
4
4
5
5
use crate::package::{DiffType, Package};
6
6
7
7
-
#[derive(Deserialize, Debug)]
7
7
+
#[derive(Debug)]
8
8
pub struct DiffRoot {
9
9
pub packages: BTreeMap<String, Package>,
10
10
···
12
12
pub schema: String,
13
13
}
14
14
15
15
+
impl<'de> Deserialize<'de> for DiffRoot {
16
16
+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
17
17
+
where
18
18
+
D: serde::Deserializer<'de>,
19
19
+
{
20
20
+
#[derive(Deserialize)]
21
21
+
struct Raw {
22
22
+
packages: BTreeMap<String, Package>,
23
23
+
schema: String,
24
24
+
}
25
25
+
26
26
+
let Raw {
27
27
+
mut packages,
28
28
+
schema,
29
29
+
} = Raw::deserialize(deserializer)?;
30
30
+
31
31
+
for pkg in packages.values_mut() {
32
32
+
pkg.diff_type = DiffType::from_versions(&pkg.versions_before, &pkg.versions_after);
33
33
+
}
34
34
+
35
35
+
Ok(DiffRoot { packages, schema })
36
36
+
}
37
37
+
}
38
38
+
15
39
fn run_diff(before: &str, after: &str) -> String {
16
40
let raw_diff = Command::new("nix")
17
41
.args(["store", "diff-closures", "--json", before, after])
18
42
.output()
19
19
-
.expect("Failed to execute command");
43
43
+
.expect("Failed to execute nix command");
20
44
21
45
if !raw_diff.status.success() {
22
22
-
eprintln!("Error: {}", String::from_utf8_lossy(&raw_diff.stderr));
46
46
+
eprintln!("{}", String::from_utf8_lossy(&raw_diff.stderr));
23
47
std::process::exit(1);
24
48
}
25
49
26
26
-
let diff_output = String::from_utf8_lossy(&raw_diff.stdout);
27
27
-
if diff_output.is_empty() {
50
50
+
let stdout = raw_diff.stdout;
51
51
+
if stdout.is_empty() {
28
52
eprintln!("No differences found.");
29
53
std::process::exit(0);
30
54
}
31
55
32
32
-
diff_output.into_owned()
56
56
+
// Assume nix output is valid UTF-8
57
57
+
String::from_utf8(stdout).expect("Output was not valid UTF-8")
33
58
}
34
59
35
60
fn parse_diff(input: &str) -> Result<DiffRoot> {
36
36
-
serde_json::from_str(input)
37
37
-
.map(|mut diff_root: DiffRoot| {
38
38
-
for package in diff_root.packages.values_mut() {
39
39
-
package.diff_type =
40
40
-
DiffType::from_versions(&package.versions_before, &package.versions_after);
41
41
-
}
42
42
-
diff_root
43
43
-
})
44
44
-
.map_err(|e| {
45
45
-
eprintln!("Failed to parse JSON: {e}");
46
46
-
std::process::exit(1);
47
47
-
})
61
61
+
serde_json::from_str::<DiffRoot>(input).map_err(|e| {
62
62
+
eprintln!("Failed to parse JSON: {e}");
63
63
+
std::process::exit(1);
64
64
+
})
48
65
}
49
66
50
67
pub fn diff(before: &str, after: &str) -> Result<DiffRoot> {