aboutsummaryrefslogtreecommitdiff
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(())
+}