diff options
Diffstat (limited to 'src/actions')
| -rw-r--r-- | src/actions/create.rs | 12 | ||||
| -rw-r--r-- | src/actions/shift.rs | 67 | ||||
| -rw-r--r-- | src/actions/update.rs | 94 |
3 files changed, 113 insertions, 60 deletions
diff --git a/src/actions/create.rs b/src/actions/create.rs index f00e95d..472cbe3 100644 --- a/src/actions/create.rs +++ b/src/actions/create.rs @@ -1,8 +1,8 @@ -use std::fs; +use std::fs::{self, File}; use anyhow::Result; -use crate::{actions::update, files::Locations}; +use crate::{actions::update, files::Locations, history::RepositoryHistory}; use super::ActionOptions; @@ -13,8 +13,12 @@ pub fn create(command_options: ActionOptions) -> Result<()> { fs::remove_dir_all(locations.ka_path.as_path())?; } - fs::create_dir(locations.ka_path)?; - fs::create_dir(locations.ka_files_path)?; + fs::create_dir(&locations.ka_path)?; + fs::create_dir(&locations.ka_files_path)?; + + let mut index_file = File::create(locations.get_repository_index())?; + let empty_history = RepositoryHistory::default(); + empty_history.write_to_file(&mut index_file)?; update(command_options)?; diff --git a/src/actions/shift.rs b/src/actions/shift.rs index 6880c20..0fbc233 100644 --- a/src/actions/shift.rs +++ b/src/actions/shift.rs @@ -1,56 +1,63 @@ use std::{ - fs, + fs::{self, OpenOptions}, io::{Seek, Write}, - path::Path, }; use anyhow::Result; use crate::{ - files::{Locations, FileState}, - history::FileHistory, + files::{FileState, Locations}, + history::{FileHistory, RepositoryHistory}, }; use super::ActionOptions; -pub fn shift(command_options: ActionOptions, path: &str, new_cursor: usize) -> Result<()> { +pub fn shift(command_options: ActionOptions, new_cursor: usize) -> Result<()> { let locations = Locations::from(&command_options); - match FileState::from_working(&locations, Path::new(path))? { - FileState::Tracked(tracked) => { - let mut history_file = tracked.load_history_file()?; + let repository_index_path = locations.get_repository_index(); + let mut repository_index_file = OpenOptions::new().write(true).open(repository_index_path)?; + let mut repository_history = RepositoryHistory::from_file(&mut repository_index_file)?; - let mut file_history = FileHistory::from_file(&mut history_file)?; - file_history.set_cursor(new_cursor); + repository_history.cursor = new_cursor; + repository_history.write_to_file(&mut repository_index_file)?; - if file_history.file_is_deleted() { - fs::remove_file(path)?; - } else { - let new_content = file_history.get_content(); - let mut working_file = tracked.create_working_file()?; + // TOOD: Only shift files which would be affected by cursor change - working_file.rewind()?; - working_file.set_len(0)?; + for state in locations.get_repository_files()? { + match state { + FileState::Tracked(tracked) => { + let mut history_file = tracked.load_history_file()?; - working_file.write_all(&new_content)?; - } + let file_history = FileHistory::from_file(&mut history_file)?; - file_history.write_to_file(&mut history_file)?; - } - FileState::Deleted(deleted) => { - let mut history_file = deleted.load_history_file()?; + if file_history.is_file_deleted(new_cursor) { + fs::remove_file(tracked.working_path)?; + } else { + let new_content = file_history.get_content(new_cursor); + let mut working_file = tracked.create_working_file()?; + + working_file.rewind()?; + working_file.set_len(0)?; + + working_file.write_all(&new_content)?; + } + } + FileState::Deleted(deleted) => { + let mut history_file = deleted.load_history_file()?; - let mut file_history = FileHistory::from_file(&mut history_file)?; - file_history.set_cursor(new_cursor); + let file_history = FileHistory::from_file(&mut history_file)?; - if !file_history.file_is_deleted() { - let mut new_working_file = deleted.create_working_file(&locations)?; - let new_content = file_history.get_content(); + if !file_history.is_file_deleted(new_cursor) { + let mut new_working_file = deleted.create_working_file(&locations)?; + let new_content = file_history.get_content(new_cursor); - new_working_file.write_all(&new_content)?; + new_working_file.write_all(&new_content)?; + } } + // TODO: What do we do with untracked files on a shift? Delete them? + _ => (), } - FileState::Untracked(_) => panic!("File is not tracked with Ka."), } Ok(()) diff --git a/src/actions/update.rs b/src/actions/update.rs index aa9c3a4..a9bc0d2 100644 --- a/src/actions/update.rs +++ b/src/actions/update.rs @@ -1,40 +1,78 @@ -use std::io::Read; +use std::{ + fs::{File, OpenOptions}, + io::Read, + time::SystemTime, +}; use anyhow::{Context, Result}; use crate::{ - files::{Locations, FileState}, - history::{FileChange, FileHistory}, diff::ContentChange, + files::{FileState, Locations}, + history::{FileChange, FileChangeVariant, FileHistory, RepositoryChange, RepositoryHistory}, }; use super::ActionOptions; pub fn update(command_options: ActionOptions) -> Result<()> { + let timestamp = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH)? + .as_secs(); + let locations = Locations::from(&command_options); + let repository_index_path = locations.get_repository_index(); + let mut repository_index_file = OpenOptions::new() + .read(true) + .write(true) + .open(repository_index_path)?; + let mut repository_history = RepositoryHistory::from_file(&mut repository_index_file)?; + let entries = locations .get_repository_files() .context("Could not traverse files.")?; - for element in entries { - update_file(element, &locations)?; + let mut affected_files = Vec::new(); + + for state in entries { + let changed_file = get_new_history_for_file(repository_history.cursor, &state, &locations)?; + if let Some((mut history_file, new_file_history)) = changed_file { + new_file_history.write_to_file(&mut history_file)?; + affected_files.push(state.get_working_path(&locations)?); + } + } + + if affected_files.len() > 0 { + repository_history.add_change(RepositoryChange { + affected_files, + timestamp, + }); + repository_history.cursor += 1; + + repository_history.write_to_file(&mut repository_index_file)?; } Ok(()) } -fn update_file(file_state: FileState, locations: &Locations) -> Result<()> { - let new_state = match file_state { +fn get_new_history_for_file( + cursor: usize, + file_state: &FileState, + locations: &Locations, +) -> Result<Option<(File, FileHistory)>> { + match file_state { FileState::Deleted(deleted) => { let mut history_file = deleted.load_history_file()?; let file_history = FileHistory::from_file(&mut history_file)?; - if !file_history.file_is_deleted() { + if !file_history.is_file_deleted(cursor) { let mut new_history = file_history; - new_history.add_change(FileChange::Deleted); - Some((history_file, new_history)) + new_history.add_change(FileChange { + change_index: cursor + 1, + variant: FileChangeVariant::Deleted, + }); + Ok(Some((history_file, new_history))) } else { - None + Ok(None) } } FileState::Untracked(untracked) => { @@ -43,15 +81,21 @@ fn update_file(file_state: FileState, locations: &Locations) -> Result<()> { let mut file_content = Vec::new(); file.read_to_end(&mut file_content)?; - let change = FileChange::Updated(vec![ContentChange::Inserted { - at: 0, - new_content: file_content, - }]); + let change = FileChange { + change_index: cursor + 1, + variant: FileChangeVariant::Updated(vec![ContentChange::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)) + Ok(Some(( + untracked.create_history_file(locations)?, + new_history, + ))) } FileState::Tracked(tracked) => { let mut history_file = tracked.load_history_file()?; @@ -62,21 +106,19 @@ fn update_file(file_state: FileState, locations: &Locations) -> Result<()> { let mut new_content = Vec::new(); working_file.read_to_end(&mut new_content)?; - let old_content = file_history.get_content(); + let old_content = file_history.get_content(cursor); let changes = ContentChange::diff(&old_content, &new_content); + // TODO: Check if file was changed. + let mut new_history = file_history; - new_history.add_change(FileChange::Updated(changes)); - new_history.set_cursor(new_history.cursor() + 1); + new_history.add_change(FileChange { + change_index: cursor + 1, + variant: FileChangeVariant::Updated(changes), + }); - Some((history_file, new_history)) + Ok(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(()) } |
