diff options
author | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2024-03-02 14:54:34 +0100 |
---|---|---|
committer | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2024-03-02 14:54:34 +0100 |
commit | 8e5f1f5154d93e60422407a5387d8b9967fc5952 (patch) | |
tree | bbe30a1ab628d5aca1cf30de1106d1f3907c243f /jgvariant-tool/src/main | |
parent | 6146428ef31e21f13201874ddc135bbf49ae77aa (diff) |
jgvariant-tool: Add 'ostree summary add-static-delta' command.
Change-Id: I3b318269c4c85b581d6639fe5ec6a14bf2604ad4
Diffstat (limited to 'jgvariant-tool/src/main')
3 files changed, 108 insertions, 5 deletions
diff --git a/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/Main.java b/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/Main.java index fbf5b71..744d902 100644 --- a/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/Main.java +++ b/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/Main.java @@ -17,7 +17,9 @@ import picocli.CommandLine; * * <p>Also provides ways to manipulate OSTree repositories. * - * <p>Usage example (dumping the contents of an OSTree summary file): + * <h2>Usage Examples</h2> + * + * <h3>Dumping the contents of an OSTree summary file</h3> * * {@snippet lang="sh" : * $ jgvariant ostree summary read ./jgvariant-ostree/src/test/resources/ostree/summary @@ -56,6 +58,21 @@ import picocli.CommandLine; * } * } * } + * + * <h3>Adding a static delta to an OSTree summary file</h3> + * + * <p>Static delta <code>3...</code> (in hex), between commits <code>1...</code> and <code>2... + * </code>: + * + * {@snippet lang="sh" : + * $ jgvariant ostree summary add-static-delta ./jgvariant-ostree/src/test/resources/ostree/summary 3333333333333333333333333333333333333333333333333333333333333333 2222222222222222222222222222222222222222222222222222222222222222 1111111111111111111111111111111111111111111111111111111111111111 + * } + * + * <p>Static delta <code>3...</code> (in hex), between the empty commit and <code>2...</code>: + * + * {@snippet lang="sh" : + * $ jgvariant ostree summary add-static-delta ./jgvariant-ostree/src/test/resources/ostree/summary 4444444444444444444444444444444444444444444444444444444444444444 2222222222222222222222222222222222222222222222222222222222222222 + * } */ public final class Main { static { diff --git a/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/MainCommand.java b/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/MainCommand.java index fe8211e..2bea23c 100644 --- a/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/MainCommand.java +++ b/jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/MainCommand.java @@ -7,6 +7,10 @@ package eu.mulk.jgvariant.tool; import static java.util.logging.Level.*; import eu.mulk.jgvariant.core.Decoder; +import eu.mulk.jgvariant.core.Signature; +import eu.mulk.jgvariant.core.Variant; +import eu.mulk.jgvariant.ostree.ByteString; +import eu.mulk.jgvariant.ostree.Metadata; import eu.mulk.jgvariant.ostree.Summary; import eu.mulk.jgvariant.tool.jsonb.*; import jakarta.json.bind.Jsonb; @@ -16,10 +20,15 @@ import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; +import java.nio.file.StandardOpenOption; +import java.text.ParseException; +import java.util.*; import java.util.logging.Logger; +import java.util.stream.IntStream; import org.jetbrains.annotations.VisibleForTesting; import picocli.AutoComplete; import picocli.CommandLine; @@ -76,10 +85,56 @@ final class MainCommand { static final class SummaryCommand extends BaseDecoderCommand<Summary> { @Command(mixinStandardHelpOptions = true) - void read(@Parameters(paramLabel = "<file>") File file) throws IOException { + void read(@Parameters(paramLabel = "<file>", description = "Summary file to read") File file) + throws IOException { read(file, Summary.decoder()); } + @Command(name = "add-static-delta", mixinStandardHelpOptions = true) + void addStaticDelta( + @Parameters(paramLabel = "<file>", description = "Summary file to manipulate.") + File summaryFile, + @Parameters(paramLabel = "<delta>", description = "Checksum of the static delta (hex).") + String delta, + @Parameters(paramLabel = "<to>", description = "Commit checksum the delta ends at (hex).") + String toCommit, + @Parameters( + paramLabel = "<from>", + arity = "0..1", + description = "Commit checksum the delta starts from (hex).") + String fromCommit) + throws IOException, ParseException { + var summaryDecoder = Summary.decoder(); + + var summary = decodeFile(summaryFile, summaryDecoder); + + var staticDeltaMapSignature = Signature.parse("a{sv}"); + var checksumSignature = Signature.parse("ay"); + + var metadata = summary.metadata(); + var metadataFields = new LinkedHashMap<>(metadata.fields()); + metadataFields.compute( + "ostree.static-deltas", + (k, v) -> { + Map<String, Variant> staticDeltas = + v != null + ? new LinkedHashMap<>((Map<String, Variant>) v.value()) + : new LinkedHashMap<>(); + staticDeltas.put( + fromCommit != null ? fromCommit + "-" + toCommit : toCommit, + new Variant(checksumSignature, toByteList(ByteString.ofHex(delta).bytes()))); + return new Variant(staticDeltaMapSignature, staticDeltas); + }); + metadata = new Metadata(metadataFields); + summary = new Summary(summary.entries(), metadata); + + encodeFile(summaryFile, summaryDecoder, summary); + } + + private List<Byte> toByteList(byte[] bytes) { + return IntStream.range(0, bytes.length).mapToObj(i -> bytes[i]).toList(); + } + SummaryCommand() {} } @@ -111,10 +166,24 @@ final class MainCommand { abstract static class BaseDecoderCommand<T> extends BaseCommand { protected final void read(File file, Decoder<T> decoder) throws IOException { + var thing = decodeFile(file, decoder); + out().println(jsonb.toJson(thing)); + } + + protected final T decodeFile(File file, Decoder<T> decoder) throws IOException { LOG.fine(() -> "Reading file %s".formatted(file)); var fileBytes = ByteBuffer.wrap(Files.readAllBytes(fs().getPath(file.getPath()))); - var thing = decoder.decode(fileBytes); - out().println(jsonb.toJson(thing)); + return decoder.decode(fileBytes); + } + + @SuppressWarnings("ResultOfMethodCallIgnored") + protected final void encodeFile(File file, Decoder<T> decoder, T thing) throws IOException { + var thingBytes = decoder.encode(thing); + + LOG.fine(() -> "Writing file %s".formatted(file)); + try (var out = FileChannel.open(fs().getPath(file.getPath()), StandardOpenOption.WRITE)) { + out.write(thingBytes); + } } } diff --git a/jgvariant-tool/src/main/java/module-info.java b/jgvariant-tool/src/main/java/module-info.java index e62808e..6faa226 100644 --- a/jgvariant-tool/src/main/java/module-info.java +++ b/jgvariant-tool/src/main/java/module-info.java @@ -11,7 +11,9 @@ * * <p>The {@link eu.mulk.jgvariant.tool.Main} class defines the entry point of the tool. * - * <p>Usage example (dumping the contents of an OSTree summary file): + * <h2>Usage Examples</h2> + * + * <h3>Dumping the contents of an OSTree summary file</h3> * * {@snippet lang="sh" : * $ jgvariant ostree summary read ./jgvariant-ostree/src/test/resources/ostree/summary @@ -50,6 +52,21 @@ * } * } * } + * + * <h3>Adding a static delta to an OSTree summary file</h3> + * + * <p>Static delta <code>3...</code> (in hex), between commits <code>1...</code> and <code>2... + * </code>: + * + * {@snippet lang="sh" : + * $ jgvariant ostree summary add-static-delta ./jgvariant-ostree/src/test/resources/ostree/summary 3333333333333333333333333333333333333333333333333333333333333333 2222222222222222222222222222222222222222222222222222222222222222 1111111111111111111111111111111111111111111111111111111111111111 + * } + * + * <p>Static delta <code>3...</code> (in hex), between the empty commit and <code>2...</code>: + * + * {@snippet lang="sh" : + * $ jgvariant ostree summary add-static-delta ./jgvariant-ostree/src/test/resources/ostree/summary 4444444444444444444444444444444444444444444444444444444444444444 2222222222222222222222222222222222222222222222222222222222222222 + * } */ module eu.mulk.jgvariant.tool { requires transitive eu.mulk.jgvariant.ostree; |