//! The replicated document: the replica with its epoch, and the store semantics //! (merged-view paths over JSON) the HTTP API and remakes work with. /// The engine's types, under the names the rest of the crate uses: the document /// (Automerge's `AutoCommit`), its changes and their hashes, and its writers (actors). /// Only `document` and `remake` use Automerge itself (`architecture.md`, The document). pub(crate) use automerge::{ActorId, AutoCommit as Document, Change, ChangeHash}; pub(crate) mod changes; pub(crate) mod file; pub(crate) mod lock; pub(crate) mod meta; pub(crate) mod replica; pub(crate) mod store; #[cfg(test)] mod tests { use std::path::{Path, PathBuf}; /// Every `.rs` file under `dir`. fn sources(dir: &Path, out: &mut Vec) { for entry in std::fs::read_dir(dir).unwrap() { let path = entry.unwrap().path(); if path.is_dir() { sources(&path, out); } else if path.extension().is_some_and(|extension| extension == "rs") { out.push(path); } } } /// Automerge is used only in `document`, `remake` and the sync session /// (`state/session.rs`); the rest of the node names its types as `document` /// re-exports them and works through `document` (`architecture.md`, The document). #[test] fn automerge_stays_behind_document() { let src = Path::new(env!("CARGO_MANIFEST_DIR")).join("src"); let allowed = [ src.join("document"), src.join("remake"), src.join("state").join("session.rs"), ]; let mut files = Vec::new(); sources(&src, &mut files); let mut found = Vec::new(); for file in files .iter() .filter(|file| !allowed.iter().any(|allowed| file.starts_with(allowed))) { let text = std::fs::read_to_string(file).unwrap(); for (number, line) in text.lines().enumerate() { if line.contains("automerge::") || line.trim_start().starts_with("use automerge") { found.push(format!( "{}:{}: {}", file.display(), number + 1, line.trim() )); } } } assert!( found.is_empty(), "Automerge used outside `document`:\n{}", found.join("\n") ); } }