From 68df1a12f662a232a5f8944c9022d0600415fb38 Mon Sep 17 00:00:00 2001 From: Gisli Magnusson Date: Tue, 18 Nov 2025 16:02:44 +0000 Subject: [PATCH 1/3] feat(ENGKNOW-2892): Add command line support for working with link files. --- .../main/java/org/gorpipe/gor/cli/GorCLI.java | 4 +- .../org/gorpipe/gor/cli/link/LinkCommand.java | 17 ++ .../gor/cli/link/LinkRollbackCommand.java | 50 ++++++ .../cli/link/LinkStreamSourceProvider.java | 26 +++ .../gor/cli/link/LinkUpdateCommand.java | 62 +++++++ .../gorpipe/gor/cli/link/LinkCommandTest.java | 154 ++++++++++++++++++ .../gorpipe/gor/driver/linkfile/LinkFile.java | 47 +++++- .../gor/driver/linkfile/LinkFileEntryV1.java | 6 +- 8 files changed, 356 insertions(+), 10 deletions(-) create mode 100644 gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkCommand.java create mode 100644 gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkRollbackCommand.java create mode 100644 gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkStreamSourceProvider.java create mode 100644 gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkUpdateCommand.java create mode 100644 gorscripts/src/test/java/org/gorpipe/gor/cli/link/LinkCommandTest.java diff --git a/gorscripts/src/main/java/org/gorpipe/gor/cli/GorCLI.java b/gorscripts/src/main/java/org/gorpipe/gor/cli/GorCLI.java index 84d7b40a..a3e201f5 100644 --- a/gorscripts/src/main/java/org/gorpipe/gor/cli/GorCLI.java +++ b/gorscripts/src/main/java/org/gorpipe/gor/cli/GorCLI.java @@ -26,6 +26,7 @@ import org.gorpipe.gor.cli.help.HelpCommand; import org.gorpipe.gor.cli.index.IndexCommand; import org.gorpipe.gor.cli.info.InfoCommand; +import org.gorpipe.gor.cli.link.LinkCommand; import org.gorpipe.gor.cli.manager.ManagerCommand; import org.gorpipe.gor.cli.migrator.FolderMigratorCommand; import org.gorpipe.gor.cli.query.QueryCommand; @@ -38,7 +39,8 @@ version="version 1.0", description = "Command line interface for gor query language and processes.", subcommands = {QueryCommand.class, HelpCommand.class, ManagerCommand.class, IndexCommand.class, - CacheCommand.class, RenderCommand.class, InfoCommand.class, FolderMigratorCommand.class}) + CacheCommand.class, RenderCommand.class, InfoCommand.class, FolderMigratorCommand.class, + LinkCommand.class}) public class GorCLI extends HelpOptions implements Runnable { public static void main(String[] args) { GorLogbackUtil.initLog("gor"); diff --git a/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkCommand.java b/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkCommand.java new file mode 100644 index 00000000..c83be67c --- /dev/null +++ b/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkCommand.java @@ -0,0 +1,17 @@ +package org.gorpipe.gor.cli.link; + +import org.gorpipe.gor.cli.HelpOptions; +import picocli.CommandLine; + +@SuppressWarnings("squid:S106") +@CommandLine.Command(name = "link", + description = "Manage link files (create, update, rollback).", + header = "Link file management commands.", + subcommands = {LinkUpdateCommand.class, LinkRollbackCommand.class, LinkResolveCommand.class}) +public class LinkCommand extends HelpOptions implements Runnable { + + @Override + public void run() { + CommandLine.usage(this, System.err); + } +} diff --git a/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkRollbackCommand.java b/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkRollbackCommand.java new file mode 100644 index 00000000..4a239fb7 --- /dev/null +++ b/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkRollbackCommand.java @@ -0,0 +1,50 @@ +package org.gorpipe.gor.cli.link; + +import java.io.IOException; +import java.time.Instant; + +import org.gorpipe.gor.driver.linkfile.LinkFile; +import org.gorpipe.util.DateUtils; + +import picocli.CommandLine; + +@CommandLine.Command(name = "rollback", + description = "Rollback the latest entry or rollback entries newer than a given date.") +public class LinkRollbackCommand implements Runnable { + + @CommandLine.Parameters(index = "0", paramLabel = "LINK_FILE", description = "Path to the link file to rollback.") + private String linkFilePath; + + @CommandLine.Option(names = {"-d", "--date"}, paramLabel = "DATE", + description = "ISO-8601 date/time or epoch milliseconds to rollback to (entries newer than this are removed).") + private String rollbackDate; + + @Override + public void run() { + var normalizedLinkPath = LinkFile.validateAndUpdateLinkFileName(linkFilePath); + try { + var linkFile = LinkFile.load(LinkStreamSourceProvider.resolve(normalizedLinkPath, true, this)); + boolean changed = rollbackDate == null ? linkFile.rollbackLatestEntry() : linkFile.rollbackToTimestamp(parseDate(rollbackDate)); + if (!changed) { + throw new CommandLine.ParameterException(new CommandLine(this), + "No entries were removed. Link file may already be at the requested state."); + } + linkFile.save(); + System.err.printf("Rolled back link file %s%n", normalizedLinkPath); + } catch (IOException e) { + throw new CommandLine.ExecutionException(new CommandLine(this), + "Failed to load link file: " + normalizedLinkPath, e); + } + } + + private long parseDate(String dateValue) { + try { + Instant instant = DateUtils.parseDateISOEpoch(dateValue, true); + return instant.toEpochMilli(); + } catch (Exception e) { + throw new CommandLine.ParameterException(new CommandLine(this), + "Invalid date value: " + dateValue, e); + } + } +} + diff --git a/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkStreamSourceProvider.java b/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkStreamSourceProvider.java new file mode 100644 index 00000000..bfde54a8 --- /dev/null +++ b/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkStreamSourceProvider.java @@ -0,0 +1,26 @@ +package org.gorpipe.gor.cli.link; + +import org.gorpipe.gor.driver.providers.stream.sources.StreamSource; +import org.gorpipe.gor.model.DriverBackedFileReader; +import picocli.CommandLine; + +final class LinkStreamSourceProvider { + + private LinkStreamSourceProvider() { + } + + static StreamSource resolve(String linkPath, boolean writeable, Object commandInstance) { + var fileReader = new DriverBackedFileReader("", null); + var dataSource = fileReader.resolveUrl(linkPath, writeable); + if (dataSource == null) { + throw new CommandLine.ExecutionException(new CommandLine(commandInstance), + "Could not resolve link file path: " + linkPath); + } + if (dataSource instanceof StreamSource streamSource) { + return streamSource; + } + throw new CommandLine.ExecutionException(new CommandLine(commandInstance), + "Link path is not stream compatible: " + linkPath); + } +} + diff --git a/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkUpdateCommand.java b/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkUpdateCommand.java new file mode 100644 index 00000000..c6247e3d --- /dev/null +++ b/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkUpdateCommand.java @@ -0,0 +1,62 @@ +package org.gorpipe.gor.cli.link; + +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.gorpipe.gor.driver.linkfile.LinkFile; +import org.gorpipe.util.Strings; + +import picocli.CommandLine; + +@CommandLine.Command(name = "update", + description = "Append a new entry to a link file, creating the file if needed.") +public class LinkUpdateCommand implements Runnable { + + @CommandLine.Parameters(index = "0", paramLabel = "LINK_FILE", description = "Path to the link file to update.") + private String linkFilePath; + + @CommandLine.Parameters(index = "1", paramLabel = "LINK_VALUE", description = "Value to add to the link file (file path, URL or query).") + private String linkValue; + + @CommandLine.Option(names = {"-m", "--md5"}, paramLabel = "MD5", + description = "MD5 checksum to associate with the new link entry.") + private String entryMd5; + + @CommandLine.Option(names = {"-i", "--info"}, paramLabel = "INFO", + description = "Free-form info string to store with the new link entry.") + private String entryInfo; + + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") + @CommandLine.Option(names = {"-h", "--header"}, paramLabel = "KEY=VALUE", + description = "Header property to upsert in the link file metadata. Repeatable.", + mapFallbackValue = "") + private final Map headerParams = new LinkedHashMap<>(); + + @Override + public void run() { + var normalizedLinkPath = LinkFile.validateAndUpdateLinkFileName(linkFilePath); + try { + var linkFile = LinkFile.load(LinkStreamSourceProvider.resolve(normalizedLinkPath, true, this)); + applyHeaders(linkFile); + linkFile.appendEntry(linkValue, entryMd5, entryInfo); + linkFile.save(); + System.out.printf("Updated link file %s with %s%n", normalizedLinkPath, linkValue); + } catch (IOException e) { + throw new CommandLine.ExecutionException(new CommandLine(this), + "Failed to load or create link file: " + normalizedLinkPath, e); + } + } + + private void applyHeaders(LinkFile linkFile) { + for (var entry : headerParams.entrySet()) { + var key = entry.getKey(); + var value = entry.getValue(); + if (Strings.isNullOrEmpty(key)) { + continue; + } + linkFile.getMeta().setProperty(key.trim().toUpperCase(), value != null ? value.trim() : ""); + } + } +} + diff --git a/gorscripts/src/test/java/org/gorpipe/gor/cli/link/LinkCommandTest.java b/gorscripts/src/test/java/org/gorpipe/gor/cli/link/LinkCommandTest.java new file mode 100644 index 00000000..d8a519fb --- /dev/null +++ b/gorscripts/src/test/java/org/gorpipe/gor/cli/link/LinkCommandTest.java @@ -0,0 +1,154 @@ +package org.gorpipe.gor.cli.link; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.file.Path; +import java.time.Instant; + +import org.gorpipe.gor.driver.linkfile.LinkFile; +import org.gorpipe.gor.driver.providers.stream.sources.file.FileSource; +import static org.junit.Assert.assertEquals; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import picocli.CommandLine; + +public class LinkCommandTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Test + public void testUpdateCreatesLinkFileAndAppliesHeaders() throws Exception { + Path linkFile = temp.getRoot().toPath().resolve("update_test.gor.link"); + CommandLine cmd = new CommandLine(new LinkCommand()); + + int exitCode = cmd.execute("update", linkFile.toString(), "data/file1.gor", "-h", "ENTRIES_COUNT_MAX=5"); + assertEquals(0, exitCode); + + LinkFile link = LinkFile.load(new FileSource(linkFile)); + assertEquals(1, link.getEntriesCount()); + assertEquals(resolve(linkFile, "data/file1.gor"), link.getLatestEntryUrl()); + assertEquals(5, link.getEntriesCountMax()); + } + + @Test + public void testUpdateWithMd5AndInfo() throws Exception { + Path linkFile = temp.getRoot().toPath().resolve("update_md5_info.gor.link"); + CommandLine cmd = new CommandLine(new LinkCommand()); + + int exitCode = cmd.execute("update", linkFile.toString(), "data/file1.gor", + "-m", "abc123", "-i", "first entry"); + assertEquals(0, exitCode); + + LinkFile link = LinkFile.load(new FileSource(linkFile)); + var latest = link.getLatestEntry(); + assertEquals("abc123", latest.md5()); + assertEquals("first entry", latest.info()); + } + + @Test + public void testRollbackLatestEntry() throws Exception { + Path linkFile = temp.getRoot().toPath().resolve("rollback_latest.gor.link"); + CommandLine cmd = new CommandLine(new LinkCommand()); + + cmd.execute("update", linkFile.toString(), "data/file1.gor"); + Thread.sleep(5); + cmd.execute("update", linkFile.toString(), "data/file2.gor"); + + int exitCode = cmd.execute("rollback", linkFile.toString()); + assertEquals(0, exitCode); + + LinkFile link = LinkFile.load(new FileSource(linkFile)); + assertEquals(1, link.getEntriesCount()); + assertEquals(resolve(linkFile, "data/file1.gor"), link.getLatestEntryUrl()); + } + + @Test + public void testRollbackToDate() throws Exception { + Path linkFile = temp.getRoot().toPath().resolve("rollback_date.gor.link"); + CommandLine cmd = new CommandLine(new LinkCommand()); + + cmd.execute("update", linkFile.toString(), "data/file1.gor"); + LinkFile first = LinkFile.load(new FileSource(linkFile)); + long firstTimestamp = first.getLatestEntry().timestamp(); + + Thread.sleep(5); + cmd.execute("update", linkFile.toString(), "data/file2.gor"); + + String rollbackIso = Instant.ofEpochMilli(firstTimestamp).toString(); + int exitCode = cmd.execute("rollback", linkFile.toString(), "-d", rollbackIso); + assertEquals(0, exitCode); + + LinkFile link = LinkFile.load(new FileSource(linkFile)); + assertEquals(1, link.getEntriesCount()); + assertEquals(resolve(linkFile, "data/file1.gor"), link.getLatestEntryUrl()); + } + + @Test + public void testResolveLatestEntry() throws Exception { + Path linkFile = temp.getRoot().toPath().resolve("resolve_latest.gor.link"); + CommandLine cmd = new CommandLine(new LinkCommand()); + + cmd.execute("update", linkFile.toString(), "data/file1.gor"); + Thread.sleep(5); + cmd.execute("update", linkFile.toString(), "data/file2.gor"); + + String resolved = executeAndCapture(cmd, "resolve", linkFile.toString()); + assertEquals(resolve(linkFile, "data/file2.gor"), resolved); + } + + @Test + public void testResolveSpecificDate() throws Exception { + Path linkFile = temp.getRoot().toPath().resolve("resolve_date.gor.link"); + CommandLine cmd = new CommandLine(new LinkCommand()); + + cmd.execute("update", linkFile.toString(), "data/file1.gor"); + long firstTimestamp = LinkFile.load(new FileSource(linkFile)).getLatestEntry().timestamp(); + Thread.sleep(5); + cmd.execute("update", linkFile.toString(), "data/file2.gor"); + + String resolved = executeAndCapture(cmd, "resolve", linkFile.toString(), + "-d", Instant.ofEpochMilli(firstTimestamp).toString()); + assertEquals(resolve(linkFile, "data/file1.gor"), resolved); + } + + @Test + public void testResolveFullEntry() throws Exception { + Path linkFile = temp.getRoot().toPath().resolve("resolve_full.gor.link"); + CommandLine cmd = new CommandLine(new LinkCommand()); + + cmd.execute("update", linkFile.toString(), "data/file1.gor"); + Thread.sleep(5); + cmd.execute("update", linkFile.toString(), "data/file2.gor"); + + String expectedEntry = LinkFile.load(new FileSource(linkFile)).getLatestEntry().format(); + String resolved = executeAndCapture(cmd, "resolve", linkFile.toString(), "-f"); + assertEquals(expectedEntry, resolved); + } + + private String resolve(Path linkFile, String relative) { + return linkFile.getParent().resolve(relative).toAbsolutePath().normalize().toString(); + } + + private String executeAndCapture(CommandLine cmd, String... args) { + PrintStream originalOut = System.out; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + System.setOut(new PrintStream(baos, true)); + try { + int exitCode = cmd.execute(args); + assertEquals(0, exitCode); + } finally { + System.setOut(originalOut); + } + String output = baos.toString(); + if (output.endsWith("\r\n")) { + output = output.substring(0, output.length() - 2); + } else if (output.endsWith("\n") || output.endsWith("\r")) { + output = output.substring(0, output.length() - 1); + } + return output; + } +} + diff --git a/model/src/main/java/org/gorpipe/gor/driver/linkfile/LinkFile.java b/model/src/main/java/org/gorpipe/gor/driver/linkfile/LinkFile.java index b7f94d3c..1e5c34e6 100644 --- a/model/src/main/java/org/gorpipe/gor/driver/linkfile/LinkFile.java +++ b/model/src/main/java/org/gorpipe/gor/driver/linkfile/LinkFile.java @@ -1,8 +1,11 @@ package org.gorpipe.gor.driver.linkfile; -import com.github.benmanes.caffeine.cache.Cache; -import com.github.benmanes.caffeine.cache.Caffeine; -import com.google.common.util.concurrent.UncheckedExecutionException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; +import java.util.concurrent.TimeUnit; + import org.gorpipe.exceptions.GorResourceException; import org.gorpipe.gor.driver.meta.SourceReference; import org.gorpipe.gor.driver.providers.stream.StreamUtils; @@ -12,11 +15,9 @@ import org.gorpipe.gor.util.DataUtil; import org.gorpipe.util.Strings; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.List; -import java.util.concurrent.TimeUnit; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.google.common.util.concurrent.UncheckedExecutionException; /** * Class to work with link files, read, write and access metadata. @@ -207,6 +208,34 @@ public LinkFile appendMeta(String meta) { return this; } + /** + * Remove the latest entry, if any. + * + * @return true if an entry was removed, otherwise false. + */ + public boolean rollbackLatestEntry() { + if (entries.isEmpty()) { + return false; + } + entries.remove(entries.size() - 1); + return true; + } + + /** + * Remove entries that are newer than the provided timestamp. + * + * @param timestamp the timestamp to rollback to (inclusive) + * @return true if one or more entries were removed, otherwise false. + */ + public boolean rollbackToTimestamp(long timestamp) { + boolean removed = false; + while (!entries.isEmpty() && entries.get(entries.size() - 1).timestamp() > timestamp) { + entries.remove(entries.size() - 1); + removed = true; + } + return removed; + } + public void save() { save(-1); } @@ -220,6 +249,8 @@ public void save(long timestamp) { } private void save(OutputStream os, long timestamp) { + meta.setProperty(meta.HEADER_SERIAL_KEY, Integer.toString(Integer.parseInt(meta.getProperty(meta.HEADER_SERIAL_KEY, "0")) + 1)); + var content = new StringBuilder(getHeader()); if (!entries.isEmpty()) { diff --git a/model/src/main/java/org/gorpipe/gor/driver/linkfile/LinkFileEntryV1.java b/model/src/main/java/org/gorpipe/gor/driver/linkfile/LinkFileEntryV1.java index a8be5d8b..14dbff69 100644 --- a/model/src/main/java/org/gorpipe/gor/driver/linkfile/LinkFileEntryV1.java +++ b/model/src/main/java/org/gorpipe/gor/driver/linkfile/LinkFileEntryV1.java @@ -70,6 +70,10 @@ private static LinkFileEntryV1 parseLine(String line) { } public String format() { - return url + "\t" + Instant.ofEpochMilli(timestamp) + "\t" + md5 + "\t" + serial+ "\t" + info; + return url + + "\t" + Instant.ofEpochMilli(timestamp) + + "\t" + (md5 != null ? md5 : "") + + "\t" + serial + + "\t" + (info != null ? info : ""); } } From e4452877289cbc6cdcfda0f6bf3609f6f13b519c Mon Sep 17 00:00:00 2001 From: Gisli Magnusson Date: Tue, 18 Nov 2025 16:03:49 +0000 Subject: [PATCH 2/3] feat(ENGKNOW-2892): Add command line support for working with link files. --- .../gor/cli/link/LinkResolveCommand.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkResolveCommand.java diff --git a/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkResolveCommand.java b/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkResolveCommand.java new file mode 100644 index 00000000..23a22671 --- /dev/null +++ b/gorscripts/src/main/java/org/gorpipe/gor/cli/link/LinkResolveCommand.java @@ -0,0 +1,67 @@ +package org.gorpipe.gor.cli.link; + +import java.io.IOException; +import java.time.Instant; + +import org.gorpipe.gor.driver.linkfile.LinkFile; +import org.gorpipe.util.DateUtils; +import org.gorpipe.util.Strings; + +import picocli.CommandLine; + +@CommandLine.Command(name = "resolve", + description = "Resolve a link file to the entry active at the current or given time.") +public class LinkResolveCommand implements Runnable { + + @CommandLine.Parameters(index = "0", paramLabel = "LINK_FILE", + description = "Path to the link file to resolve.") + private String linkFilePath; + + @CommandLine.Option(names = {"-d", "--date"}, paramLabel = "DATE", + description = "ISO-8601 date/time or epoch milliseconds to resolve at (default: now).") + private String resolveDate; + + @CommandLine.Option(names = {"-f", "--full-entry"}, + description = "Return the full link file entry instead of only the resolved URL.") + private boolean returnFullEntry; + + @Override + public void run() { + var normalizedLinkPath = LinkFile.validateAndUpdateLinkFileName(linkFilePath); + try { + var linkFile = LinkFile.load(LinkStreamSourceProvider.resolve(normalizedLinkPath, true, this)); + long timestamp = resolveDate == null ? System.currentTimeMillis() : parseDate(resolveDate); + var entry = linkFile.getEntry(timestamp); + if (entry == null) { + throw new CommandLine.ParameterException(new CommandLine(this), + "No link entry found for the requested time."); + } + String output; + if (returnFullEntry) { + output = entry.format(); + } else { + var resolved = linkFile.getEntryUrl(timestamp); + if (Strings.isNullOrEmpty(resolved)) { + throw new CommandLine.ParameterException(new CommandLine(this), + "No link entry found for the requested time."); + } + output = resolved; + } + System.out.println(output); + } catch (IOException e) { + throw new CommandLine.ExecutionException(new CommandLine(this), + "Failed to load link file: " + normalizedLinkPath, e); + } + } + + private long parseDate(String dateValue) { + try { + Instant instant = DateUtils.parseDateISOEpoch(dateValue, true); + return instant.toEpochMilli(); + } catch (Exception e) { + throw new CommandLine.ParameterException(new CommandLine(this), + "Invalid date value: " + dateValue, e); + } + } +} + From 0c0abda161c9d2970a9f5e42109d95ca2d1bc250 Mon Sep 17 00:00:00 2001 From: Gisli Magnusson Date: Tue, 18 Nov 2025 16:46:49 +0000 Subject: [PATCH 3/3] feat(ENGKNOW-2892): Add command line support for working with link files. --- gortools/src/test/java/gorsat/UTestGorWrite.java | 6 +++--- .../java/org/gorpipe/gor/driver/linkfile/LinkFileTest.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gortools/src/test/java/gorsat/UTestGorWrite.java b/gortools/src/test/java/gorsat/UTestGorWrite.java index b60a67ba..ce1e669b 100644 --- a/gortools/src/test/java/gorsat/UTestGorWrite.java +++ b/gortools/src/test/java/gorsat/UTestGorWrite.java @@ -71,6 +71,7 @@ public void setupTest() throws IOException { var meta = new LinkFileMeta(); meta.setProperty(BaseMeta.HEADER_VERSION_KEY, "1"); + meta.setProperty(BaseMeta.HEADER_SERIAL_KEY, "1"); defaultV1LinkFileHeader = meta.formatHeader(); } @@ -136,9 +137,8 @@ public void testWritePathWithExistingVersionedLinkFile() throws IOException { Files.writeString(workDirPath.resolve("dbsnp3.gor.link"), defaultV1LinkFileHeader + workDirPath.resolve("dbsnp.gor").toString() + "\n"); TestUtils.runGorPipe("gor dbsnp.gor | write dbsnp2.gor -link dbsnp3.gor", "-gorroot", workDirPath.toString()); - Assert.assertTrue(Files.readString(workDirPath.resolve("dbsnp3.gor.link")).startsWith( - defaultV1LinkFileHeader - + workDirPath.resolve("dbsnp.gor") + "\t1970-01-01T00:00:00Z\t\t0\t\n" + Assert.assertTrue(Files.readString(workDirPath.resolve("dbsnp3.gor.link")).contains( + workDirPath.resolve("dbsnp.gor") + "\t1970-01-01T00:00:00Z\t\t0\t\n" + workDirPath.resolve("dbsnp2.gor") + "\t")); } diff --git a/model/src/test/java/org/gorpipe/gor/driver/linkfile/LinkFileTest.java b/model/src/test/java/org/gorpipe/gor/driver/linkfile/LinkFileTest.java index 6a3836d4..b64d7a9a 100644 --- a/model/src/test/java/org/gorpipe/gor/driver/linkfile/LinkFileTest.java +++ b/model/src/test/java/org/gorpipe/gor/driver/linkfile/LinkFileTest.java @@ -22,7 +22,7 @@ public class LinkFileTest { private StreamSource mockSource; private final String v1LinkFileContent = """ - ## SERIAL = 0 + ## SERIAL = 1 ## VERSION = 1 #FILE\tTIMESTAMP\tMD5\tSERIAL\tINFO source/v1/ver1.gorz\t2024-12-15T11:21:30.790Z\tABCDEAF13422\t1\t @@ -117,7 +117,7 @@ public void testSaveLinkFileV1ToV1() throws IOException { linkFile.appendEntry(simpleFile, "NEWMD5SUM"); linkFile.save(); String savedContent = Files.readString(linkPath); - assertTrue(savedContent.startsWith(v1LinkFileContent)); + assertTrue(savedContent.startsWith("## SERIAL = 2")); assertTrue(savedContent.contains(simpleFile)); }