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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
// Back - An extremely simple git issue tracking system. Inspired by tvix's
// panettone
//
// Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de>
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This file is part of Back.
//
// You should have received a copy of the License along with this program.
// If not, see <https://www.gnu.org/licenses/agpl.txt>.
use std::convert::Infallible;
use operation_type::OperationType;
use serde::Deserialize;
use serde_json::Value;
use crate::{
get,
git_bug::format::{MarkDown, TimeStamp},
};
use super::{entity, label::Label, Status};
pub mod operation_type;
#[derive(Deserialize, Debug)]
#[serde(try_from = "Value")]
pub enum Operation {
AddComment {
timestamp: TimeStamp,
message: MarkDown,
},
Create {
timestamp: TimeStamp,
title: MarkDown,
message: MarkDown,
},
EditComment {
timestamp: TimeStamp,
target: entity::Id,
message: MarkDown,
},
LabelChange {
timestamp: TimeStamp,
added: Vec<Label>,
removed: Vec<Label>,
},
SetStatus {
timestamp: TimeStamp,
status: Status,
},
SetTitle {
timestamp: TimeStamp,
title: MarkDown,
was: MarkDown,
},
// These seem to be just weird non-operation, operations.
// defined in: git-bug/entities/bug/operation.go
NoOp {},
SetMetadata {},
}
impl TryFrom<Value> for Operation {
type Error = Infallible;
fn try_from(value: Value) -> Result<Self, Self::Error> {
let operation_type = OperationType::from_json_int(
value
.get("type")
.expect("Should exist")
.as_u64()
.expect("This should work"),
);
let op = match operation_type {
OperationType::AddComment => Self::AddComment {
timestamp: get! {value, "timestamp" },
message: get! {value, "message"},
},
OperationType::Create => Self::Create {
timestamp: get! {value, "timestamp"},
title: get! {value, "title"},
message: get! {value, "message"},
},
OperationType::EditComment => Self::EditComment {
timestamp: get! {value, "timestamp"},
target: get! {value, "target"},
message: get! {value, "message"},
},
OperationType::LabelChange => Self::LabelChange {
timestamp: get! {value, "timestamp"},
added: serde_json::from_value(
value
.get("added")
.expect("This should be available")
.to_owned(),
)
.expect("This should be parsable"),
removed: serde_json::from_value(
value
.get("removed")
.expect("This should be available")
.to_owned(),
)
.expect("This should be parsable"),
},
OperationType::SetStatus => Self::SetStatus {
timestamp: get! {value, "timestamp"},
status: get! {value, "status"},
},
OperationType::SetTitle => Self::SetTitle {
timestamp: get! {value, "timestamp"},
title: get! {value, "title"},
was: get! {value, "was"},
},
OperationType::NoOp => Self::NoOp {},
OperationType::SetMetadata => Self::SetMetadata {},
};
Ok(op)
}
}
|