From 7ca9dc20e3cb1780156fba1d003d2bc6e903a599 Mon Sep 17 00:00:00 2001 From: Pasqual Koschmieder Date: Fri, 20 Oct 2023 09:14:52 +0200 Subject: [PATCH] Fix history trim for non-timestamped files (#873) --- .../reader/impl/history/DefaultHistory.java | 16 ++++++---- .../impl/history/HistoryPersistenceTest.java | 30 +++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java b/reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java index 416c3039d..90a9b9a3c 100644 --- a/reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java +++ b/reader/src/main/java/org/jline/reader/impl/history/DefaultHistory.java @@ -247,12 +247,16 @@ protected void trimHistory(Path path, int max) throws IOException { Log.trace("Trimming history path: ", path); // Load all history entries LinkedList allItems = new LinkedList<>(); - try (BufferedReader reader = Files.newBufferedReader(path)) { - reader.lines().forEach(l -> { - int idx = l.indexOf(':'); - Instant time = Instant.ofEpochMilli(Long.parseLong(l.substring(0, idx))); - String line = unescape(l.substring(idx + 1)); - allItems.add(createEntry(allItems.size(), time, line)); + try (BufferedReader historyFileReader = Files.newBufferedReader(path)) { + historyFileReader.lines().forEach(l -> { + if (reader.isSet(LineReader.Option.HISTORY_TIMESTAMPED)) { + int idx = l.indexOf(':'); + Instant time = Instant.ofEpochMilli(Long.parseLong(l.substring(0, idx))); + String line = unescape(l.substring(idx + 1)); + allItems.add(createEntry(allItems.size(), time, line)); + } else { + allItems.add(createEntry(allItems.size(), Instant.now(), unescape(l))); + } }); } // Remove duplicates diff --git a/reader/src/test/java/org/jline/reader/impl/history/HistoryPersistenceTest.java b/reader/src/test/java/org/jline/reader/impl/history/HistoryPersistenceTest.java index b18683eae..70964b325 100644 --- a/reader/src/test/java/org/jline/reader/impl/history/HistoryPersistenceTest.java +++ b/reader/src/test/java/org/jline/reader/impl/history/HistoryPersistenceTest.java @@ -11,6 +11,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; +import java.time.Instant; import java.util.List; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; @@ -19,6 +20,7 @@ import org.jline.reader.LineReader; import org.jline.reader.impl.ReaderTestSupport; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -97,4 +99,32 @@ public void testFileHistory() throws Exception { lines = Files.readAllLines(Paths.get("test")); assertEquals(cmdsPerThread * (nbThreads + 1), lines.size()); } + + private void testHistoryTrim(boolean timestamped) { + reader.unsetOpt(LineReader.Option.HISTORY_INCREMENTAL); + reader.option(LineReader.Option.HISTORY_TIMESTAMPED, timestamped); + reader.setVariable(LineReader.HISTORY_FILE_SIZE, 5); + reader.setVariable(LineReader.HISTORY_FILE, Paths.get("test")); + + DefaultHistory history = new DefaultHistory(reader); + for (int i = 0; i < 50; i++) { + history.add(Instant.now(), "Hello " + i); + if (i % 5 == 0) { + Assertions.assertDoesNotThrow(history::save); + } + } + + Assertions.assertDoesNotThrow(history::load); + Assertions.assertEquals(5, history.size()); + } + + @Test + public void testHistoryTrimNonTimestamped() { + testHistoryTrim(false); + } + + @Test + public void testHistoryTrimTimestamped() { + testHistoryTrim(true); + } }