about summary refs log tree commit diff
path: root/src/actions/update.rs
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2021-10-01 00:34:16 +0200
committerMel <einebeere@gmail.com>2021-10-01 00:34:16 +0200
commit3f5c5026909af023c8a3885a4a3d97c669302c1b (patch)
tree44c7e3e81d3b71ad6977afe4ac1596033b5834a6 /src/actions/update.rs
parent8f700551fd3f98c7b9846af647a7318c171152a6 (diff)
downloadka-3f5c5026909af023c8a3885a4a3d97c669302c1b.tar.zst
ka-3f5c5026909af023c8a3885a4a3d97c669302c1b.zip
Global repository cursor
Diffstat (limited to 'src/actions/update.rs')
-rw-r--r--src/actions/update.rs94
1 files changed, 68 insertions, 26 deletions
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(())
 }