about summary refs log tree commit diff
path: root/src/actions
diff options
context:
space:
mode:
Diffstat (limited to 'src/actions')
-rw-r--r--src/actions/create.rs20
-rw-r--r--src/actions/mod.rs30
-rw-r--r--src/actions/shift.rs55
-rw-r--r--src/actions/update.rs80
4 files changed, 185 insertions, 0 deletions
diff --git a/src/actions/create.rs b/src/actions/create.rs
new file mode 100644
index 0000000..26d20c8
--- /dev/null
+++ b/src/actions/create.rs
@@ -0,0 +1,20 @@
+use std::{fs, io};
+
+use crate::{actions::update, files::Locations};
+
+use super::ActionOptions;
+
+pub fn create(command_options: ActionOptions) -> io::Result<()> {
+    let locations = Locations::from(&command_options);
+
+    if locations.ka_path.exists() {
+        fs::remove_dir_all(locations.ka_path.as_path())?;
+    }
+
+    fs::create_dir(locations.ka_path)?;
+    fs::create_dir(locations.ka_files_path)?;
+
+    update(command_options)?;
+
+    Ok(())
+}
diff --git a/src/actions/mod.rs b/src/actions/mod.rs
new file mode 100644
index 0000000..588ce8f
--- /dev/null
+++ b/src/actions/mod.rs
@@ -0,0 +1,30 @@
+mod create;
+mod shift;
+mod update;
+
+use std::path::{Path, PathBuf};
+
+pub use create::create;
+pub use shift::shift;
+pub use update::update;
+
+pub struct ActionOptions {
+    pub repository_path: PathBuf,
+}
+
+impl ActionOptions {
+    pub fn from_path(path: &str) -> Self {
+        ActionOptions {
+            repository_path: Path::new(path).to_path_buf(),
+        }
+    }
+
+    pub fn from_pwd() -> Result<Self, ()> {
+        let current_path = std::env::current_dir();
+        if let Ok(repository_path) = current_path {
+            Ok(ActionOptions { repository_path })
+        } else {
+            Err(())
+        }
+    }
+}
diff --git a/src/actions/shift.rs b/src/actions/shift.rs
new file mode 100644
index 0000000..c02f0ed
--- /dev/null
+++ b/src/actions/shift.rs
@@ -0,0 +1,55 @@
+use std::{
+    fs,
+    io::{self, Seek, Write},
+    path::Path,
+};
+
+use crate::{
+    files::{Locations, RepositoryPaths},
+    history::FileHistory,
+};
+
+use super::ActionOptions;
+
+pub fn shift(command_options: ActionOptions, path: &str, new_cursor: usize) -> io::Result<()> {
+    let locations = Locations::from(&command_options);
+
+    match RepositoryPaths::from_tracked(&locations, Path::new(path)) {
+        RepositoryPaths::Tracked(tracked) => {
+            let mut history_file = tracked.load_history_file()?;
+
+            let mut file_history = FileHistory::from_file(&mut history_file).unwrap();
+            file_history.set_cursor(new_cursor);
+
+            if file_history.file_is_deleted() {
+                fs::remove_file(path)?;
+            } else {
+                let new_content = file_history.get_content();
+                let mut tracked_file = tracked.create_tracked_file()?;
+
+                tracked_file.rewind()?;
+                tracked_file.set_len(0)?;
+
+                tracked_file.write_all(new_content.as_bytes())?;
+            }
+
+            file_history.write_to_file(&mut history_file)?;
+        }
+        RepositoryPaths::Deleted(deleted) => {
+            let mut history_file = deleted.load_history_file()?;
+
+            let mut file_history = FileHistory::from_file(&mut history_file).unwrap();
+            file_history.set_cursor(new_cursor);
+
+            if !file_history.file_is_deleted() {
+                let mut new_tracked_file = deleted.create_tracked_file(&locations)?;
+                let new_content = file_history.get_content();
+
+                new_tracked_file.write_all(new_content.as_bytes())?;
+            }
+        }
+        RepositoryPaths::Untracked(_) => panic!("File is not tracked with Ka."),
+    }
+
+    Ok(())
+}
diff --git a/src/actions/update.rs b/src/actions/update.rs
new file mode 100644
index 0000000..a2bc08d
--- /dev/null
+++ b/src/actions/update.rs
@@ -0,0 +1,80 @@
+use std::io::{self, Read};
+
+use crate::{
+    files::{Locations, RepositoryPaths},
+    history::{FileChange, FileHistory},
+    text_diff::TextChange,
+};
+
+use super::ActionOptions;
+
+pub fn update(command_options: ActionOptions) -> io::Result<()> {
+    let locations = Locations::from(&command_options);
+
+    let entries = locations
+        .get_repository_paths()
+        .expect("Could not traverse files.");
+
+    for element in entries {
+        update_file(element, &locations)?;
+    }
+
+    Ok(())
+}
+
+fn update_file(paths: RepositoryPaths, locations: &Locations) -> io::Result<()> {
+    let new_state = match paths {
+        RepositoryPaths::Deleted(deleted) => {
+            let mut history_file = deleted.load_history_file()?;
+            let file_history = FileHistory::from_file(&mut history_file).unwrap();
+            if !file_history.file_is_deleted() {
+                let mut new_history = file_history;
+                new_history.add_change(FileChange::Deleted);
+                Some((history_file, new_history))
+            } else {
+                None
+            }
+        }
+        RepositoryPaths::Untracked(untracked) => {
+            let mut file = untracked.load_file()?;
+
+            let mut file_content = String::new();
+            file.read_to_string(&mut file_content)?;
+
+            let change = FileChange::Updated(vec![TextChange::Inserted {
+                at: 0,
+                new_content: file_content,
+            }]);
+
+            let mut new_history = FileHistory::default();
+            new_history.add_change(change);
+
+            Some((untracked.create_history_file(locations)?, new_history))
+        }
+        RepositoryPaths::Tracked(tracked) => {
+            let mut history_file = tracked.load_history_file()?;
+            let mut tracked_file = tracked.load_tracked_file()?;
+
+            let file_history = FileHistory::from_file(&mut history_file).unwrap();
+
+            let mut new_content = String::new();
+            tracked_file.read_to_string(&mut new_content)?;
+
+            let old_content = file_history.get_content();
+
+            let changes = TextChange::diff(&old_content, &new_content);
+
+            let mut new_history = file_history;
+            new_history.add_change(FileChange::Updated(changes));
+            new_history.set_cursor(new_history.cursor() + 1);
+
+            Some((history_file, new_history))
+        }
+    };
+
+    if let Some((mut history_file, new_file_history)) = new_state {
+        new_file_history.write_to_file(&mut history_file)?;
+    }
+
+    Ok(())
+}