Skip to content

Commit

Permalink
Restore syncing between devices functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
leroycep committed Aug 11, 2019
1 parent 29f057b commit 0de1d00
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 14 deletions.
27 changes: 20 additions & 7 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ pub enum Error {

#[snafu(display("Error importing data: {}", source))]
ImportError { source: Box<dyn std::error::Error> },

#[snafu(display("Errors synchronizing data: {:?}", errors))]
SyncError {
errors: Vec<RepositoryError<SyncFolderStoreError>>,
},
}

fn main() {
Expand All @@ -75,45 +80,53 @@ fn main() {
fn run() -> Result<(), Error> {
let opt = Opt::from_args();

// Load config
let conf_file = match opt.config {
Some(config_path) => config_path,
None => {
let proj_dirs = directories::ProjectDirs::from("xyz", "geemili", "augr").unwrap();
proj_dirs.config_dir().join("config.toml")
}
};

let conf = config::load_config(&conf_file).context(GetConfig {})?;

// Load store for own data
let store = SyncFolderStore::new(conf.sync_folder.into(), conf.device_id).should_init(true);
let mut repo = Repository::from_store(store).unwrap();

// Synchronize data
repo.try_sync_data()
.map_err(|errors| Error::SyncError { errors })?;
repo.save_meta().unwrap();

// Convert abstract patch data structure into a more conventional format
let eventgraph = repo.timesheet();
let timesheet = eventgraph
.flatten()
.map_err(|conflicts| Error::MergeConflicts { conflicts })?;

// Run command
match opt.cmd.unwrap_or(Command::default()) {
Command::Start(subcmd) => {
let patches = subcmd.exec(&timesheet);
for patch in patches {
let patch_ref = String::new();
let res = repo.add_patch(patch).unwrap();
println!("{}: {:?}", patch_ref, res);
println!("{}", patch.patch_ref());
repo.add_patch(patch).unwrap();
}
}
Command::Import(subcmd) => {
let patches = subcmd.exec(&timesheet).context(ImportError {})?;
for patch in patches {
let patch_ref = String::new();
let res = repo.add_patch(patch).unwrap();
println!("{}: {:?}", patch_ref, res);
println!("{}", patch.patch_ref());
repo.add_patch(patch).unwrap();
}
}
Command::Summary(subcmd) => subcmd.exec(&timesheet),
Command::Chart(subcmd) => subcmd.exec(&timesheet),
Command::Tags(subcmd) => subcmd.exec(&timesheet),
};

// Save which patches this device uses to disk
repo.save_meta().unwrap();

Ok(())
Expand Down
49 changes: 42 additions & 7 deletions core/src/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ where
conflicts: Vec<TimesheetError>,
patch: PatchRef,
},

#[snafu(display("IOError: {}", source))]
IOError { source: IE },
}

#[derive(Debug)]
Expand Down Expand Up @@ -114,17 +117,15 @@ where
&self.timesheet
}

fn load_all_patches(&mut self) -> Result<(), Vec<Error<S::Error>>> {
fn load_patches(
&mut self,
patches: impl Iterator<Item = PatchRef>,
) -> Result<(), Vec<Error<S::Error>>> {
let mut errors = Vec::new();

let mut error_on_loading: BTreeSet<PatchRef> = BTreeSet::new();

let meta = self
.store
.get_meta()
.context(LoadMeta {})
.map_err(|e| vec![e])?;
let mut patches_to_load: VecDeque<PatchRef> = meta.patches().cloned().collect();
let mut patches_to_load: VecDeque<PatchRef> = patches.collect();
while let Some(patch_ref) = patches_to_load.pop_front() {
let patch = match self.store.get_patch(&patch_ref) {
Ok(p) => p,
Expand Down Expand Up @@ -161,4 +162,38 @@ where
Ok(())
}
}

fn load_all_patches(&mut self) -> Result<(), Vec<Error<S::Error>>> {
let meta = self
.store
.get_meta()
.context(LoadMeta {})
.map_err(|e| vec![e])?;

self.load_patches(meta.patches().cloned())
}
}

use crate::store::sync_folder_store::{SyncFolderStore, SyncFolderStoreError};

impl Repository<SyncFolderStore> {
pub fn try_sync_data(&mut self) -> Result<(), Vec<Error<SyncFolderStoreError>>> {
let metas = self
.store
.get_other_metas()
.context(IOError {})
.map_err(|e| vec![e])?;

let patches_to_load: Vec<PatchRef> = metas
.filter_map(|x| x.ok())
.flat_map(|meta| {
meta.patches()
.map(|x| x.clone())
.collect::<Vec<_>>()
.into_iter()
})
.collect();

self.load_patches(patches_to_load.into_iter())
}
}
27 changes: 27 additions & 0 deletions core/src/store/sync_folder_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ pub enum SyncFolderStoreError {
source: std::io::Error,
path: PathBuf,
},

#[snafu(display("IO error: {}", source))]
IOError { source: std::io::Error },
}

impl SyncFolderStore {
Expand All @@ -70,6 +73,30 @@ impl SyncFolderStore {
.join(self.device_id.clone())
.with_extension("toml")
}

pub fn get_other_metas(
&self,
) -> Result<impl Iterator<Item = Result<Meta, SyncFolderStoreError>>, SyncFolderStoreError>
{
let meta_folder = self.root_folder.join("meta");
let meta_file = self.meta_file_path();

let sync_folder_items = meta_folder.read_dir().context(IOError {})?;
let iter = sync_folder_items
.filter_map(|d| d.ok())
.filter(move |dir_entry| dir_entry.path() != meta_file)
.map(|dir_entry| {
let path = dir_entry.path();
let contents = read_to_string(&path).context(ReadFile { path: path.clone() })?;

let meta = toml::de::from_str(&contents).context(DeserializeMeta {
device_id: path.display().to_string(),
})?;

Ok(meta)
});
Ok(iter)
}
}

impl Store for SyncFolderStore {
Expand Down

0 comments on commit 0de1d00

Please sign in to comment.