Skip to content

Commit 0f90e1b

Browse files
authored
1.6.0-alpha.1 (#212)
* docs: fixed spelling mistake in I-D * chore: bumped version * docs: updated spec I-D * fix: adjusted success and fail translations resolves #210 * chore: updated dependencies * fix: improve ordering of custom metadata resolves #206 * fix: improved scrolling behaviour resolves #155 * style: reformatted * chore: corrected incorrect version in cargo.toml * refactor: applied clippy suggestions
1 parent 405be5f commit 0f90e1b

File tree

16 files changed

+710
-632
lines changed

16 files changed

+710
-632
lines changed

Cargo.lock

Lines changed: 558 additions & 545 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "evidenceangel"
33
description = "Library and executables to work with EvidenceAngel evidence packages (*.evp)."
4-
version = "1.5.0-rc.8"
4+
version = "1.6.0-alpha.1"
55
edition = "2024"
66
license = "GPL-3.0-or-later"
77
authors = [
@@ -40,10 +40,8 @@ exporter-zip-of-files = []
4040
ui = [
4141
"dep:clap",
4242
"dep:directories",
43-
"dep:fluent",
4443
"dep:fluent-templates",
4544
"dep:glib-build-tools",
46-
"dep:once_cell",
4745
"dep:open",
4846
"dep:parse_datetime",
4947
"dep:parking_lot",
@@ -69,23 +67,21 @@ clap-verbosity-flag = { version = "3.0.2", default-features = false, features =
6967
clap_complete = { version = "4.5.2", optional = true }
7068
colored = { version = "3.0.0", optional = true }
7169
directories = { version = "6.0.0", optional = true }
72-
fluent = { version = "0.16.1", optional = true }
7370
fluent-templates = { version = "0.13.0", optional = true }
7471
getset = "0.1.2"
7572
html-escape = { version = "0.2.13", optional = true }
7673
infer = "0.19.0"
7774
jsonschema = "0.30.0"
78-
once_cell = { version = "1.19.0", optional = true }
7975
open = { version = "5.3.0", optional = true }
8076
parking_lot = { version = "0.12.3", optional = true }
81-
parse_datetime = { version = "0.9.0", optional = true }
77+
parse_datetime = { version = "0.10.0", optional = true }
8278
relm4 = { version = "0.9.0", features = [
8379
"libadwaita",
8480
"gnome_46",
8581
], optional = true }
8682
relm4-icons = { version = "0.9.0", optional = true }
87-
rust_xlsxwriter = { version = "0.86.1", features = ["chrono"], optional = true }
88-
schemars = { version = "0.8.21", features = ["chrono"], optional = true }
83+
rust_xlsxwriter = { version = "0.89.1", features = ["chrono"], optional = true }
84+
schemars = { version = "1.0.4", features = ["chrono04"], optional = true }
8985
serde = { version = "1.0.200", features = ["derive"] }
9086
serde_json = "1.0.116"
9187
sha256 = "1.5.0"
@@ -97,7 +93,7 @@ tracing-panic = { version = "0.1.2", optional = true }
9793
tracing-subscriber = { version = "0.3.19", optional = true }
9894
tracing-subscriber-multi = { version = "0.1.0", optional = true }
9995
uuid = { version = "1.8.0", features = ["v4", "fast-rng", "serde"] }
100-
zip = "2.4.1"
96+
zip = "4.3.0"
10197

10298
[target.'cfg(windows)'.dependencies]
10399
winapi = "0.3.9"
@@ -107,5 +103,5 @@ winresource = "0.1"
107103
ico-builder = "0.1"
108104

109105
[build-dependencies]
110-
glib-build-tools = { version = "0.20.0", optional = true }
106+
glib-build-tools = { version = "0.21.0", optional = true }
111107
mdbook = { version = "0.4.48", default-features = false, features = ["search"] }

schemas/draft-hopkins-evp-spec.md

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ submissionType = "independent"
99

1010
[seriesInfo]
1111
name = "Internet-Draft"
12-
value = "draft-hopkins-evp-spec-01"
12+
value = "draft-hopkins-evp-spec-04"
1313
stream = "independent"
1414
status = "informational"
1515

16-
date = 2025-05-05T00:00:00Z
16+
date = 2025-07-27T00:00:00Z
1717

1818
[[author]]
1919
initials="L."
@@ -63,9 +63,23 @@ The format does not attempt to:
6363
## Intended Audience
6464

6565
This specification is intended for those who might wish to write their
66-
own implementation of the evidence package format.
67-
68-
## Changes from Previous Verisons
66+
own implementation of the evidence package format. There are a number of
67+
situations where writing an implementation may be desirable:
68+
69+
* in an automation tool that runs a number of operations to
70+
automatically test something, to produce an evidence package
71+
containing the results of the automated testing;
72+
* in a manual evidence collection tool, where a user might want to
73+
collect evidence in a single, easy to manage place for later
74+
processing or sharing;
75+
* in an analysis tool, to view, annotate, share and understand the
76+
evidence from previous testing;
77+
* in a viewer, to view evidence that has been shared, for example from a
78+
testing team to a customer, or;
79+
* any other situation where it may be desirable to collect test evidence
80+
and bundle it together for later.
81+
82+
## Changes from Previous Versions
6983

7084
This document forms the original specification.
7185

@@ -79,8 +93,22 @@ when, and only when, they appear in all capitals, as shown here.
7993

8094
# Specification
8195

82-
An evidence package is a structured ZIP archive. It **MUST** contain the
83-
file "manifest.json", and the directories "media" and "testcases".
96+
An evidence package is a structured ZIP archive [@!zip]. It **MUST**
97+
contain the file "manifest.json", and the directories "media" and
98+
"testcases" internally within the ZIP archive. This structure does not
99+
need to be represented outside of the ZIP archive and as such the
100+
internal structure does not need to be understood by an end-user of any
101+
tool that works with evidence packages.
102+
103+
<reference anchor="zip" target="https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT">
104+
<front>
105+
<title>.ZIP File Format Specification</title>
106+
<author>
107+
<organization>PKWARE, Inc.</organization>
108+
</author>
109+
<date year="2022" month="November" day="01"/>
110+
</front>
111+
</reference>
84112

85113
See (#example-archive) for an example of the file's internal structure.
86114

@@ -306,7 +334,7 @@ When an implementor loads a file with fields it cannot understand, it
306334

307335
# IANA Considerations
308336

309-
This document acts as the specification for the requested media type
337+
This document acts as the specification for the media type
310338
application/vnd.angel.evidence-package.
311339

312340
# Security Considerations

src/evidenceangel-cli/package.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl fmt::Display for CliPackage {
144144
.custom_test_case_metadata_fields
145145
.iter()
146146
.collect::<Vec<_>>();
147-
sorted_custom_fields.sort_by(|(a, _), (b, _)| a.cmp(b));
147+
sorted_custom_fields.sort_by(|(_, a), (_, b)| a.cmp(b));
148148
for (idx, (key, field)) in sorted_custom_fields.iter().enumerate() {
149149
let ch = if idx == sorted_custom_fields.len() - 1 {
150150
"╰"
@@ -176,7 +176,7 @@ impl fmt::Display for CliPackage {
176176
}
177177

178178
/// A custom metadata field within a package
179-
#[derive(Serialize, JsonSchema)]
179+
#[derive(Serialize, JsonSchema, PartialEq, Eq)]
180180
struct CliCustomMetadataField {
181181
/// The field's ID
182182
key: String,
@@ -205,6 +205,24 @@ impl fmt::Display for CliCustomMetadataField {
205205
}
206206
}
207207

208+
impl PartialOrd for CliCustomMetadataField {
209+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
210+
Some(self.cmp(other))
211+
}
212+
}
213+
214+
impl Ord for CliCustomMetadataField {
215+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
216+
if self.primary && !other.primary {
217+
return std::cmp::Ordering::Less;
218+
}
219+
if !self.primary && other.primary {
220+
return std::cmp::Ordering::Greater;
221+
}
222+
self.name.cmp(&other.name)
223+
}
224+
}
225+
208226
/// A test case within a package
209227
#[derive(Serialize, JsonSchema)]
210228
struct PackageTestCase {

src/evidenceangel-cli/test_cases.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,12 @@ impl fmt::Display for CliTestCase {
269269
}
270270
};
271271

272-
rich_text.push_str(&format!(
272+
// SAFETY: This won't fail as there is no I/O
273+
write!(
274+
rich_text,
273275
"{padding_left}{formatted}{padding_right} | "
274-
));
276+
)
277+
.unwrap();
275278
}
276279
rich_text.push('\n');
277280
}
@@ -882,7 +885,7 @@ pub fn process(path: PathBuf, command: &TestCasesSubcommand) -> CliData {
882885
new_order.insert(new_pos, case_id);
883886
}
884887
Err(e) => return CliError::FailedToReadPackage(Rc::new(e)).into(),
885-
};
888+
}
886889

887890
// Update order
888891
if let Err(e) = package.set_test_case_order(new_order) {

src/evidenceangel-ui/app.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,7 +1229,7 @@ impl Component for AppModel {
12291229
.expect("Cannot navigate to metadata when no package is open");
12301230
if let Some(fields) = &pkg_fields {
12311231
let mut fields: Vec<_> = fields.iter().collect();
1232-
fields.sort_by(|(a, _), (b, _)| a.cmp(b));
1232+
fields.sort_by(|(_, a), (_, b)| a.cmp(b));
12331233
for (key, field) in fields {
12341234
custom_fields.push_back(CustomMetadataEditorFactoryInit {
12351235
root: root.clone(),
@@ -1306,7 +1306,7 @@ impl Component for AppModel {
13061306
pkg.read().metadata().custom_test_case_metadata()
13071307
{
13081308
let mut fields: Vec<_> = fields.iter().collect();
1309-
fields.sort_by(|(a, _), (b, _)| a.cmp(b));
1309+
fields.sort_by(|(_, a), (_, b)| a.cmp(b));
13101310
for (key, field) in fields {
13111311
custom_metadata.push_back(CustomMetadataFactoryInit {
13121312
key: key.clone(),

src/evidenceangel-ui/evidence_factory/http.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,15 @@ impl Component for ComponentModel {
5555

5656
gtk::ScrolledWindow {
5757
set_hexpand: true,
58+
set_vscrollbar_policy: gtk::PolicyType::Never,
5859

5960
gtk::TextView {
6061
add_css_class: "monospace",
6162
set_left_margin: 8,
6263
set_right_margin: 8,
6364
set_top_margin: 8,
6465
set_bottom_margin: 8,
66+
set_height_request: super::EVIDENCE_INNER_HEIGHT_REQUEST,
6567
set_halign: gtk::Align::Fill,
6668
set_valign: gtk::Align::Fill,
6769

@@ -80,13 +82,15 @@ impl Component for ComponentModel {
8082

8183
gtk::ScrolledWindow {
8284
set_hexpand: true,
85+
set_vscrollbar_policy: gtk::PolicyType::Never,
8386

8487
gtk::TextView {
8588
add_css_class: "monospace",
8689
set_left_margin: 8,
8790
set_right_margin: 8,
8891
set_top_margin: 8,
8992
set_bottom_margin: 8,
93+
set_height_request: super::EVIDENCE_INNER_HEIGHT_REQUEST,
9094
set_halign: gtk::Align::Fill,
9195
set_valign: gtk::Align::Fill,
9296

src/evidenceangel-ui/evidence_factory/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ mod rich_text;
2222
mod text;
2323

2424
const EVIDENCE_HEIGHT_REQUEST: i32 = 300;
25+
const EVIDENCE_INNER_HEIGHT_REQUEST: i32 = 100;
2526
const HTTP_SEPARATOR: char = '\x1e';
2627

2728
pub struct EvidenceFactoryModel {
@@ -271,7 +272,7 @@ impl FactoryComponent for EvidenceFactoryModel {
271272
widgets.evidence_child.set_child(Some(component.widget()));
272273
self.sub_component = Box::new(component);
273274
}
274-
};
275+
}
275276

276277
widgets
277278
}

src/evidenceangel-ui/evidence_factory/rich_text.rs

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -117,40 +117,36 @@ impl Component for ComponentModel {
117117
// Text
118118
#[name = "frame"]
119119
gtk::Frame {
120-
gtk::ScrolledWindow {
121-
set_height_request: 200,
122-
set_hexpand: true,
123-
124-
#[name = "text_view"]
125-
gtk::TextView {
126-
set_left_margin: 8,
127-
set_right_margin: 8,
128-
set_top_margin: 8,
129-
set_bottom_margin: 8,
130-
set_wrap_mode: gtk::WrapMode::Word,
131-
132-
#[name = "text_buffer"]
133-
#[wrap(Some)]
134-
set_buffer = &gtk::TextBuffer {
135-
set_text: &init.text,
136-
connect_changed => ComponentInput::Internal(ComponentInputInternal::TextChanged) @signal_text_changed,
137-
},
120+
#[name = "text_view"]
121+
gtk::TextView {
122+
set_left_margin: 8,
123+
set_right_margin: 8,
124+
set_top_margin: 8,
125+
set_bottom_margin: 8,
126+
set_height_request: super::EVIDENCE_INNER_HEIGHT_REQUEST,
127+
set_wrap_mode: gtk::WrapMode::Word,
128+
129+
#[name = "text_buffer"]
130+
#[wrap(Some)]
131+
set_buffer = &gtk::TextBuffer {
132+
set_text: &init.text,
133+
connect_changed => ComponentInput::Internal(ComponentInputInternal::TextChanged) @signal_text_changed,
134+
},
138135

139-
add_controller = gtk::ShortcutController {
140-
add_shortcut = gtk::Shortcut {
141-
#[wrap(Some)]
142-
set_trigger = gtk::ShortcutTrigger::parse_string("<primary>B").unwrap(),
143-
#[wrap(Some)]
144-
set_action = gtk::ShortcutAction::parse_string("action(rich-text-editor.bold)").unwrap(),
145-
},
146-
add_shortcut = gtk::Shortcut {
147-
#[wrap(Some)]
148-
set_trigger = gtk::ShortcutTrigger::parse_string("<primary>I").unwrap(),
149-
#[wrap(Some)]
150-
set_action = gtk::ShortcutAction::parse_string("action(rich-text-editor.italic)").unwrap(),
151-
},
136+
add_controller = gtk::ShortcutController {
137+
add_shortcut = gtk::Shortcut {
138+
#[wrap(Some)]
139+
set_trigger = gtk::ShortcutTrigger::parse_string("<primary>B").unwrap(),
140+
#[wrap(Some)]
141+
set_action = gtk::ShortcutAction::parse_string("action(rich-text-editor.bold)").unwrap(),
152142
},
153-
}
143+
add_shortcut = gtk::Shortcut {
144+
#[wrap(Some)]
145+
set_trigger = gtk::ShortcutTrigger::parse_string("<primary>I").unwrap(),
146+
#[wrap(Some)]
147+
set_action = gtk::ShortcutAction::parse_string("action(rich-text-editor.italic)").unwrap(),
148+
},
149+
},
154150
}
155151
},
156152
}

src/evidenceangel-ui/evidence_factory/text.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,18 @@ impl Component for ComponentModel {
3838
view! {
3939
#[root]
4040
gtk::Frame {
41-
gtk::ScrolledWindow {
42-
set_height_request: 100,
43-
set_hexpand: true,
41+
gtk::TextView {
42+
set_left_margin: 8,
43+
set_right_margin: 8,
44+
set_top_margin: 8,
45+
set_bottom_margin: 8,
46+
set_height_request: super::EVIDENCE_INNER_HEIGHT_REQUEST,
4447

45-
gtk::TextView {
46-
set_left_margin: 8,
47-
set_right_margin: 8,
48-
set_top_margin: 8,
49-
set_bottom_margin: 8,
50-
51-
#[name = "text_buffer"]
52-
#[wrap(Some)]
53-
set_buffer = &gtk::TextBuffer {
54-
set_text: &init.text,
55-
connect_changed => ComponentInput::Internal(ComponentInputInternal::TextChanged),
56-
}
48+
#[name = "text_buffer"]
49+
#[wrap(Some)]
50+
set_buffer = &gtk::TextBuffer {
51+
set_text: &init.text,
52+
connect_changed => ComponentInput::Internal(ComponentInputInternal::TextChanged),
5753
}
5854
}
5955
}

0 commit comments

Comments
 (0)