Skip to main content

lfsx_server/
model.rs

1use serde::{Deserialize, Serialize};
2
3use crate::locks::Lock;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
6#[serde(rename_all = "lowercase")]
7pub enum Operation {
8    Upload,
9    Download,
10}
11
12#[derive(Debug, Clone, Deserialize, Serialize)]
13pub struct ObjectId {
14    pub oid: String,
15    pub size: u64,
16}
17
18#[derive(Debug, Deserialize)]
19pub struct BatchRequest {
20    pub operation: Operation,
21    #[serde(default)]
22    pub transfers: Vec<String>,
23    pub objects: Vec<ObjectId>,
24    #[serde(rename = "ref")]
25    pub reference: Option<Reference>,
26}
27
28#[derive(Debug, Deserialize)]
29pub struct RetainRequest {
30    pub oids: Vec<String>,
31    #[serde(default)]
32    pub dry_run: bool,
33}
34
35#[derive(Debug, Deserialize)]
36pub struct CompressRequest {
37    #[serde(default)]
38    pub dry_run: bool,
39}
40
41#[derive(Debug, Deserialize)]
42pub struct DedupeRequest {
43    #[serde(default)]
44    pub dry_run: bool,
45}
46
47#[derive(Debug, Serialize)]
48pub struct BatchResponse {
49    pub transfer: &'static str,
50    pub objects: Vec<ObjectSpec>,
51}
52
53#[derive(Debug, Serialize)]
54pub struct ObjectSpec {
55    #[serde(flatten)]
56    pub id: ObjectId,
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub actions: Option<Actions>,
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub error: Option<ObjectError>,
61}
62
63#[derive(Debug, Default, Serialize)]
64pub struct Actions {
65    #[serde(skip_serializing_if = "Option::is_none")]
66    pub upload: Option<Action>,
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub download: Option<Action>,
69    #[serde(skip_serializing_if = "Option::is_none")]
70    pub verify: Option<Action>,
71}
72
73#[derive(Debug, Serialize)]
74pub struct Action {
75    pub href: String,
76    pub expires_in: u32,
77}
78
79#[derive(Debug, Serialize)]
80pub struct ObjectError {
81    pub code: u16,
82    pub message: String,
83}
84
85impl ObjectSpec {
86    pub fn missing(id: ObjectId) -> Self {
87        Self {
88            id,
89            actions: None,
90            error: Some(ObjectError {
91                code: 404,
92                message: "object not found".into(),
93            }),
94        }
95    }
96
97    pub fn too_large(id: ObjectId, limit: u64) -> Self {
98        Self {
99            error: Some(ObjectError {
100                code: 413,
101                message: format!(
102                    "object is {} bytes, over the {limit} byte limit this server accepts",
103                    id.size
104                ),
105            }),
106            id,
107            actions: None,
108        }
109    }
110
111    pub fn over_quota(id: ObjectId, used: u64, limit: u64) -> Self {
112        Self {
113            id,
114            actions: None,
115            error: Some(ObjectError {
116                code: 507,
117                message: format!(
118                    "this repository holds {used} bytes of its {limit} byte budget — collect what \
119                     it no longer references, or ask for more room"
120                ),
121            }),
122        }
123    }
124}
125
126#[derive(Debug, Deserialize)]
127pub struct CreateLockRequest {
128    pub path: String,
129}
130
131#[derive(Debug, Deserialize)]
132pub struct ListLocksQuery {
133    pub path: Option<String>,
134    pub id: Option<String>,
135    pub cursor: Option<String>,
136    pub limit: Option<usize>,
137    // Accepted and not acted on: see `refs` in the README. Rejecting it would
138    // break a client that sends what the specification tells it to send.
139    #[serde(rename = "refspec")]
140    pub refspec: Option<String>,
141}
142
143#[derive(Debug, Default, Deserialize)]
144pub struct VerifyLocksRequest {
145    pub cursor: Option<String>,
146    pub limit: Option<usize>,
147    #[serde(rename = "ref")]
148    pub reference: Option<Reference>,
149}
150
151#[derive(Debug, Deserialize)]
152pub struct Reference {
153    pub name: String,
154}
155
156#[derive(Debug, Deserialize)]
157pub struct UnlockRequest {
158    #[serde(default)]
159    pub force: bool,
160}
161
162#[derive(Debug, Serialize)]
163pub struct LockResponse {
164    pub lock: Lock,
165}
166
167#[derive(Debug, Serialize)]
168pub struct ListLocksResponse {
169    pub locks: Vec<Lock>,
170    #[serde(skip_serializing_if = "String::is_empty")]
171    pub next_cursor: String,
172}
173
174#[derive(Debug, Serialize)]
175pub struct VerifyLocksResponse {
176    pub ours: Vec<Lock>,
177    pub theirs: Vec<Lock>,
178    #[serde(skip_serializing_if = "String::is_empty")]
179    pub next_cursor: String,
180}
181
182#[derive(Debug, Serialize)]
183pub struct StatsResponse {
184    pub objects: u64,
185    pub bytes: u64,
186    pub locks: usize,
187}