aboutsummaryrefslogtreecommitdiff
path: root/src/actions
diff options
context:
space:
mode:
Diffstat (limited to 'src/actions')
-rw-r--r--src/actions/create.rs12
-rw-r--r--src/actions/shift.rs67
-rw-r--r--src/actions/update.rs94
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(())
}