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
//! The syncing process consists of three stages. //! First you call `ubiquity::detect::find_updates` with a few of arguments //! which tell Ubiquity where to look for changed files. It will return a list of files that differ between replicas. //! //! You can do whatever you like with that list, but most often you want to resolve those differences. //! You can use an algorithm, user input, or a hardcoded value to determine which replica is the 'master' replica for each difference. //! The 'master' is the correct, most up to date version of the file that will be propagated to all other replicas. //! //! Ubiquity comes with the `ubiquity::reconcile::guess_operation` function which will pick whichever file changed since the last run, or `None` if no files change, or if files changed on both sides. //! //! Once you have the 'master' replica, you can propagate changes using `ubiquity::propagate::propagate`. //! //! # Examples //! ``` //! extern crate ubiquity; //! extern crate regex; //! extern crate typenum; //! #[macro_use] //! extern crate generic_array; //! //! use std::path::{Path, PathBuf}; //! use std::fs; //! use ubiquity::{archive, detect, reconcile, propagate}; //! use ubiquity::config::{SyncInfo}; //! use regex::Regex; //! //! fn main() { //! let archive = archive::Archive::new(Path::new("tests/replicas/archives").to_path_buf()).unwrap(); //! //! let a = Path::new("tests/replicas/path_a"); //! let b = Path::new("tests/replicas/path_b"); //! if !a.is_dir() { //! fs::create_dir(a).unwrap(); //! } //! if !b.is_dir() { //! fs::create_dir(b).unwrap(); //! } //! //! let mut config: SyncInfo = SyncInfo::new(arr![PathBuf; PathBuf::from("tests/replicas/path_a"), PathBuf::from("tests/replicas/path_b")]); //! config.ignore.regexes.push(Regex::new(r".DS_Store").unwrap()); //! config.ignore.paths.push("Microsoft User Data".to_string()); //! //! let mut search = detect::SearchDirectories::from_root(); //! //! let result = detect::find_updates(&archive, &mut search, &config, &detect::EmptyProgressCallback).expect("Failed to find conflicts"); //! //! if result.differences.is_empty() { //! println!("All in sync"); //! } //! //! for difference in result.differences { //! let operation = reconcile::guess_operation(&difference); //! println!("Difference at {:?}, resolving using {:?}", difference.path, operation); //! if let reconcile::Operation::PropagateFromMaster(master) = operation { //! propagate::propagate(&difference, master, &archive, &propagate::DefaultPropagationOptions, &propagate::EmptyProgressCallback).unwrap(); //! } //! } //! } //! ``` #![feature(plugin)] #![feature(question_mark)] #![feature(custom_derive)] #![plugin(serde_macros)] extern crate fnv; #[macro_use] extern crate bincode; extern crate serde; extern crate regex; extern crate byteorder; #[macro_use] extern crate log; extern crate walkdir; extern crate fs2; extern crate generic_array; extern crate typenum; /// Detects differences between replicas pub mod detect; /// Makes suggestions on how to resolve differences between replicas pub mod reconcile; /// Propagates changes from a master replica to all others pub mod propagate; /// Handles the serialization and deserialization of archive data pub mod archive; /// Core structures for representing the state of the filesystem pub mod state; /// Configuration for the whole system pub mod config; /// Error handling pub mod error; mod compare_files; mod util;