All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Daniel P. Berrange" <berrange@redhat.com>
To: qemu-devel@nongnu.org
Cc: qemu-block@nongnu.org, "Markus Armbruster" <armbru@redhat.com>,
	"Max Reitz" <mreitz@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Andreas Färber" <afaerber@suse.de>,
	"Eric Blake" <eblake@redhat.com>,
	"Daniel P. Berrange" <berrange@redhat.com>
Subject: [Qemu-devel] [PATCH v14 09/21] qapi: permit auto-creating single element lists
Date: Fri, 30 Sep 2016 15:45:32 +0100	[thread overview]
Message-ID: <1475246744-29302-10-git-send-email-berrange@redhat.com> (raw)
In-Reply-To: <1475246744-29302-1-git-send-email-berrange@redhat.com>

When converting QemuOpts to a QObject, there is no information
about compound types available, so when visiting a list, the
corresponding QObject is not guaranteed to be a QList. We
therefore need to be able to auto-create a single element QList
from whatever type we find.

This mode should only be enabled if you have compatibility
requirements for

   -arg foo=hello,foo=world

to be treated as equivalent to the preferred syntax:

   -arg foo.0=hello,foo.1=world

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 include/qapi/qobject-input-visitor.h | 20 +++++++-
 qapi/qobject-input-visitor.c         | 27 +++++++++--
 tests/test-qobject-input-visitor.c   | 88 +++++++++++++++++++++++++++++++-----
 3 files changed, 117 insertions(+), 18 deletions(-)

diff --git a/include/qapi/qobject-input-visitor.h b/include/qapi/qobject-input-visitor.h
index f134d90..1809f48 100644
--- a/include/qapi/qobject-input-visitor.h
+++ b/include/qapi/qobject-input-visitor.h
@@ -42,6 +42,19 @@ Visitor *qobject_input_visitor_new(QObject *obj, bool strict);
  * represented as strings. i.e. if visiting a boolean, the value should
  * be a QString whose contents represent a valid boolean.
  *
+ * If @autocreate_list is true, then as an alternative to a normal QList,
+ * list values can be stored as a QString or QDict instead, which will
+ * be interpreted as representing single element lists. This should only
+ * by used if compatibility is required with the OptsVisitor which allowed
+ * repeated keys, without list indexes, to represent lists. e.g. set this
+ * to true if you have compatibility requirements for
+ *
+ *   -arg foo=hello,foo=world
+ *
+ * to be treated as equivalent to the preferred syntax:
+ *
+ *   -arg foo.0=hello,foo.1=world
+ *
  * The visitor always operates in strict mode, requiring all dict keys
  * to be consumed during visitation. An error will be reported if this
  * does not happen.
@@ -49,7 +62,8 @@ Visitor *qobject_input_visitor_new(QObject *obj, bool strict);
  * The returned input visitor should be released by calling
  * visit_free() when no longer required.
  */
-Visitor *qobject_input_visitor_new_autocast(QObject *obj);
+Visitor *qobject_input_visitor_new_autocast(QObject *obj,
+                                            bool autocreate_list);
 
 
 /**
@@ -64,6 +78,8 @@ Visitor *qobject_input_visitor_new_autocast(QObject *obj);
  * The returned input visitor should be released by calling
  * visit_free() when no longer required.
  */
-Visitor *qobject_input_visitor_new_opts(const QemuOpts *opts, Error **errp);
+Visitor *qobject_input_visitor_new_opts(const QemuOpts *opts,
+                                        bool autocreate_list,
+                                        Error **errp);
 
 #endif
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index d9269c9..d88e9f9 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -48,6 +48,10 @@ struct QObjectInputVisitor
 
     /* True to reject parse in visit_end_struct() if unvisited keys remain. */
     bool strict;
+
+    /* Whether we can auto-create single element lists when
+     * encountering a non-QList type */
+    bool autocreate_list;
 };
 
 static QObjectInputVisitor *to_qiv(Visitor *v)
