cli: convert: allow multiple paths to be passed as leftover arguments
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Fri, 9 Jun 2017 21:15:55 +0000 (17:15 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 9 Jun 2017 22:18:17 +0000 (18:18 -0400)
Allow this:

    babeltrace /path/to/trace1 /path/to/trace2 /path/to/trace3

This worked with Babeltrace 1 and needs to work with Babeltrace 2.

What's done here is that a _base_ implicit set of arguments for an
eventual source.ctf.fs component is created implicitly or by default
like it used to be. For each leftover argument, we copy this base set of
arguments and append the `path` parameter with the specific leftover
argument. Then we name and connect those source components as usual.
What's left is one source.ctf.fs component for each individual path.
Each individual component can still recurse.

tests/cli/test_convert_args is updated because it used to check that a
command line with multiple leftovers was expected to fail, but it
doesn't with this patch.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
cli/babeltrace-cfg-cli-args.c
tests/cli/test_convert_args.in

index 757ed1129a109af7ec2b1cc961c378d7b7dea8a7..6a711726dd03b43bd9191e59ecebcc376863b565 100644 (file)
@@ -932,12 +932,12 @@ end:
 static
 void destroy_glist_of_gstring(GList *list)
 {
+       GList *at;
+
        if (!list) {
                return;
        }
 
-       GList *at;
-
        for (at = list; at != NULL; at = g_list_next(at)) {
                g_string_free(at->data, TRUE);
        }
@@ -3083,7 +3083,7 @@ end:
 }
 
 static
-void destroy_implicit_component_args(struct implicit_component_args *args)
+void finalize_implicit_component_args(struct implicit_component_args *args)
 {
        assert(args);
 
@@ -3102,6 +3102,17 @@ void destroy_implicit_component_args(struct implicit_component_args *args)
        bt_put(args->extra_params);
 }
 
+static
+void destroy_implicit_component_args(void *args)
+{
+       if (!args) {
+               return;
+       }
+
+       finalize_implicit_component_args(args);
+       g_free(args);
+}
+
 static
 int init_implicit_component_args(struct implicit_component_args *args,
                const char *comp_arg, bool exists)
@@ -3117,7 +3128,7 @@ int init_implicit_component_args(struct implicit_component_args *args,
        if (!args->comp_arg || !args->name_arg ||
                        !args->params_arg || !args->extra_params) {
                ret = -1;
-               destroy_implicit_component_args(args);
+               finalize_implicit_component_args(args);
                print_err_oom();
                goto end;
        }
@@ -3486,6 +3497,84 @@ end:
        return ret;
 }
 
+static
+struct implicit_component_args *create_implicit_component_args(void)
+{
+       struct implicit_component_args *impl_args =
+               g_new0(struct implicit_component_args, 1);
+
+       if (!impl_args) {
+               goto end;
+       }
+
+       if (init_implicit_component_args(impl_args, NULL, true)) {
+               destroy_implicit_component_args(impl_args);
+               impl_args = NULL;
+               goto end;
+       }
+
+end:
+       return impl_args;
+}
+
+static
+int fill_implicit_ctf_inputs_args(GPtrArray *implicit_ctf_inputs_args,
+               struct implicit_component_args *base_implicit_ctf_input_args,
+               GList *leftovers)
+{
+       int ret = 0;
+       GList *leftover;
+
+       for (leftover = leftovers; leftover != NULL;
+                       leftover = g_list_next(leftover)) {
+               GString *gs_leftover = leftover->data;
+               struct implicit_component_args *impl_args =
+                       create_implicit_component_args();
+
+               if (!impl_args) {
+                       print_err_oom();
+                       goto error;
+               }
+
+               impl_args->exists = true;
+               g_string_assign(impl_args->comp_arg,
+                       base_implicit_ctf_input_args->comp_arg->str);
+               g_string_assign(impl_args->params_arg,
+                       base_implicit_ctf_input_args->params_arg->str);
+
+               /*
+                * We need our own copy of the extra parameters because
+                * this is where the unique path goes.
+                */
+               BT_PUT(impl_args->extra_params);
+               impl_args->extra_params =
+                       bt_value_copy(base_implicit_ctf_input_args->extra_params);
+               if (!impl_args) {
+                       print_err_oom();
+                       destroy_implicit_component_args(impl_args);
+                       goto error;
+               }
+
+               /* Append unique path parameter */
+               ret = append_implicit_component_extra_param(impl_args,
+                       "path", gs_leftover->str);
+               if (ret) {
+                       destroy_implicit_component_args(impl_args);
+                       goto error;
+               }
+
+               g_ptr_array_add(implicit_ctf_inputs_args, impl_args);
+       }
+
+       goto end;
+
+error:
+       ret = -1;
+
+end:
+       return ret;
+}
+
 /*
  * Creates a Babeltrace config object from the arguments of a convert
  * command.
@@ -3521,7 +3610,9 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
        GList *source_names = NULL;
        GList *filter_names = NULL;
        GList *sink_names = NULL;
-       struct implicit_component_args implicit_ctf_input_args = { 0 };
+       GList *leftovers = NULL;
+       GPtrArray *implicit_ctf_inputs_args = NULL;
+       struct implicit_component_args base_implicit_ctf_input_args = { 0 };
        struct implicit_component_args implicit_ctf_output_args = { 0 };
        struct implicit_component_args implicit_lttng_live_args = { 0 };
        struct implicit_component_args implicit_dummy_args = { 0 };
@@ -3543,7 +3634,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
                goto end;
        }
 
-       if (init_implicit_component_args(&implicit_ctf_input_args,
+       if (init_implicit_component_args(&base_implicit_ctf_input_args,
                        "source.ctf.fs", false)) {
                goto error;
        }
@@ -3583,6 +3674,13 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
                goto error;
        }
 
+       implicit_ctf_inputs_args = g_ptr_array_new_with_free_func(
+               (GDestroyNotify) destroy_implicit_component_args);
+       if (!implicit_ctf_inputs_args) {
+               print_err_oom();
+               goto error;
+       }
+
        all_names = bt_value_map_create();
        if (!all_names) {
                print_err_oom();
@@ -4006,17 +4104,18 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
                        implicit_text_args.exists = true;
                        break;
                case OPT_CLOCK_OFFSET:
-                       implicit_ctf_input_args.exists = true;
+                       base_implicit_ctf_input_args.exists = true;
                        ret = append_implicit_component_extra_param(
-                               &implicit_ctf_input_args, "clock-offset-cycles", arg);
+                               &base_implicit_ctf_input_args, "clock-offset-cycles", arg);
                        if (ret) {
                                goto error;
                        }
                        break;
                case OPT_CLOCK_OFFSET_NS:
-                       implicit_ctf_input_args.exists = true;
+                       base_implicit_ctf_input_args.exists = true;
                        ret = append_implicit_component_extra_param(
-                               &implicit_ctf_input_args, "clock-offset-ns", arg);
+                               &base_implicit_ctf_input_args,
+                               "clock-offset-ns", arg);
                        if (ret) {
                                goto error;
                        }
@@ -4109,7 +4208,7 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
                        got_input_format_opt = true;
 
                        if (strcmp(arg, "ctf") == 0) {
-                               implicit_ctf_input_args.exists = true;
+                               base_implicit_ctf_input_args.exists = true;
                        } else if (strcmp(arg, "lttng-live") == 0) {
                                implicit_lttng_live_args.exists = true;
                        } else {
@@ -4169,9 +4268,10 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
                        print_run_args_0 = true;
                        break;
                case OPT_STREAM_INTERSECTION:
-                       append_implicit_component_param(&implicit_ctf_input_args,
+                       append_implicit_component_param(
+                               &base_implicit_ctf_input_args,
                                "stream-intersection", "yes");
-                       implicit_ctf_input_args.exists = true;
+                       base_implicit_ctf_input_args.exists = true;
                        break;
                case OPT_VERBOSE:
                        if (got_verbose_opt) {
@@ -4210,22 +4310,37 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
                goto error;
        }
 
-       /* Consume leftover argument */
-       leftover = poptGetArg(pc);
+       /* Consume and keep leftover arguments */
+       while ((leftover = poptGetArg(pc))) {
+               GString *gs_leftover = g_string_new(leftover);
 
-       if (poptPeekArg(pc)) {
-               printf_err("Unexpected argument:\n    %s\n",
-                       poptPeekArg(pc));
-               goto error;
+               if (!gs_leftover) {
+                       print_err_oom();
+                       goto error;
+               }
+
+               leftovers = g_list_append(leftovers, gs_leftover);
+               if (!leftovers) {
+                       g_string_free(gs_leftover, TRUE);
+                       print_err_oom();
+                       goto error;
+               }
        }
 
        /* Print CTF metadata or print LTTng live sessions */
        if (print_ctf_metadata) {
-               if (!leftover) {
+               GString *gs_leftover;
+
+               if (g_list_length(leftovers) == 0) {
                        printf_err("--output-format=ctf-metadata specified without a path\n");
                        goto error;
                }
 
+               if (g_list_length(leftovers) > 1) {
+                       printf_err("Too many paths specified for --output-format=ctf-metadata\n");
+                       goto error;
+               }
+
                cfg = bt_config_print_ctf_metadata_create(plugin_paths);
                if (!cfg) {
                        goto error;
@@ -4233,8 +4348,9 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
 
                cfg->debug = got_debug_opt;
                cfg->verbose = got_verbose_opt;
+               gs_leftover = leftovers->data;
                g_string_assign(cfg->cmd_data.print_ctf_metadata.path,
-                       leftover);
+                       gs_leftover->str);
                goto end;
        }
 
@@ -4292,11 +4408,19 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
                }
        }
 
-       /* Decide where the leftover argument goes */
-       if (leftover) {
+       /* Decide where the leftover argument(s) go */
+       if (g_list_length(leftovers) > 0) {
                if (implicit_lttng_live_args.exists) {
+                       GString *gs_leftover;
+
+                       if (g_list_length(leftovers) > 1) {
+                               printf_err("Too many URLs specified for --output-format=lttng-live\n");
+                               goto error;
+                       }
+
+                       gs_leftover = leftovers->data;
                        lttng_live_url_parts =
-                               bt_common_parse_lttng_live_url(leftover,
+                               bt_common_parse_lttng_live_url(gs_leftover->str,
                                        error_buf, sizeof(error_buf));
                        if (!lttng_live_url_parts.proto) {
                                printf_err("Invalid LTTng live URL format: %s\n",
@@ -4315,19 +4439,26 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
                                cfg->debug = got_debug_opt;
                                cfg->verbose = got_verbose_opt;
                                g_string_assign(cfg->cmd_data.print_lttng_live_sessions.url,
-                                       leftover);
+                                       gs_leftover->str);
                                goto end;
                        }
 
                        ret = append_implicit_component_extra_param(
-                               &implicit_lttng_live_args, "url", leftover);
+                               &implicit_lttng_live_args, "url",
+                               gs_leftover->str);
                        if (ret) {
                                goto error;
                        }
                } else {
-                       ret = append_implicit_component_extra_param(
-                               &implicit_ctf_input_args, "path", leftover);
-                       implicit_ctf_input_args.exists = true;
+                       /*
+                        * Append one implicit component argument set
+                        * for each leftover (souce.ctf.fs paths). Copy
+                        * the base implicit component arguments.
+                        * Note that they still have to be named later.
+                        */
+                       ret = fill_implicit_ctf_inputs_args(
+                               implicit_ctf_inputs_args,
+                               &base_implicit_ctf_input_args, leftovers);
                        if (ret) {
                                goto error;
                        }
@@ -4338,35 +4469,42 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
         * Ensure mutual exclusion between implicit `source.ctf.fs` and
         * `source.ctf.lttng-live` components.
         */
-       if (implicit_ctf_input_args.exists && implicit_lttng_live_args.exists) {
+       if (base_implicit_ctf_input_args.exists &&
+                       implicit_lttng_live_args.exists) {
                printf_err("Cannot create both implicit `%s` and `%s` components\n",
-                       implicit_ctf_input_args.comp_arg->str,
+                       base_implicit_ctf_input_args.comp_arg->str,
                        implicit_lttng_live_args.comp_arg->str);
                goto error;
        }
 
        /*
         * If the implicit `source.ctf.fs` or `source.ctf.lttng-live`
-        * components exists, make sure there's a leftover (which is the
-        * path or URL).
+        * components exists, make sure there's at least one leftover
+        * (which is the path or URL).
         */
-       if (implicit_ctf_input_args.exists && !leftover) {
+       if (base_implicit_ctf_input_args.exists &&
+                       g_list_length(leftovers) == 0) {
                printf_err("Missing path for implicit `%s` component\n",
-                       implicit_ctf_input_args.comp_arg->str);
+                       base_implicit_ctf_input_args.comp_arg->str);
                goto error;
        }
 
-       if (implicit_lttng_live_args.exists && !leftover) {
+       if (implicit_lttng_live_args.exists && g_list_length(leftovers) == 0) {
                printf_err("Missing URL for implicit `%s` component\n",
                        implicit_lttng_live_args.comp_arg->str);
                goto error;
        }
 
        /* Assign names to implicit components */
-       ret = assign_name_to_implicit_component(&implicit_ctf_input_args,
-               "source-ctf-fs", all_names, &source_names, true);
-       if (ret) {
-               goto error;
+       for (i = 0; i < implicit_ctf_inputs_args->len; i++) {
+               struct implicit_component_args *impl_args =
+                       g_ptr_array_index(implicit_ctf_inputs_args, i);
+
+               ret = assign_name_to_implicit_component(impl_args,
+                       "source-ctf-fs", all_names, &source_names, true);
+               if (ret) {
+                       goto error;
+               }
        }
 
        ret = assign_name_to_implicit_component(&implicit_lttng_live_args,
@@ -4452,10 +4590,15 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[],
         * Append the equivalent run arguments for the implicit
         * components.
         */
-       ret = append_run_args_for_implicit_component(&implicit_ctf_input_args,
-               run_args);
-       if (ret) {
-               goto error;
+       for (i = 0; i < implicit_ctf_inputs_args->len; i++) {
+               struct implicit_component_args *impl_args =
+                       g_ptr_array_index(implicit_ctf_inputs_args, i);
+
+               ret = append_run_args_for_implicit_component(impl_args,
+                       run_args);
+               if (ret) {
+                       goto error;
+               }
        }
 
        ret = append_run_args_for_implicit_component(&implicit_lttng_live_args,
@@ -4582,19 +4725,24 @@ end:
                g_string_free(cur_name_prefix, TRUE);
        }
 
+       if (implicit_ctf_inputs_args) {
+               g_ptr_array_free(implicit_ctf_inputs_args, TRUE);
+       }
+
        bt_put(run_args);
        bt_put(all_names);
        destroy_glist_of_gstring(source_names);
        destroy_glist_of_gstring(filter_names);
        destroy_glist_of_gstring(sink_names);
-       destroy_implicit_component_args(&implicit_ctf_input_args);
-       destroy_implicit_component_args(&implicit_ctf_output_args);
-       destroy_implicit_component_args(&implicit_lttng_live_args);
-       destroy_implicit_component_args(&implicit_dummy_args);
-       destroy_implicit_component_args(&implicit_text_args);
-       destroy_implicit_component_args(&implicit_debug_info_args);
-       destroy_implicit_component_args(&implicit_muxer_args);
-       destroy_implicit_component_args(&implicit_trimmer_args);
+       destroy_glist_of_gstring(leftovers);
+       finalize_implicit_component_args(&base_implicit_ctf_input_args);
+       finalize_implicit_component_args(&implicit_ctf_output_args);
+       finalize_implicit_component_args(&implicit_lttng_live_args);
+       finalize_implicit_component_args(&implicit_dummy_args);
+       finalize_implicit_component_args(&implicit_text_args);
+       finalize_implicit_component_args(&implicit_debug_info_args);
+       finalize_implicit_component_args(&implicit_muxer_args);
+       finalize_implicit_component_args(&implicit_trimmer_args);
        bt_put(plugin_paths);
        bt_common_destroy_lttng_live_url_parts(&lttng_live_url_parts);
        return cfg;
index 896a8d1d083da0d7b87da40668b3b9584857aa26..7498f120a7459f0132d3416ab19a32d9a1e6fdfa 100644 (file)
@@ -70,7 +70,7 @@ comment() {
        echo "### $1 ###"
 }
 
-plan_tests 77
+plan_tests 76
 
 test_bt_convert_run_args 'path leftover' '/path/to/trace' '--component source.ctf.fs --name source-ctf-fs --key path --value /path/to/trace --component sink.text.pretty --name pretty --component filter.utils.muxer --name muxer --component filter.lttng-utils.debug-info --name debug-info --connect source-ctf-fs:muxer --connect muxer:debug-info --connect debug-info:pretty'
 test_bt_convert_run_args 'path leftover + named user source with --params' '/path/to/trace --component ZZ:source.another.source --params salut=yes' '--component ZZ:source.another.source --params salut=yes --component source.ctf.fs --name source-ctf-fs --key path --value /path/to/trace --component sink.text.pretty --name pretty --component filter.utils.muxer --name muxer --component filter.lttng-utils.debug-info --name debug-info --connect ZZ:muxer --connect source-ctf-fs:muxer --connect muxer:debug-info --connect debug-info:pretty'
@@ -142,7 +142,6 @@ test_bt_convert_fails 'unknown -o' '-o lol'
 test_bt_convert_fails 'duplicate -o' '-o dummy --clock-seconds --output-format=text'
 test_bt_convert_fails '--run-args and --run-args-0' '/path/to/trace --run-args --run-args-0'
 test_bt_convert_fails 'duplicate -v' '/path/to/trace -vv'
-test_bt_convert_fails 'two leftover arguments' '/path/to/trace /other/path'
 test_bt_convert_fails '-o ctf-metadata without path' '-o ctf-metadata'
 test_bt_convert_fails '-i lttng-live and implicit source.ctf.fs' '-i lttng-live net://some-host/host/target/session --clock-offset=23'
 test_bt_convert_fails 'implicit source.ctf.fs without path' '--clock-offset=23'
This page took 0.032976 seconds and 4 git commands to generate.