Simple JSON output for sources and templates, to be able to query them
with no need to parse unstructured outputs like the "--list-format long"
one.
---
builder/cmdline.ml | 3 +-
builder/list_entries.ml | 60 +++++++++++++++++++++++++++++++++++
builder/list_entries.mli | 2 +-
builder/test-virt-builder-list.sh | 67 +++++++++++++++++++++++++++++++++++++++
builder/virt-builder.pod | 12 ++++++-
5 files changed, 141 insertions(+), 3 deletions(-)
diff --git a/builder/cmdline.ml b/builder/cmdline.ml
index 6d6439f..e3b1484 100644
--- a/builder/cmdline.ml
+++ b/builder/cmdline.ml
@@ -136,6 +136,7 @@ let parse_cmdline () =
list_format := match arg with
| "short" -> `Short
| "long" -> `Long
+ | "json" -> `Json
| fmt ->
eprintf (f_"%s: invalid --list-format type '%s', see the man
page.\n") prog fmt;
exit 1 in
@@ -265,7 +266,7 @@ let parse_cmdline () =
"--list", Arg.Unit list_mode, ditto;
"--long", Arg.Unit list_set_long, " " ^ s_"Shortcut
for --list-format short";
"--list-format", Arg.String list_set_format,
- "short|long" ^ " " ^
s_"Set the format for --list (default: short)";
+ "short|long|json" ^ " " ^
s_"Set the format for --list (default: short)";
"--no-logfile", Arg.Set scrub_logfile, " " ^ s_"Scrub build
log file";
"--long-options", Arg.Unit display_long_options, " " ^
s_"List long options";
"-m",
Arg.Int set_memsize, "mb" ^ " " ^
s_"Set memory size";
diff --git a/builder/list_entries.ml b/builder/list_entries.ml
index 97ab201..7369e6c 100644
--- a/builder/list_entries.ml
+++ b/builder/list_entries.ml
@@ -25,6 +25,7 @@ let rec list_entries ~list_format ~sources index =
match list_format with
| `Short -> list_entries_short index
| `Long -> list_entries_long ~sources index
+ | `Json -> list_entries_json ~sources index
and list_entries_short index =
List.iter (
@@ -78,3 +79,62 @@ and list_entries_long ~sources index =
printf "\n"
)
) index
+
+and list_entries_json ~sources index =
+ let trailing_comma index size =
+ if index = size - 1 then "" else "," in
+ let json_string_of_bool b =
+ if b then "true" else "false" in
+ let json_string_escape str =
+ let res = ref "" in
+ for i = 0 to String.length str - 1 do
+ res := !res ^ (match str.[i] with
+ | '"' -> "\\\""
+ | '\\' -> "\\\\"
+ | '\b' -> "\\b"
+ | '\n' -> "\\n"
+ | '\r' -> "\\r"
+ | '\t' -> "\\t"
+ | c -> String.make 1 c)
+ done;
+ !res in
+ let json_optional_printf_string key value =
+ match value with
+ | None -> ()
+ | Some str ->
+ printf " \"%s\": \"%s\",\n" key
(json_string_escape str) in
+ let json_optional_printf_int64 key value =
+ match value with
+ | None -> ()
+ | Some n ->
+ printf " \"%s\": \"%Ld\",\n" key n in
+
+ printf "{\n";
+ printf " \"version\": %d,\n" 1;
+ printf " \"sources\": [\n";
+ iteri (
+ fun i (source, fingerprint) ->
+ printf " {\n";
+ printf " \"uri\": \"%s\",\n" source;
+ printf " \"fingerprint\": \"%s\"\n" fingerprint;
+ printf " }%s\n" (trailing_comma i (List.length sources))
+ ) sources;
+ printf " ],\n";
+ printf " \"templates\": [\n";
+ iteri (
+ fun i (name, { Index_parser.printable_name = printable_name;
+ size = size;
+ compressed_size = compressed_size;
+ notes = notes;
+ hidden = hidden }) ->
+ printf " {\n";
+ printf " \"os-version\": \"%s\",\n" name;
+ json_optional_printf_string "full-name" printable_name;
+ printf " \"size\": %Ld,\n" size;
+ json_optional_printf_int64 "compressed-size" compressed_size;
+ json_optional_printf_string "notes" notes;
+ printf " \"hidden\": %s\n" (json_string_of_bool hidden);
+ printf " }%s\n" (trailing_comma i (List.length index))
+ ) index;
+ printf " ]\n";
+ printf "}\n"
diff --git a/builder/list_entries.mli b/builder/list_entries.mli
index 41d0bff..e7c32f1 100644
--- a/builder/list_entries.mli
+++ b/builder/list_entries.mli
@@ -16,4 +16,4 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)
-val list_entries : list_format:([ `Short | `Long ]) -> sources:(string * string) list
-> Index_parser.index -> unit
+val list_entries : list_format:([ `Short | `Long | `Json ]) -> sources:(string *
string) list -> Index_parser.index -> unit
diff --git a/builder/test-virt-builder-list.sh b/builder/test-virt-builder-list.sh
index 083c035..c3b791f 100755
--- a/builder/test-virt-builder-list.sh
+++ b/builder/test-virt-builder-list.sh
@@ -103,3 +103,70 @@ Phony Windows look-alike used for testing." ]; then
echo "$long_list"
exit 1
fi
+
+json_list=$(./virt-builder --no-check-signature --no-cache --list --list-format json)
+
+if [ "$json_list" != "{
+ \"version\": 1,
+ \"sources\": [
+ {
+ \"uri\": \"$VIRT_BUILDER_SOURCE\",
+ \"fingerprint\": \"F777 4FB1 AD07 4A7E 8C87 67EA 9173 8F73 E1B7
68A0\"
+ }
+ ],
+ \"templates\": [
+ {
+ \"os-version\": \"phony-debian\",
+ \"full-name\": \"Phony Debian\",
+ \"size\": 536870912,
+ \"notes\": \"Phony Debian look-alike used for testing.\",
+ \"hidden\": false
+ },
+ {
+ \"os-version\": \"phony-fedora\",
+ \"full-name\": \"Phony Fedora\",
+ \"size\": 1073741824,
+ \"notes\": \"Phony Fedora look-alike used for testing.\",
+ \"hidden\": false
+ },
+ {
+ \"os-version\": \"phony-fedora-qcow2\",
+ \"full-name\": \"Phony Fedora qcow2\",
+ \"size\": 1073741824,
+ \"notes\": \"Phony Fedora look-alike used for testing.\",
+ \"hidden\": false
+ },
+ {
+ \"os-version\": \"phony-fedora-qcow2-uncompressed\",
+ \"full-name\": \"Phony Fedora qcow2 uncompressed\",
+ \"size\": 1073741824,
+ \"notes\": \"Phony Fedora look-alike used for testing.\",
+ \"hidden\": false
+ },
+ {
+ \"os-version\": \"phony-fedora-no-format\",
+ \"full-name\": \"Phony Fedora\",
+ \"size\": 1073741824,
+ \"notes\": \"Phony Fedora look-alike used for testing.\",
+ \"hidden\": false
+ },
+ {
+ \"os-version\": \"phony-ubuntu\",
+ \"full-name\": \"Phony Ubuntu\",
+ \"size\": 536870912,
+ \"notes\": \"Phony Ubuntu look-alike used for testing.\",
+ \"hidden\": false
+ },
+ {
+ \"os-version\": \"phony-windows\",
+ \"full-name\": \"Phony Windows\",
+ \"size\": 536870912,
+ \"notes\": \"Phony Windows look-alike used for testing.\",
+ \"hidden\": false
+ }
+ ]
+}" ]; then
+ echo "$0: unexpected --list --format json output:"
+ echo "$json_list"
+ exit 1
+fi
diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
index 05abcc6..ded045b 100644
--- a/builder/virt-builder.pod
+++ b/builder/virt-builder.pod
@@ -31,7 +31,7 @@ virt-builder - Build virtual machine images quickly
[--firstboot SCRIPT] [--firstboot-command 'CMD ARGS ...']
[--firstboot-install PKG,[PKG...]]
- virt-builder -l|--list [--long] [--list-format short|long]
+ virt-builder -l|--list [--long] [--list-format short|long|json]
virt-builder --notes os-version
@@ -395,6 +395,16 @@ its short description.
Prints a textual list with the details of the available sources, followed
by the details of the available templates.
+=item B<json>
+
+Prints a JSON object with the details of the available sources and
+the details of the available templates.
+
+The C<version> key in the main object represents the "compatibility
version",
+and it is bumped every time the resulting JSON output is incompatible with
+the previous versions (for example the structure has changed, or non-optional
+keys are no more present).
+
=back
I<--long> is a shorthand for the C<long> format.
--
1.8.3.1