lb_rs/model/
server_ops.rs1use super::errors::{DiffError, LbErrKind, LbResult};
2use crate::model::clock::get_time;
3use crate::model::file_like::FileLike;
4use crate::model::file_metadata::FileDiff;
5use crate::model::lazy::{LazyStaged1, LazyTree};
6use crate::model::server_file::{IntoServerFile, ServerFile};
7use crate::model::server_tree::ServerTree;
8use crate::model::signed_file::SignedFile;
9use crate::model::tree_like::TreeLike;
10
11type LazyServerStaged1<'a> = LazyStaged1<ServerTree<'a>, Vec<ServerFile>>;
12
13impl<'a> LazyTree<ServerTree<'a>> {
14 pub fn stage_diff(self, changes: Vec<FileDiff<SignedFile>>) -> LbResult<LazyServerStaged1<'a>> {
17 for change in &changes {
19 if let Some(old) = &change.old {
20 if old.id() != change.new.id() {
21 return Err(LbErrKind::Diff(DiffError::DiffMalformed))?;
22 }
23 }
24 }
25
26 for change in &changes {
28 match &change.old {
29 Some(old) => {
30 if old.timestamped_value.value.document_hmac
31 != change.new.timestamped_value.value.document_hmac
32 {
33 return Err(LbErrKind::Diff(DiffError::HmacModificationInvalid))?;
34 }
35 }
36 None => {
37 if change.new.timestamped_value.value.document_hmac.is_some() {
38 return Err(LbErrKind::Diff(DiffError::HmacModificationInvalid))?;
39 }
40 }
41 }
42 }
43
44 for change in &changes {
46 match &change.old {
47 Some(old) => {
48 let current = &self
49 .maybe_find(old.id())
50 .ok_or(LbErrKind::Diff(DiffError::OldFileNotFound))?
51 .file;
52 if current != old {
53 return Err(LbErrKind::Diff(DiffError::OldVersionIncorrect))?;
54 }
55 }
56 None => {
57 if self.tree.files.maybe_find(change.new.id()).is_some() {
59 return Err(LbErrKind::Diff(DiffError::OldVersionRequired))?;
60 }
61 }
62 }
63 }
64
65 let now = get_time().0 as u64;
66 let changes = changes
67 .into_iter()
68 .map(|change| change.new.add_time(now))
69 .collect();
70
71 Ok(self.stage(changes))
72 }
73}