aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRuben Beltran del Rio <git@r.bdr.sh>2024-03-09 14:17:34 +0100
committerRuben Beltran del Rio <git@r.bdr.sh>2024-03-09 14:17:34 +0100
commit172f4c8807d44ebe38c7f227b7fdc2d6a9dbe323 (patch)
treeb880761cf254fbc668cea0d577d5331a28af67cc /src
parent36a4680d18de012e2e5c732f9db161dafa884344 (diff)
Allow sync up and down
Diffstat (limited to 'src')
-rw-r--r--src/command/add_remote.rs6
-rw-r--r--src/command/remove_remote.rs7
-rw-r--r--src/command/sync_down.rs16
-rw-r--r--src/command/sync_up.rs6
-rw-r--r--src/main.rs1
-rw-r--r--src/remote/git.rs60
-rw-r--r--src/remote/mod.rs65
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)
+}