Merge branch 'jk/argv-array'
authorJunio C Hamano <gitster@pobox.com>
Tue, 11 Sep 2012 18:36:18 +0000 (11:36 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 11 Sep 2012 18:36:18 +0000 (11:36 -0700)
Use argv-array API in "git fetch" implementation.

* jk/argv-array:
submodule: use argv_array instead of hand-building arrays
fetch: use argv_array instead of hand-building arrays
argv-array: fix bogus cast when freeing array
argv-array: add pop function

1  2 
builtin/fetch.c
submodule.c
diff --combined builtin/fetch.c
index 97a849a9dc082555fe1cbe6d0216d03563c75951,6196e91798dd075800b24d8b9129f0321f7b7338..24be754e1b4444ea46752016ba77bdef1c892712
  #include "transport.h"
  #include "submodule.h"
  #include "connected.h"
+ #include "argv-array.h"
  
  static const char * const builtin_fetch_usage[] = {
 -      "git fetch [<options>] [<repository> [<refspec>...]]",
 -      "git fetch [<options>] <group>",
 -      "git fetch --multiple [<options>] [(<repository> | <group>)...]",
 -      "git fetch --all [<options>]",
 +      N_("git fetch [<options>] [<repository> [<refspec>...]]"),
 +      N_("git fetch [<options>] <group>"),
 +      N_("git fetch --multiple [<options>] [(<repository> | <group>)...]"),
 +      N_("git fetch --all [<options>]"),
        NULL
  };
  
@@@ -56,36 -57,36 +57,36 @@@ static int option_parse_recurse_submodu
  static struct option builtin_fetch_options[] = {
        OPT__VERBOSITY(&verbosity),
        OPT_BOOLEAN(0, "all", &all,
 -                  "fetch from all remotes"),
 +                  N_("fetch from all remotes")),
        OPT_BOOLEAN('a', "append", &append,
 -                  "append to .git/FETCH_HEAD instead of overwriting"),
 -      OPT_STRING(0, "upload-pack", &upload_pack, "path",
 -                 "path to upload pack on remote end"),
 -      OPT__FORCE(&force, "force overwrite of local branch"),
 +                  N_("append to .git/FETCH_HEAD instead of overwriting")),
 +      OPT_STRING(0, "upload-pack", &upload_pack, N_("path"),
 +                 N_("path to upload pack on remote end")),
 +      OPT__FORCE(&force, N_("force overwrite of local branch")),
        OPT_BOOLEAN('m', "multiple", &multiple,
 -                  "fetch from multiple remotes"),
 +                  N_("fetch from multiple remotes")),
        OPT_SET_INT('t', "tags", &tags,
 -                  "fetch all tags and associated objects", TAGS_SET),
 +                  N_("fetch all tags and associated objects"), TAGS_SET),
        OPT_SET_INT('n', NULL, &tags,
 -                  "do not fetch all tags (--no-tags)", TAGS_UNSET),
 +                  N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
        OPT_BOOLEAN('p', "prune", &prune,
 -                  "prune remote-tracking branches no longer on remote"),
 -      { OPTION_CALLBACK, 0, "recurse-submodules", NULL, "on-demand",
 -                  "control recursive fetching of submodules",
 +                  N_("prune remote-tracking branches no longer on remote")),
 +      { OPTION_CALLBACK, 0, "recurse-submodules", NULL, N_("on-demand"),
 +                  N_("control recursive fetching of submodules"),
                    PARSE_OPT_OPTARG, option_parse_recurse_submodules },
        OPT_BOOLEAN(0, "dry-run", &dry_run,
 -                  "dry run"),
 -      OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
 +                  N_("dry run")),
 +      OPT_BOOLEAN('k', "keep", &keep, N_("keep downloaded pack")),
        OPT_BOOLEAN('u', "update-head-ok", &update_head_ok,
 -                  "allow updating of HEAD ref"),
 -      OPT_BOOL(0, "progress", &progress, "force progress reporting"),
 -      OPT_STRING(0, "depth", &depth, "depth",
 -                 "deepen history of shallow clone"),
 -      { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, "dir",
 -                 "prepend this to submodule path output", PARSE_OPT_HIDDEN },
 +                  N_("allow updating of HEAD ref")),
 +      OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
 +      OPT_STRING(0, "depth", &depth, N_("depth"),
 +                 N_("deepen history of shallow clone")),
 +      { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
 +                 N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
        { OPTION_STRING, 0, "recurse-submodules-default",
                   &recurse_submodules_default, NULL,
 -                 "default mode for recursion", PARSE_OPT_HIDDEN },
 +                 N_("default mode for recursion"), PARSE_OPT_HIDDEN },
        OPT_END()
  };
  
