diff options
| author | Ruben Beltran del Rio <git@r.bdr.sh> | 2024-03-09 14:17:34 +0100 |
|---|---|---|
| committer | Ruben Beltran del Rio <git@r.bdr.sh> | 2024-03-09 14:17:34 +0100 |
| commit | 172f4c8807d44ebe38c7f227b7fdc2d6a9dbe323 (patch) | |
| tree | b880761cf254fbc668cea0d577d5331a28af67cc /src | |
| parent | 36a4680d18de012e2e5c732f9db161dafa884344 (diff) | |
Allow sync up and down
Diffstat (limited to 'src')
| -rw-r--r-- | src/command/add_remote.rs | 6 | ||||
| -rw-r--r-- | src/command/remove_remote.rs | 7 | ||||
| -rw-r--r-- | src/command/sync_down.rs | 16 | ||||
| -rw-r--r-- | src/command/sync_up.rs | 6 | ||||
| -rw-r--r-- | src/main.rs | 1 | ||||
| -rw-r--r-- | src/remote/git.rs | 60 | ||||
| -rw-r--r-- | src/remote/mod.rs | 65 |
7 files changed, 138 insertions, 23 deletions
diff --git a/src/command/add_remote.rs b/src/command/add_remote.rs index ad7be83..040e572 100644 --- a/src/command/add_remote.rs +++ b/src/command/add_remote.rs @@ -1,6 +1,6 @@ -use std::fs::{create_dir_all, write}; use std::io::Result; use crate::configuration::Configuration; +use crate::remote::add; pub struct AddRemote; @@ -16,10 +16,8 @@ impl super::Command for AddRemote { } fn execute(&self, input: Option<&String>, configuration: &Configuration, _: &String) -> Result<()> { - create_dir_all(&configuration.config_directory)?; let input = input.expect("You must provide a location for the remote."); - write(&configuration.remote_config, input)?; - return Ok(()) + add(&configuration.config_directory, &configuration.remote_config, input) } fn after_dependencies(&self) -> Vec<Box<dyn super::Command>> { diff --git a/src/command/remove_remote.rs b/src/command/remove_remote.rs index b2f554c..7590487 100644 --- a/src/command/remove_remote.rs +++ b/src/command/remove_remote.rs @@ -1,6 +1,6 @@ -use std::fs::remove_file; use std::io::Result; use crate::configuration::Configuration; +use crate::remote::remove; pub struct RemoveRemote; @@ -16,10 +16,7 @@ impl super::Command for RemoveRemote { } fn execute(&self, _: Option<&String>, configuration: &Configuration, _: &String) -> Result<()> { - if configuration.remote_config.exists() { - remove_file(&configuration.remote_config)?; - } - return Ok(()) + remove(&configuration.remote_config) } fn after_dependencies(&self) -> Vec<Box<dyn super::Command>> { diff --git a/src/command/sync_down.rs b/src/command/sync_down.rs index dc4114e..bba34b2 100644 --- a/src/command/sync_down.rs +++ b/src/command/sync_down.rs @@ -1,6 +1,6 @@ -use std::fs::create_dir_all; -use std::io::{Result, Error}; +use std::io::{Result}; use crate::configuration::Configuration; +use crate::remote::sync_down; pub struct SyncDown; @@ -16,16 +16,10 @@ impl super::Command for SyncDown { } fn execute(&self, _: Option<&String>, configuration: &Configuration, command: &String) -> Result<()> { - match create_dir_all(&configuration.data_directory) { - Ok(_) => { - // We only care to show these warnings if this is the primary command. - if command == self.command() { - println!("WARNING: Sync Down Not yet implemented"); - } - return Ok(()) - }, - Err(e) => Err(Error::new(e.kind(), format!("Could not create data directory"))) + if command == self.command() { + return sync_down(&configuration.data_directory, &configuration.remote_config); } + return Ok(()) } fn after_dependencies(&self) -> Vec<Box<dyn super::Command>> { diff --git a/src/command/sync_up.rs b/src/command/sync_up.rs index 635de10..a5d2a4c 100644 --- a/src/command/sync_up.rs +++ b/src/command/sync_up.rs @@ -1,5 +1,6 @@ use std::io::Result; use crate::configuration::Configuration; +use crate::remote::sync_up; pub struct SyncUp; @@ -14,9 +15,8 @@ impl super::Command for SyncUp { vec![] } - fn execute(&self, input: Option<&String>, _: &Configuration, _: &String) -> Result<()> { - println!("Sync Up: {:?}!", input); - return Ok(()) + fn execute(&self, _: Option<&String>, configuration: &Configuration, _: &String) -> Result<()> { + sync_up(&configuration.data_directory, &configuration.remote_config) } fn after_dependencies(&self) -> Vec<Box<dyn super::Command>> { diff --git a/src/main.rs b/src/main.rs index a0a9fef..8867dc0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ mod metadata; mod post; mod template; mod utils; +mod remote; use std::iter::once; use std::env::args; diff --git a/src/remote/git.rs b/src/remote/git.rs new file mode 100644 index 0000000..a4c1c28 --- /dev/null +++ b/src/remote/git.rs @@ -0,0 +1,60 @@ +use std::io::Result; +use std::path::PathBuf; +use std::process::Command; +use std::time::{SystemTime, UNIX_EPOCH}; + +pub struct Git; + +impl Git { + pub fn new() -> Self { + Git + } +} + +impl super::Remote for Git { + fn can_handle(&self, _: &str) -> bool { + // If we ever implement another remote we will want a check strategy + true + } + + fn sync_up(&self, remote: &str, directory: &PathBuf) -> Result<()> { + let timestamp = SystemTime::now().duration_since(UNIX_EPOCH) + .expect("Invalid time") + .as_millis(); + + let commands = vec![ + format!("cd {} && git init -b main", directory.display()), + format!("cd {} && git add .", directory.display()), + format!("cd {} && git commit --allow-empty -m blog-sync-up-{}", directory.display(), timestamp), + format!("cd {} && git push {} main --force", directory.display(), remote), + ]; + + for command in commands { + Command::new("sh") + .arg("-c") + .arg(&command) + .status() + .expect("Failed while performing sync up with git"); + } + + Ok(()) + } + + fn sync_down(&self, remote: &str, directory: &PathBuf) -> Result<()> { + let commands = vec![ + format!("cd {} && git init -b main", directory.display()), + format!("cd {} && git checkout .", directory.display()), + format!("cd {} && git clean . -f", directory.display()), + format!("cd {} && git pull {} main", directory.display(), remote), + ]; + + for command in commands { + Command::new("sh") + .arg("-c") + .arg(&command) + .status() + .expect("Failed while performing sync down with git"); + } + Ok(()) + } +} diff --git a/src/remote/mod.rs b/src/remote/mod.rs index e69de29..de90ef5 100644 --- a/src/remote/mod.rs +++ b/src/remote/mod.rs @@ -0,0 +1,65 @@ +mod git; + +use std::fs::{create_dir_all, remove_file, write, File}; +use std::io::{Error, ErrorKind::Other, Read, Result}; +use std::path::PathBuf; + +use git::Git; + +pub trait Remote { + fn can_handle(&self, remote: &str) -> bool; + fn sync_up(&self, remote: &str, directory: &PathBuf) -> Result<()>; + fn sync_down(&self, remote: &str, directory: &PathBuf) -> Result<()>; +} + +pub fn add(config_directory: &PathBuf, remote_config: &PathBuf, remote: &String) -> Result<()> { + create_dir_all(config_directory)?; + write(remote_config, remote)?; + Ok(()) +} + +pub fn remove(remote_config: &PathBuf) -> Result<()> { + if remote_config.exists() { + remove_file(remote_config)? + } + Ok(()) +} + +pub fn sync_up(data_directory: &PathBuf, remote_config: &PathBuf) -> Result<()> { + let remote_address = read_remote(remote_config) + .expect("No remote is configured"); + create_dir_all(data_directory)?; + let remotes = available_remotes(); + for remote in remotes { + if remote.can_handle(&remote_address) { + return remote.sync_up(&remote_address, data_directory); + } + } + Err(Error::new(Other, "No valid strategies found for your configured remote.")) +} + +pub fn sync_down(data_directory: &PathBuf, remote_config: &PathBuf) -> Result<()> { + let remote_address = read_remote(remote_config) + .expect("No remote is configured"); + create_dir_all(data_directory)?; + let remotes = available_remotes(); + for remote in remotes { + if remote.can_handle(&remote_address) { + return remote.sync_down(&remote_address, data_directory); + } + } + Err(Error::new(Other, "No valid strategies found for your configured remote.")) +} + +fn available_remotes() -> Vec<Box<dyn Remote>> { + vec![ + Box::new(Git::new()) + ] +} + +fn read_remote(file_path: &PathBuf) -> Option<String> { + let mut file = File::open(file_path).ok()?; + let mut contents = String::new(); + file.read_to_string(&mut contents).ok()?; + Some(contents) +} |