1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use crate::fragment::Fragment;
use crate::trailer::Trailer;
use std::convert::TryFrom;
#[derive(Debug, PartialEq, Clone)]
pub struct Trailers {
trailers: Vec<Trailer>,
}
impl From<Vec<Trailer>> for Trailers {
fn from(trailers: Vec<Trailer>) -> Self {
Trailers { trailers }
}
}
impl From<Trailers> for String {
fn from(trailers: Trailers) -> Self {
trailers
.trailers
.into_iter()
.map(String::from)
.collect::<Vec<_>>()
.join("\n")
}
}
impl From<Vec<Fragment>> for Trailers {
fn from(ast: Vec<Fragment>) -> Self {
ast.into_iter()
.filter_map(|values| {
if let Fragment::Body(body) = values {
Some(body)
} else {
None
}
})
.rev()
.filter_map(|body| {
if body.is_empty() {
None
} else {
Some(Trailer::try_from(body))
}
})
.take_while(std::result::Result::is_ok)
.flatten()
.collect::<Vec<Trailer>>()
.into_iter()
.rev()
.collect::<Vec<Trailer>>()
.into()
}
}
#[cfg(test)]
mod tests {
use super::Trailers;
use crate::fragment::Fragment;
use crate::trailer::Trailer;
use crate::Body;
use indoc::indoc;
use pretty_assertions::assert_eq;
#[test]
fn it_can_give_me_it_as_a_string() {
let trailers = Trailers::from(vec![Trailer::new(
"Co-authored-by",
"Billie Thompson <billie@example.com>",
)]);
assert_eq!(
String::from(trailers),
String::from("Co-authored-by: Billie Thompson <billie@example.com>")
)
}
#[test]
fn it_can_be_constructed_from_ast() {
let trailers = vec![
Fragment::Body(Body::from("Example Commit")),
Fragment::Body(Body::default()),
Fragment::Body(Body::from(indoc!(
"
This is an example commit. This is to illustrate something for a test and would be
pretty unusual to find in an actual git history.
"
))),
Fragment::Body(Body::default()),
Fragment::Body(Body::from(
"Co-authored-by: Billie Thompson <billie@example.com>",
)),
Fragment::Body(Body::from(
"Co-authored-by: Somebody Else <somebody@example.com>",
)),
];
let expected: Trailers = vec![
Trailer::new("Co-authored-by", "Billie Thompson <billie@example.com>"),
Trailer::new("Co-authored-by", "Somebody Else <somebody@example.com>"),
]
.into();
assert_eq!(Trailers::from(trailers), expected)
}
}