@@ -108,6 +112,7 @@ static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv,
     assert(obj);
     tos->obj = obj;
     tos->qapi = qapi;
+    qobject_incref(obj);
 
     if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
         h = g_hash_table_new(g_str_hash, g_str_equal);
@@ -147,6 +152,7 @@ static void qobject_input_stack_object_free(StackObject *tos)
     if (tos->h) {
         g_hash_table_unref(tos->h);
     }
+    qobject_decref(tos->obj);
 
     g_free(tos);
 }
@@ -197,7 +203,7 @@ static void qobject_input_start_list(Visitor *v, const char *name,
     QObject *qobj = qobject_input_get_object(qiv, name, true);
     const QListEntry *entry;
 
-    if (!qobj || qobject_type(qobj) != QTYPE_QLIST) {
+    if (!qobj || (!qiv->autocreate_list && qobject_type(qobj) != QTYPE_QLIST)) {
         if (list) {
             *list = NULL;
         }
@@ -206,7 +212,16 @@ static void qobject_input_start_list(Visitor *v, const char *name,
         return;
     }
 
-    entry = qobject_input_push(qiv, qobj, list, errp);
+    if (qobject_type(qobj) != QTYPE_QLIST) {
+        QList *tmplist = qlist_new();
+        qlist_append_obj(tmplist, qobj);
+        qobject_incref(qobj);
+        entry = qobject_input_push(qiv, QOBJECT(tmplist), list, errp);
+        QDECREF(tmplist);
+    } else {
+        entry = qobject_input_push(qiv, qobj, list, errp);
+    }
+
     if (list) {
         if (entry) {
             *list = g_malloc0(size);
@@ -514,7 +529,8 @@ Visitor *qobject_input_visitor_new(QObject *obj, bool strict)
     return &v->visitor;
 }
 
-Visitor *qobject_input_visitor_new_autocast(QObject *obj)
+Visitor *qobject_input_visitor_new_autocast(QObject *obj,
+                                            bool autocreate_list)
 {
     QObjectInputVisitor *v;
 
@@ -539,6 +555,7 @@ Visitor *qobject_input_visitor_new_autocast(QObject *obj)
     v->visitor.optional = qobject_input_optional;
     v->visitor.free = qobject_input_free;
     v->strict = true;
+    v->autocreate_list = autocreate_list;
 
     v->root = obj;
     qobject_incref(obj);
@@ -548,6 +565,7 @@ Visitor *qobject_input_visitor_new_autocast(QObject *obj)
 
 
 Visitor *qobject_input_visitor_new_opts(const QemuOpts *opts,
+                                        bool autocreate_list,
                                         Error **errp)
 {
     QDict *pdict;
@@ -564,7 +582,8 @@ Visitor *qobject_input_visitor_new_opts(const QemuOpts *opts,
         goto cleanup;
     }
 
-    v = qobject_input_visitor_new_autocast(pobj);
+    v = qobject_input_visitor_new_autocast(pobj,
+                                           autocreate_list);
  cleanup:
     qobject_decref(pobj);
     QDECREF(pdict);
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index d5b8044..c227565 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -42,6 +42,7 @@ static void visitor_input_teardown(TestInputVisitorData *data,
    functions (and not in main()). */
 static Visitor *visitor_input_test_init_internal(TestInputVisitorData *data,
                                                  bool strict, bool autocast,
+                                                 bool autocreate_list,
                                                  const char *json_string,
                                                  va_list *ap)
 {
@@ -52,17 +53,20 @@ static Visitor *visitor_input_test_init_internal(TestInputVisitorData *data,
 
     if (autocast) {
         assert(strict);
-        data->qiv = qobject_input_visitor_new_autocast(data->obj);
+        data->qiv = qobject_input_visitor_new_autocast(data->obj,
+                                                       autocreate_list);
     } else {
+        assert(!autocreate_list);
         data->qiv = qobject_input_visitor_new(data->obj, strict);
     }
     g_assert(data->qiv);
     return data->qiv;
 }
 
-static GCC_FMT_ATTR(4, 5)
+static GCC_FMT_ATTR(5, 6)
 Visitor *visitor_input_test_init_full(TestInputVisitorData *data,
                                       bool strict, bool autocast,
+                                      bool autocreate_list,
                                       const char *json_string, ...)
 {
     Visitor *v;
@@ -70,6 +74,7 @@ Visitor *visitor_input_test_init_full(TestInputVisitorData *data,
 
     va_start(ap, json_string);
     v = visitor_input_test_init_internal(data, strict, autocast,
+                                         autocreate_list,
                                          json_string, &ap);
     va_end(ap);
     return v;
@@ -83,7 +88,7 @@ Visitor *visitor_input_test_init(TestInputVisitorData *data,
     va_list ap;
 
     va_start(ap, json_string);
-    v = visitor_input_test_init_internal(data, true, false,
+    v = visitor_input_test_init_internal(data, true, false, false,
                                          json_string, &ap);
     va_end(ap);
     return v;
@@ -99,7 +104,7 @@ Visitor *visitor_input_test_init(TestInputVisitorData *data,
 static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data,
                                             const char *json_string)
 {
-    return visitor_input_test_init_internal(data, true, false,
+    return visitor_input_test_init_internal(data, true, false, false,
                                             json_string, NULL);
 }
 
@@ -139,7 +144,7 @@ static void test_visitor_in_int_autocast(TestInputVisitorData *data,
     Error *err = NULL;
     Visitor *v;
 
-    v = visitor_input_test_init_full(data, true, true,
+    v = visitor_input_test_init_full(data, true, true, false,
                                      "%" PRId64, value);
     visit_type_int(v, NULL, &res, &err);
     error_free_or_abort(&err);
@@ -151,7 +156,7 @@ static void test_visitor_in_int_str_autocast(TestInputVisitorData *data,
     int64_t res = 0, value = -42;
     Visitor *v;
 
-    v = visitor_input_test_init_full(data, true, true,
+    v = visitor_input_test_init_full(data, true, true, false,
                                      "\"-42\"");
 
     visit_type_int(v, NULL, &res, &error_abort);
@@ -190,7 +195,7 @@ static void test_visitor_in_bool_autocast(TestInputVisitorData *data,
     Error *err = NULL;
     Visitor *v;
 
-    v = visitor_input_test_init_full(data, true, true, "true");
+    v = visitor_input_test_init_full(data, true, true, false, "true");
 
     visit_type_bool(v, NULL, &res, &err);
     error_free_or_abort(&err);
@@ -202,7 +207,7 @@ static void test_visitor_in_bool_str_autocast(TestInputVisitorData *data,
     bool res = false;
     Visitor *v;
 
-    v = visitor_input_test_init_full(data, true, true, "\"yes\"");
+    v = visitor_input_test_init_full(data, true, true, false, "\"yes\"");
 
     visit_type_bool(v, NULL, &res, &error_abort);
     g_assert_cmpint(res, ==, true);
@@ -240,7 +245,7 @@ static void test_visitor_in_number_autocast(TestInputVisitorData *data,
     Error *err = NULL;
     Visitor *v;
 
-    v = visitor_input_test_init_full(data, true, true, "%f", value);
+    v = visitor_input_test_init_full(data, true, true, false, "%f", value);
 
     visit_type_number(v, NULL, &res, &err);
     error_free_or_abort(&err);
@@ -252,7 +257,7 @@ static void test_visitor_in_number_str_autocast(TestInputVisitorData *data,
     double res = 0, value = 3.14;
     Visitor *v;
 
-    v = visitor_input_test_init_full(data, true, true, "\"3.14\"");
+    v = visitor_input_test_init_full(data, true, true, false, "\"3.14\"");
 
     visit_type_number(v, NULL, &res, &error_abort);
     g_assert_cmpfloat(res, ==, value);
@@ -277,7 +282,7 @@ static void test_visitor_in_size_str_autocast(TestInputVisitorData *data,
     uint64_t res, value = 500 * 1024 * 1024;
     Visitor *v;
 
-    v = visitor_input_test_init_full(data, true, true, "\"500M\"");
+    v = visitor_input_test_init_full(data, true, true, false, "\"500M\"");
 
     visit_type_size(v, NULL, &res, &error_abort);
     g_assert_cmpfloat(res, ==, value);
@@ -396,6 +401,59 @@ static void test_visitor_in_list(TestInputVisitorData *data,
     g_assert(!head);
 }
 
+static void test_visitor_in_list_autocreate_none(TestInputVisitorData *data,
+                                                 const void *unused)
+{
+    UserDefOneList *head = NULL;
+    Visitor *v;
+    Error *err = NULL;
+
+    v = visitor_input_test_init_full(data, true, true, false,
+                                     "{ 'string': 'string0', 'integer': 42 }");
+
+    visit_type_UserDefOneList(v, NULL, &head, &err);
+    error_free_or_abort(&err);
+    g_assert(head == NULL);
+}
+
+static void test_visitor_in_list_autocreate_dict(TestInputVisitorData *data,
+                                                 const void *unused)
+{
+    UserDefOneList *head = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init_full(data, true, true, true,
+                                     "{ 'string': 'string0', 'integer': '42' }");
+
+    visit_type_UserDefOneList(v, NULL, &head, &error_abort);
+    g_assert(head != NULL);
+
+    g_assert_cmpstr(head->value->string, ==, "string0");
+    g_assert_cmpint(head->value->integer, ==, 42);
+    g_assert(head->next == NULL);
+
+    qapi_free_UserDefOneList(head);
+    head = NULL;
+}
+
+static void test_visitor_in_list_autocreate_int(TestInputVisitorData *data,
+                                                const void *unused)
+{
+    uint32List *head = NULL;
+    Visitor *v;
+
+    /* Verify that we auto-create a single element list from the int */
+    v = visitor_input_test_init_full(data, true, true, true, "'42'");
+
+    visit_type_uint32List(v, NULL, &head, &error_abort);
+    g_assert(head != NULL);
+
+    g_assert_cmpint(head->value, ==, 42);
+
+    qapi_free_uint32List(head);
+    head = NULL;
+}
+
 static void test_visitor_in_any(TestInputVisitorData *data,
                                 const void *unused)
 {
@@ -452,7 +510,7 @@ static void test_visitor_in_null(TestInputVisitorData *data,
      * when input is not null.
      */
 
-    v = visitor_input_test_init_full(data, false, false,
+    v = visitor_input_test_init_full(data, false, false, false,
                                      "{ 'a': null, 'b': '' }");
     visit_start_struct(v, NULL, NULL, 0, &error_abort);
     visit_type_null(v, "a", &error_abort);
@@ -1040,6 +1098,12 @@ int main(int argc, char **argv)
                            NULL, test_visitor_in_struct_nested);
     input_visitor_test_add("/visitor/input/list",
                            NULL, test_visitor_in_list);
+    input_visitor_test_add("/visitor/input/list-autocreate-noautocast",
+                           NULL, test_visitor_in_list_autocreate_none);
+    input_visitor_test_add("/visitor/input/list-autocreate-autocast",
+                           NULL, test_visitor_in_list_autocreate_dict);
+    input_visitor_test_add("/visitor/input/list-autocreate-int",
+                           NULL, test_visitor_in_list_autocreate_int);
     input_visitor_test_add("/visitor/input/any",
                            NULL, test_visitor_in_any);
     input_visitor_test_add("/visitor/input/null",
-- 
2.7.4

  parent reply	other threads:[~2016-09-30 14:46 UTC|newest]

Thread overview: 109+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-30 14:45 [Qemu-devel] [PATCH v14 00/21] QAPI/QOM work for non-scalar object properties Daniel P. Berrange
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 01/21] option: make parse_option_bool/number non-static Daniel P. Berrange
2016-10-21 16:55   ` Markus Armbruster
2016-10-21 17:12     ` Eric Blake
2016-10-21 17:51       ` Markus Armbruster
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 02/21] qdict: implement a qdict_crumple method for un-flattening a dict Daniel P. Berrange
2016-10-18 14:32   ` Markus Armbruster
2016-10-20 14:11     ` Daniel P. Berrange
2016-10-21  9:58       ` Markus Armbruster
2016-10-21 18:31         ` Max Reitz
2016-10-24  9:18           ` Markus Armbruster
2016-10-24 10:28             ` Daniel P. Berrange
2016-10-24 12:38               ` Markus Armbruster
2016-10-25 10:03           ` Markus Armbruster
2016-10-25 10:20             ` Daniel P. Berrange
2016-10-25 12:29               ` Markus Armbruster
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 03/21] qapi: add trace events for visitor Daniel P. Berrange
2016-09-30 15:49   ` Eric Blake
2016-10-06 14:39   ` [Qemu-devel] [Qemu-block] " Kevin Wolf
2016-10-07 13:59   ` [Qemu-devel] " Markus Armbruster
2016-10-07 14:16     ` Daniel P. Berrange
2016-10-21 10:52       ` Markus Armbruster
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 04/21] qapi: rename QmpInputVisitor to QObjectInputVisitor Daniel P. Berrange
2016-10-25 13:41   ` Markus Armbruster
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 05/21] qapi: rename QmpOutputVisitor to QObjectOutputVisitor Daniel P. Berrange
2016-10-25 13:36   ` Markus Armbruster
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 06/21] qapi: don't pass two copies of TestInputVisitorData to tests Daniel P. Berrange
2016-09-30 17:43   ` Eric Blake
2016-10-06 14:39   ` [Qemu-devel] [Qemu-block] " Kevin Wolf
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 07/21] qapi: permit scalar type conversions in QObjectInputVisitor Daniel P. Berrange
2016-09-30 17:48   ` Eric Blake
2016-10-11 16:20   ` Markus Armbruster
2016-10-12 14:51     ` Markus Armbruster
2016-10-12 15:05       ` Markus Armbruster
2016-10-12 15:26         ` Markus Armbruster
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 08/21] qapi: allow QObjectInputVisitor to be created with QemuOpts Daniel P. Berrange
2016-09-30 17:55   ` Eric Blake
2016-10-06 14:56   ` [Qemu-devel] [Qemu-block] " Kevin Wolf
2016-10-12  8:08   ` [Qemu-devel] " Markus Armbruster
2016-10-13  7:23     ` Markus Armbruster
2016-09-30 14:45 ` Daniel P. Berrange [this message]
2016-09-30 17:59   ` [Qemu-devel] [PATCH v14 09/21] qapi: permit auto-creating single element lists Eric Blake
2016-10-12  9:18   ` Markus Armbruster
2016-10-20 14:23     ` Daniel P. Berrange
2016-10-21 11:58       ` Markus Armbruster
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 10/21] qapi: permit auto-creating nested structs Daniel P. Berrange
2016-09-30 18:23   ` Eric Blake
2016-10-06 15:10   ` [Qemu-devel] [Qemu-block] " Kevin Wolf
2016-10-06 15:18     ` Daniel P. Berrange
2016-10-06 15:30       ` Kevin Wolf
2016-10-06 15:39         ` Daniel P. Berrange
2016-10-06 15:51           ` Kevin Wolf
2016-10-06 15:57             ` Daniel P. Berrange
2016-10-12 14:00               ` Markus Armbruster
2016-10-06 17:54         ` Eric Blake
2016-10-12 14:12   ` [Qemu-devel] " Markus Armbruster
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 11/21] qapi: add integer range support for QObjectInputVisitor Daniel P. Berrange
2016-09-30 19:45   ` Eric Blake
2016-10-12 15:50   ` Markus Armbruster
2016-10-12 16:03     ` [Qemu-devel] [Qemu-block] " Kevin Wolf
2016-10-12 18:14       ` Markus Armbruster
2016-10-20 14:28     ` [Qemu-devel] " Daniel P. Berrange
2016-10-21 10:58       ` Markus Armbruster
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 12/21] option: allow qemu_opts_to_qdict to merge repeated options Daniel P. Berrange
2016-09-30 20:08   ` Eric Blake
2016-10-12 17:46   ` Markus Armbruster
2016-10-13  9:21     ` Markus Armbruster
2016-10-20 14:29     ` Daniel P. Berrange
2016-10-21 11:09       ` Markus Armbruster
2016-10-21 11:14         ` Daniel P. Berrange
2016-10-13  8:31   ` Markus Armbruster
2016-10-20 14:37     ` Daniel P. Berrange
2016-10-21 11:28       ` Markus Armbruster
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 13/21] qdict: allow qdict_crumple to accept compound types as values Daniel P. Berrange
2016-10-13 12:35   ` Markus Armbruster
2016-10-13 14:46     ` Kevin Wolf
2016-10-17 14:50       ` Markus Armbruster
2016-10-17 15:43         ` Paolo Bonzini
2016-10-17 17:48           ` Markus Armbruster
2016-10-17 17:38         ` Eric Blake
2016-10-18 10:59           ` Markus Armbruster
2016-10-18  9:34         ` Kevin Wolf
2016-10-18 15:35           ` Markus Armbruster
2016-10-19  9:25             ` Kevin Wolf
2016-10-19  9:42               ` Daniel P. Berrange
2016-10-19 13:31             ` [Qemu-devel] [Qemu-block] " Eric Blake
2016-10-20 14:46     ` [Qemu-devel] " Daniel P. Berrange
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 14/21] qapi: allow repeated opts with qobject_input_visitor_new_opts Daniel P. Berrange
2016-10-18 17:13   ` Markus Armbruster
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 15/21] qom: support non-scalar properties with -object Daniel P. Berrange
2016-10-19 16:54   ` Markus Armbruster
2017-07-10 19:30   ` Manos Pitsidianakis
2017-07-11  8:10     ` Markus Armbruster
2017-07-11 14:44       ` Markus Armbruster
2017-07-11 14:49         ` Daniel P. Berrange
2017-07-12 17:56           ` Manos Pitsidianakis
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 16/21] hmp: support non-scalar properties with object_add Daniel P. Berrange
2016-10-20  6:43   ` Markus Armbruster
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 17/21] numa: convert to use QObjectInputVisitor for -numa Daniel P. Berrange
2016-10-20  6:57   ` Markus Armbruster
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 18/21] block: convert crypto driver to use QObjectInputVisitor Daniel P. Berrange
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 19/21] acpi: convert to QObjectInputVisitor for -acpi parsing Daniel P. Berrange
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 20/21] net: convert to QObjectInputVisitor for -net/-netdev parsing Daniel P. Berrange
2016-10-20  7:38   ` Markus Armbruster
2016-10-20 13:43     ` [Qemu-devel] [Qemu-block] " Eric Blake
2016-09-30 14:45 ` [Qemu-devel] [PATCH v14 21/21] qapi: delete unused OptsVisitor code Daniel P. Berrange
2016-09-30 15:45 ` [Qemu-devel] [PATCH v14 00/21] QAPI/QOM work for non-scalar object properties no-reply
2016-09-30 18:50   ` Eric Blake
2016-10-21 18:30 ` Markus Armbruster

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1475246744-29302-10-git-send-email-berrange@redhat.com \
    --to=berrange@redhat.com \
    --cc=afaerber@suse.de \
    --cc=armbru@redhat.com \
    --cc=eblake@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.