blob: 7b25dfcb82cbe6d4b1130d3a7726cf957f226050 [file] [log] [blame]
Matthias Andreas Benkarda1e84432023-12-05 21:12:16 +01001// SPDX-FileCopyrightText: © 2023 Matthias Andreas Benkard <code@mail.matthias.benkard.de>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5package eu.mulk.jgvariant.tool;
6
7import static java.util.logging.Level.*;
8
9import eu.mulk.jgvariant.ostree.Summary;
10import eu.mulk.jgvariant.tool.jsonb.*;
11import jakarta.json.bind.Jsonb;
12import jakarta.json.bind.JsonbBuilder;
13import jakarta.json.bind.JsonbConfig;
14import java.io.File;
15import java.io.IOException;
16import java.io.PrintWriter;
17import java.nio.ByteBuffer;
18import java.nio.file.FileSystem;
19import java.nio.file.FileSystems;
20import java.nio.file.Files;
21import java.util.logging.Logger;
22import org.jetbrains.annotations.VisibleForTesting;
23import picocli.AutoComplete;
24import picocli.CommandLine;
25import picocli.CommandLine.*;
26
27@Command(
28 name = "jgvariant",
29 mixinStandardHelpOptions = true,
30 description = "Manipulate files in GVariant format.",
31 subcommands = {MainCommand.OstreeCommand.class, AutoComplete.GenerateCompletion.class})
32final class MainCommand {
33
34 private static final Logger LOG = Logger.getLogger("eu.mulk.jgvariant.tool");
35
36 private static final Jsonb jsonb =
37 JsonbBuilder.newBuilder()
38 .withConfig(
39 new JsonbConfig()
40 .withFormatting(true)
41 .withAdapters(ChecksumAdapter.INSTANCE)
42 .withSerializers(
43 ByteStringSerializer.INSTANCE,
44 ByteArraySerializer.INSTANCE,
45 SignatureSerializer.INSTANCE,
46 VariantSerializer.INSTANCE))
47 .build();
48
49 @Option(
50 names = {"-v", "--verbose"},
51 description = "Enable verbose logging.",
52 scope = CommandLine.ScopeType.INHERIT)
53 void setVerbose(boolean[] verbose) {
54 Logger.getGlobal()
55 .setLevel(
56 switch (verbose.length) {
57 case 0 -> WARNING;
58 case 1 -> INFO;
59 case 2 -> FINE;
60 default -> ALL;
61 });
62 }
63
64 @Command(
65 name = "ostree",
66 mixinStandardHelpOptions = true,
67 description = "Manipulate OSTree files.",
68 subcommands = {OstreeCommand.SummaryCommand.class})
69 static final class OstreeCommand {
70
71 @Command(
72 name = "summary",
73 mixinStandardHelpOptions = true,
74 description = "Manipulate OSTree summary files.")
75 static final class SummaryCommand extends BaseCommand {
76
77 @Command(mixinStandardHelpOptions = true)
78 void read(@Parameters(paramLabel = "<file>") File file) throws IOException {
79 LOG.fine(() -> "Reading file %s".formatted(file));
80 var fileBytes = ByteBuffer.wrap(Files.readAllBytes(fs().getPath(file.getPath())));
81 var decoder = Summary.decoder();
82 var thing = decoder.decode(fileBytes);
83 out().println(jsonb.toJson(thing));
84 }
85
86 SummaryCommand() {}
87 }
88
89 OstreeCommand() {}
90 }
91
92 @Command
93 abstract static class BaseCommand {
94
95 @Spec CommandLine.Model.CommandSpec spec;
96
97 @VisibleForTesting FileSystem fs = FileSystems.getDefault();
98
99 protected BaseCommand() {}
100
101 protected PrintWriter out() {
102 return spec.commandLine().getOut();
103 }
104
105 protected PrintWriter err() {
106 return spec.commandLine().getErr();
107 }
108
109 protected FileSystem fs() {
110 return fs;
111 }
112 }
113
114 MainCommand() {}
115}