diff options
Diffstat (limited to 'jgvariant-tool/src/main/java/eu')
| -rw-r--r-- | jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/Main.java | 19 | ||||
| -rw-r--r-- | jgvariant-tool/src/main/java/eu/mulk/jgvariant/tool/MainCommand.java | 75 | 
2 files changed, 90 insertions, 4 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); +      }      }    } | 
