diff options
Diffstat (limited to 'src/document/changes.rs')
| -rw-r--r-- | src/document/changes.rs | 21 |
1 files changed, 11 insertions, 10 deletions
diff --git a/src/document/changes.rs b/src/document/changes.rs index 345f151..0409c50 100644 --- a/src/document/changes.rs +++ b/src/document/changes.rs @@ -67,24 +67,20 @@ pub(crate) fn change_from_bytes(bytes: Vec<u8>, hash: ChangeHash) -> Result<Chan /// The bytes of the delta from `from` to `to` in `doc`: the changes in the history of /// `to` but not of `from`, each as encoded, sorted by hash and concatenated -/// (`load_delta` reads that). The same on every node holding `to`, whatever else it -/// has. None if `doc` lacks part of `to`. +/// (`load_delta` reads that). The same on every node holding `to` and `from`, whatever +/// else it has. None if `doc` lacks part of either: without one of `from`, the delta +/// would carry that one's history too, where `to` shares it, and differ from another +/// node's (a download takes chunks from several, checked against one's manifest). pub(crate) fn delta_bytes( doc: &Document, from: &[ChangeHash], to: &[ChangeHash], ) -> Option<Vec<u8>> { - if !missing(doc, to).is_empty() { + if !missing(doc, to).is_empty() || !missing(doc, from).is_empty() { return None; } - // Heads of `from` we don't have can't hide anything we have. - let from: Vec<ChangeHash> = from - .iter() - .copied() - .filter(|head| doc.get_change_by_hash(head).is_some()) - .collect(); let since: HashMap<ChangeHash, (Vec<ChangeHash>, Vec<u8>)> = doc - .get_changes(&from) + .get_changes(from) .iter() .map(|change| { ( @@ -181,7 +177,12 @@ mod tests { fn no_delta_without_its_heads() { let mut doc = Document::new(); change(&mut doc, |doc| doc.put(ROOT, "k", 1_i64).unwrap()); + let heads = doc.get_heads(); assert!(delta_bytes(&doc, &[], &[ChangeHash([7; 32])]).is_none()); + assert!( + delta_bytes(&doc, &[ChangeHash([7; 32])], &heads).is_none(), + "nor without where it starts" + ); } /// A change loads from its bytes only as the change it was asked for. |
