Skip to content

Commit d650195

Browse files
committed
reload history with reload command
1 parent b83fb40 commit d650195

File tree

4 files changed

+59
-22
lines changed

4 files changed

+59
-22
lines changed

helix-core/src/history.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,23 @@ impl History {
189189
Ok((last_saved_revision, history))
190190
}
191191

192+
pub fn merge(&mut self, mut other: History, offset: usize) -> std::io::Result<()> {
193+
let revisions = self.revisions.split_off(offset);
194+
let len = other.revisions.len();
195+
for r in revisions {
196+
let parent = if r.parent < offset {
197+
r.parent
198+
} else {
199+
len + (r.parent - offset)
200+
};
201+
other.revisions.get_mut(parent).unwrap().last_child =
202+
NonZeroUsize::new(other.revisions.len());
203+
other.revisions.push(r);
204+
}
205+
self.revisions = other.revisions;
206+
Ok(())
207+
}
208+
192209
pub fn read_header<R: Read>(reader: &mut R, path: &Path) -> std::io::Result<(usize, usize)> {
193210
let header = read_string(reader)?;
194211
if HEADER_TAG != header {
@@ -259,6 +276,11 @@ impl History {
259276
self.current == 0
260277
}
261278

279+
#[inline]
280+
pub fn is_empty(&self) -> bool {
281+
self.revisions.len() <= 1
282+
}
283+
262284
/// Returns the changes since the given revision composed into a transaction.
263285
/// Returns None if there are no changes between the current and given revisions.
264286
pub fn changes_since(&self, revision: usize) -> Option<Transaction> {

helix-term/src/application.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -515,10 +515,6 @@ impl Application {
515515
}
516516
};
517517

518-
if doc_save_event.serialize_error {
519-
self.editor.set_error("failed to serialize history");
520-
}
521-
522518
let doc = match self.editor.document_mut(doc_save_event.doc_id) {
523519
None => {
524520
warn!(
@@ -570,6 +566,9 @@ impl Application {
570566
lines,
571567
bytes
572568
));
569+
if doc_save_event.serialize_error {
570+
self.editor.set_error("failed to serialize history");
571+
}
573572
}
574573

575574
#[inline(always)]

helix-term/tests/test/commands.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,7 @@ async fn test_persistent_undo() -> anyhow::Result<()> {
486486
.with_file(file.path(), None)
487487
.build()?;
488488

489+
// TODO: Test if the history file is valid.
489490
test_key_sequence(
490491
&mut app,
491492
Some(&format!(

helix-view/src/document.rs

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use std::path::{Path, PathBuf};
2020
use std::str::FromStr;
2121
use std::sync::Arc;
2222
use std::time::SystemTime;
23+
use tokio::fs::OpenOptions;
2324

2425
use helix_core::{
2526
encoding,
@@ -591,7 +592,7 @@ impl Document {
591592
.load()
592593
.persistent_undo
593594
.then(|| self.history.get_mut().clone());
594-
let undo_file = self.undo_file(Some(&path))?.unwrap();
595+
let undofile_path = self.undo_file(Some(&path))?.unwrap();
595596
// We encode the file according to the `Document`'s encoding.
596597
let future = async move {
597598
use tokio::{fs, fs::File};
@@ -624,16 +625,22 @@ impl Document {
624625
if let Some(history) = history {
625626
let res = {
626627
let path = path.clone();
628+
let mut undofile = OpenOptions::new()
629+
.write(true)
630+
.read(true)
631+
.create(true)
632+
.open(&undofile_path)
633+
.await?
634+
.into_std()
635+
.await;
627636
tokio::task::spawn_blocking(move || -> anyhow::Result<()> {
628-
use std::fs;
629637
let append =
630-
History::read_header(&mut fs::File::open(&undo_file)?, &path).is_ok();
631-
let mut undo_file = std::fs::OpenOptions::new()
632-
.write(true)
633-
.truncate(!append)
634-
.read(true)
635-
.open(&undo_file)?;
636-
history.serialize(&mut undo_file, &path, current_rev, append)?;
638+
History::deserialize(&mut std::fs::File::open(&undofile_path)?, &path)
639+
.is_ok();
640+
if !append {
641+
undofile.set_len(0)?;
642+
}
643+
history.serialize(&mut undofile, &path, current_rev, append)?;
637644
Ok(())
638645
})
639646
.await
@@ -717,14 +724,16 @@ impl Document {
717724
let mut file = std::fs::File::open(&path)?;
718725
let (rope, ..) = from_reader(&mut file, Some(encoding))?;
719726

720-
// Calculate the difference between the buffer and source text, and apply it.
721-
// This is not considered a modification of the contents of the file regardless
722-
// of the encoding.
723-
let transaction = helix_core::diff::compare_ropes(self.text(), &rope);
724-
self.apply(&transaction, view.id);
725-
self.append_changes_to_history(view);
726-
self.reset_modified();
727-
727+
if let Err(e) = self.load_history() {
728+
log::error!("{}", e);
729+
// Calculate the difference between the buffer and source text, and apply it.
730+
// This is not considered a modification of the contents of the file regardless
731+
// of the encoding.
732+
let transaction = helix_core::diff::compare_ropes(self.text(), &rope);
733+
self.apply(&transaction, view.id);
734+
self.append_changes_to_history(view);
735+
self.reset_modified();
736+
}
728737
self.last_saved_time = SystemTime::now();
729738

730739
self.detect_indent_and_line_ending();
@@ -761,7 +770,13 @@ impl Document {
761770
&mut undo_file,
762771
self.path().unwrap(),
763772
)?;
764-
self.history.set(history);
773+
774+
if self.history.get_mut().is_empty() {
775+
self.history.set(history);
776+
} else {
777+
let offset = self.get_last_saved_revision() + 1;
778+
self.history.get_mut().merge(history, offset)?;
779+
}
765780
self.set_last_saved_revision(last_saved_revision);
766781
}
767782
}

0 commit comments

Comments
 (0)