@@@ -323,7 -324,7 +324,7 @@@ static int update_local_ref(struct ref 
                return r;
        }
  
 -      if (in_merge_bases(current, &updated, 1)) {
 +      if (in_merge_bases(current, updated)) {
                char quickref[83];
                int r;
                strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
@@@ -546,8 -547,8 +547,8 @@@ static int prune_refs(struct refspec *r
        int result = 0;
        struct ref *ref, *stale_refs = get_stale_heads(refs, ref_count, ref_map);
        const char *dangling_msg = dry_run
 -              ? _("   (%s will become dangling)\n")
 -              : _("   (%s has become dangling)\n");
 +              ? _("   (%s will become dangling)")
 +              : _("   (%s has become dangling)");
  
        for (ref = stale_refs; ref; ref = ref->next) {
                if (!dry_run)
@@@ -841,38 -842,35 +842,35 @@@ static int add_remote_or_group(const ch
        return 1;
  }
  
- static void add_options_to_argv(int *argc, const char **argv)
+ static void add_options_to_argv(struct argv_array *argv)
  {
        if (dry_run)
-               argv[(*argc)++] = "--dry-run";
+               argv_array_push(argv, "--dry-run");
        if (prune)
-               argv[(*argc)++] = "--prune";
+               argv_array_push(argv, "--prune");
        if (update_head_ok)
-               argv[(*argc)++] = "--update-head-ok";
+               argv_array_push(argv, "--update-head-ok");
        if (force)
-               argv[(*argc)++] = "--force";
+               argv_array_push(argv, "--force");
        if (keep)
-               argv[(*argc)++] = "--keep";
+               argv_array_push(argv, "--keep");
        if (recurse_submodules == RECURSE_SUBMODULES_ON)
-               argv[(*argc)++] = "--recurse-submodules";
+               argv_array_push(argv, "--recurse-submodules");
        else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)
-               argv[(*argc)++] = "--recurse-submodules=on-demand";
+               argv_array_push(argv, "--recurse-submodules=on-demand");
        if (verbosity >= 2)
-               argv[(*argc)++] = "-v";
+               argv_array_push(argv, "-v");
        if (verbosity >= 1)
-               argv[(*argc)++] = "-v";
+               argv_array_push(argv, "-v");
        else if (verbosity < 0)
-               argv[(*argc)++] = "-q";
+               argv_array_push(argv, "-q");
  
  }
  
  static int fetch_multiple(struct string_list *list)
  {
        int i, result = 0;
-       const char *argv[12] = { "fetch", "--append" };
-       int argc = 2;
-       add_options_to_argv(&argc, argv);
+       struct argv_array argv = ARGV_ARRAY_INIT;
  
        if (!append && !dry_run) {
                int errcode = truncate_fetch_head();
                        return errcode;
        }
  
+       argv_array_pushl(&argv, "fetch", "--append", NULL);
+       add_options_to_argv(&argv);
        for (i = 0; i < list->nr; i++) {
                const char *name = list->items[i].string;
-               argv[argc] = name;
-               argv[argc + 1] = NULL;
+               argv_array_push(&argv, name);
                if (verbosity >= 0)
                        printf(_("Fetching %s\n"), name);
-               if (run_command_v_opt(argv, RUN_GIT_CMD)) {
+               if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
                        error(_("Could not fetch %s"), name);
                        result = 1;
                }
+               argv_array_pop(&argv);
        }
  
+       argv_array_clear(&argv);
        return result;
  }
  
@@@ -1007,13 -1009,14 +1009,14 @@@ int cmd_fetch(int argc, const char **ar
        }
  
        if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) {
-               const char *options[10];
-               int num_options = 0;
-               add_options_to_argv(&num_options, options);
-               result = fetch_populated_submodules(num_options, options,
+               struct argv_array options = ARGV_ARRAY_INIT;
+               add_options_to_argv(&options);
+               result = fetch_populated_submodules(&options,
                                                    submodule_prefix,
                                                    recurse_submodules,
                                                    verbosity < 0);
+               argv_array_clear(&options);
        }
  
        /* All names were strdup()ed or strndup()ed */
diff --combined submodule.c
index d133796c9ca6ef1018b23d7b0379d7ed71e846ee,83e157d8d5af8567b93801f0503dcf609d09a1cf..50f213e926374e86c23cdbfc730f6d81af4816b8
@@@ -63,9 -63,6 +63,9 @@@ static int add_submodule_odb(const cha
        alt_odb->name[40] = '\0';
        alt_odb->name[41] = '\0';
        alt_odb_list = alt_odb;
 +
 +      /* add possible alternates from the submodule */
 +      read_info_alternates(objects_directory.buf, 0);
        prepare_alt_odb();
  done:
        strbuf_release(&objects_directory);
@@@ -574,7 -571,8 +574,7 @@@ static void calculate_changed_submodule
                        DIFF_OPT_SET(&diff_opts, RECURSIVE);
                        diff_opts.output_format |= DIFF_FORMAT_CALLBACK;
                        diff_opts.format_callback = submodule_collect_changed_cb;
 -                      if (diff_setup_done(&diff_opts) < 0)
 -                              die("diff_setup_done failed");
 +                      diff_setup_done(&diff_opts);
                        diff_tree_sha1(parent->item->object.sha1, commit->object.sha1, "", &diff_opts);
                        diffcore_std(&diff_opts);
                        diff_flush(&diff_opts);
        initialized_fetch_ref_tips = 0;
  }
  
- int fetch_populated_submodules(int num_options, const char **options,
+ int fetch_populated_submodules(const struct argv_array *options,
                               const char *prefix, int command_line_option,
                               int quiet)
  {
-       int i, result = 0, argc = 0, default_argc;
+       int i, result = 0;
        struct child_process cp;
-       const char **argv;
+       struct argv_array argv = ARGV_ARRAY_INIT;
        struct string_list_item *name_for_path;
        const char *work_tree = get_git_work_tree();
        if (!work_tree)
                if (read_cache() < 0)
                        die("index file corrupt");
  
-       /* 6: "fetch" (options) --recurse-submodules-default default "--submodule-prefix" prefix NULL */
-       argv = xcalloc(num_options + 6, sizeof(const char *));
-       argv[argc++] = "fetch";
-       for (i = 0; i < num_options; i++)
-               argv[argc++] = options[i];
-       argv[argc++] = "--recurse-submodules-default";
-       default_argc = argc++;
-       argv[argc++] = "--submodule-prefix";
+       argv_array_push(&argv, "fetch");
+       for (i = 0; i < options->argc; i++)
+               argv_array_push(&argv, options->argv[i]);
+       argv_array_push(&argv, "--recurse-submodules-default");
+       /* default value, "--submodule-prefix" and its value are added later */
  
        memset(&cp, 0, sizeof(cp));
-       cp.argv = argv;
        cp.env = local_repo_env;
        cp.git_cmd = 1;
        cp.no_stdin = 1;
                        if (!quiet)
                                printf("Fetching submodule %s%s\n", prefix, ce->name);
                        cp.dir = submodule_path.buf;
-                       argv[default_argc] = default_argv;
-                       argv[argc] = submodule_prefix.buf;
+                       argv_array_push(&argv, default_argv);
+                       argv_array_push(&argv, "--submodule-prefix");
+                       argv_array_push(&argv, submodule_prefix.buf);
+                       cp.argv = argv.argv;
                        if (run_command(&cp))
                                result = 1;
+                       argv_array_pop(&argv);
+                       argv_array_pop(&argv);
+                       argv_array_pop(&argv);
                }
                strbuf_release(&submodule_path);
                strbuf_release(&submodule_git_dir);
                strbuf_release(&submodule_prefix);
        }
-       free(argv);
+       argv_array_clear(&argv);
  out:
        string_list_clear(&changed_submodule_paths, 1);
        return result;
@@@ -788,7 -787,7 +789,7 @@@ static int find_first_merges(struct obj
                die("revision walk setup failed");
        while ((commit = get_revision(&revs)) != NULL) {
                struct object *o = &(commit->object);
 -              if (in_merge_bases(b, &commit, 1))
 +              if (in_merge_bases(b, commit))
                        add_object_array(o, NULL, &merges);
        }
        reset_revision_walk();
                contains_another = 0;
                for (j = 0; j < merges.nr; j++) {
                        struct commit *m2 = (struct commit *) merges.objects[j].item;
 -                      if (i != j && in_merge_bases(m2, &m1, 1)) {
 +                      if (i != j && in_merge_bases(m2, m1)) {
                                contains_another = 1;
                                break;
                        }
@@@ -865,18 -864,18 +866,18 @@@ int merge_submodule(unsigned char resul
        }
  
        /* check whether both changes are forward */
 -      if (!in_merge_bases(commit_base, &commit_a, 1) ||
 -          !in_merge_bases(commit_base, &commit_b, 1)) {
 +      if (!in_merge_bases(commit_base, commit_a) ||
 +          !in_merge_bases(commit_base, commit_b)) {
                MERGE_WARNING(path, "commits don't follow merge-base");
                return 0;
        }
  
        /* Case #1: a is contained in b or vice versa */
 -      if (in_merge_bases(commit_a, &commit_b, 1)) {
 +      if (in_merge_bases(commit_a, commit_b)) {
                hashcpy(result, b);
                return 1;
        }
 -      if (in_merge_bases(commit_b, &commit_a, 1)) {
 +      if (in_merge_bases(commit_b, commit_a)) {
                hashcpy(result, a);
                return 1;
        }