]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'nd/parseopt-completion'
authorJunio C Hamano <gitster@pobox.com>
Wed, 14 Mar 2018 19:01:06 +0000 (12:01 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 14 Mar 2018 19:01:07 +0000 (12:01 -0700)
Teach parse-options API an option to help the completion script,
and make use of the mechanism in command line completion.

* nd/parseopt-completion: (45 commits)
  completion: more subcommands in _git_notes()
  completion: complete --{reuse,reedit}-message= for all notes subcmds
  completion: simplify _git_notes
  completion: don't set PARSE_OPT_NOCOMPLETE on --rerere-autoupdate
  completion: use __gitcomp_builtin in _git_worktree
  completion: use __gitcomp_builtin in _git_tag
  completion: use __gitcomp_builtin in _git_status
  completion: use __gitcomp_builtin in _git_show_branch
  completion: use __gitcomp_builtin in _git_rm
  completion: use __gitcomp_builtin in _git_revert
  completion: use __gitcomp_builtin in _git_reset
  completion: use __gitcomp_builtin in _git_replace
  remote: force completing --mirror= instead of --mirror
  completion: use __gitcomp_builtin in _git_remote
  completion: use __gitcomp_builtin in _git_push
  completion: use __gitcomp_builtin in _git_pull
  completion: use __gitcomp_builtin in _git_notes
  completion: use __gitcomp_builtin in _git_name_rev
  completion: use __gitcomp_builtin in _git_mv
  completion: use __gitcomp_builtin in _git_merge_base
  ...

15 files changed:
1  2 
apply.c
builtin/checkout.c
builtin/fetch.c
builtin/gc.c
builtin/grep.c
builtin/mv.c
builtin/notes.c
builtin/pull.c
builtin/remote.c
builtin/replace.c
builtin/submodule--helper.c
builtin/tag.c
builtin/worktree.c
contrib/completion/git-completion.bash
parse-options.c

diff --cc apply.c
Simple merge
Simple merge
diff --cc builtin/fetch.c
Simple merge
diff --cc builtin/gc.c
Simple merge
diff --cc builtin/grep.c
Simple merge
diff --cc builtin/mv.c
Simple merge
diff --cc builtin/notes.c
Simple merge
diff --cc builtin/pull.c
Simple merge
Simple merge
Simple merge
index b1daca995f2f46ceb15148b609c4a89ccaa13de4,a5c4a8a6941d46c78e4dc58d0df47532f0bb2b45..ee020d4749623ba57a3a72d236504f0636ee9062
@@@ -752,309 -718,6 +752,309 @@@ static int module_name(int argc, const 
        return 0;
  }
  
-               OPT__FORCE(&force, N_("Remove submodule working trees even if they contain local changes")),
 +struct sync_cb {
 +      const char *prefix;
 +      unsigned int flags;
 +};
 +
 +#define SYNC_CB_INIT { NULL, 0 }
 +
 +static void sync_submodule(const char *path, const char *prefix,
 +                         unsigned int flags)
 +{
 +      const struct submodule *sub;
 +      char *remote_key = NULL;
 +      char *sub_origin_url, *super_config_url, *displaypath;
 +      struct strbuf sb = STRBUF_INIT;
 +      struct child_process cp = CHILD_PROCESS_INIT;
 +      char *sub_config_path = NULL;
 +
 +      if (!is_submodule_active(the_repository, path))
 +              return;
 +
 +      sub = submodule_from_path(&null_oid, path);
 +
 +      if (sub && sub->url) {
 +              if (starts_with_dot_dot_slash(sub->url) ||
 +                  starts_with_dot_slash(sub->url)) {
 +                      char *remote_url, *up_path;
 +                      char *remote = get_default_remote();
 +                      strbuf_addf(&sb, "remote.%s.url", remote);
 +
 +                      if (git_config_get_string(sb.buf, &remote_url))
 +                              remote_url = xgetcwd();
 +
 +                      up_path = get_up_path(path);
 +                      sub_origin_url = relative_url(remote_url, sub->url, up_path);
 +                      super_config_url = relative_url(remote_url, sub->url, NULL);
 +
 +                      free(remote);
 +                      free(up_path);
 +                      free(remote_url);
 +              } else {
 +                      sub_origin_url = xstrdup(sub->url);
 +                      super_config_url = xstrdup(sub->url);
 +              }
 +      } else {
 +              sub_origin_url = xstrdup("");
 +              super_config_url = xstrdup("");
 +      }
 +
 +      displaypath = get_submodule_displaypath(path, prefix);
 +
 +      if (!(flags & OPT_QUIET))
 +              printf(_("Synchronizing submodule url for '%s'\n"),
 +                       displaypath);
 +
 +      strbuf_reset(&sb);
 +      strbuf_addf(&sb, "submodule.%s.url", sub->name);
 +      if (git_config_set_gently(sb.buf, super_config_url))
 +              die(_("failed to register url for submodule path '%s'"),
 +                    displaypath);
 +
 +      if (!is_submodule_populated_gently(path, NULL))
 +              goto cleanup;
 +
 +      prepare_submodule_repo_env(&cp.env_array);
 +      cp.git_cmd = 1;
 +      cp.dir = path;
 +      argv_array_pushl(&cp.args, "submodule--helper",
 +                       "print-default-remote", NULL);
 +
 +      strbuf_reset(&sb);
 +      if (capture_command(&cp, &sb, 0))
 +              die(_("failed to get the default remote for submodule '%s'"),
 +                    path);
 +
 +      strbuf_strip_suffix(&sb, "\n");
 +      remote_key = xstrfmt("remote.%s.url", sb.buf);
 +
 +      strbuf_reset(&sb);
 +      submodule_to_gitdir(&sb, path);
 +      strbuf_addstr(&sb, "/config");
 +
 +      if (git_config_set_in_file_gently(sb.buf, remote_key, sub_origin_url))
 +              die(_("failed to update remote for submodule '%s'"),
 +                    path);
 +
 +      if (flags & OPT_RECURSIVE) {
 +              struct child_process cpr = CHILD_PROCESS_INIT;
 +
 +              cpr.git_cmd = 1;
 +              cpr.dir = path;
 +              prepare_submodule_repo_env(&cpr.env_array);
 +
 +              argv_array_push(&cpr.args, "--super-prefix");
 +              argv_array_pushf(&cpr.args, "%s/", displaypath);
 +              argv_array_pushl(&cpr.args, "submodule--helper", "sync",
 +                               "--recursive", NULL);
 +
 +              if (flags & OPT_QUIET)
 +                      argv_array_push(&cpr.args, "--quiet");
 +
 +              if (run_command(&cpr))
 +                      die(_("failed to recurse into submodule '%s'"),
 +                            path);
 +      }
 +
 +cleanup:
 +      free(super_config_url);
 +      free(sub_origin_url);
 +      strbuf_release(&sb);
 +      free(remote_key);
 +      free(displaypath);
 +      free(sub_config_path);
 +}
 +
 +static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data)
 +{
 +      struct sync_cb *info = cb_data;
 +      sync_submodule(list_item->name, info->prefix, info->flags);
 +
 +}
 +
 +static int module_sync(int argc, const char **argv, const char *prefix)
 +{
 +      struct sync_cb info = SYNC_CB_INIT;
 +      struct pathspec pathspec;
 +      struct module_list list = MODULE_LIST_INIT;
 +      int quiet = 0;
 +      int recursive = 0;
 +
 +      struct option module_sync_options[] = {
 +              OPT__QUIET(&quiet, N_("Suppress output of synchronizing submodule url")),
 +              OPT_BOOL(0, "recursive", &recursive,
 +                      N_("Recurse into nested submodules")),
 +              OPT_END()
 +      };
 +
 +      const char *const git_submodule_helper_usage[] = {
 +              N_("git submodule--helper sync [--quiet] [--recursive] [<path>]"),
 +              NULL
 +      };
 +
 +      argc = parse_options(argc, argv, prefix, module_sync_options,
 +                           git_submodule_helper_usage, 0);
 +
 +      if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
 +              return 1;
 +
 +      info.prefix = prefix;
 +      if (quiet)
 +              info.flags |= OPT_QUIET;
 +      if (recursive)
 +              info.flags |= OPT_RECURSIVE;
 +
 +      for_each_listed_submodule(&list, sync_submodule_cb, &info);
 +
 +      return 0;
 +}
 +
 +struct deinit_cb {
 +      const char *prefix;
 +      unsigned int flags;
 +};
 +#define DEINIT_CB_INIT { NULL, 0 }
 +
 +static void deinit_submodule(const char *path, const char *prefix,
 +                           unsigned int flags)
 +{
 +      const struct submodule *sub;
 +      char *displaypath = NULL;
 +      struct child_process cp_config = CHILD_PROCESS_INIT;
 +      struct strbuf sb_config = STRBUF_INIT;
 +      char *sub_git_dir = xstrfmt("%s/.git", path);
 +
 +      sub = submodule_from_path(&null_oid, path);
 +
 +      if (!sub || !sub->name)
 +              goto cleanup;
 +
 +      displaypath = get_submodule_displaypath(path, prefix);
 +
 +      /* remove the submodule work tree (unless the user already did it) */
 +      if (is_directory(path)) {
 +              struct strbuf sb_rm = STRBUF_INIT;
 +              const char *format;
 +
 +              /*
 +               * protect submodules containing a .git directory
 +               * NEEDSWORK: instead of dying, automatically call
 +               * absorbgitdirs and (possibly) warn.
 +               */
 +              if (is_directory(sub_git_dir))
 +                      die(_("Submodule work tree '%s' contains a .git "
 +                            "directory (use 'rm -rf' if you really want "
 +                            "to remove it including all of its history)"),
 +                          displaypath);
 +
 +              if (!(flags & OPT_FORCE)) {
 +                      struct child_process cp_rm = CHILD_PROCESS_INIT;
 +                      cp_rm.git_cmd = 1;
 +                      argv_array_pushl(&cp_rm.args, "rm", "-qn",
 +                                       path, NULL);
 +
 +                      if (run_command(&cp_rm))
 +                              die(_("Submodule work tree '%s' contains local "
 +                                    "modifications; use '-f' to discard them"),
 +                                    displaypath);
 +              }
 +
 +              strbuf_addstr(&sb_rm, path);
 +
 +              if (!remove_dir_recursively(&sb_rm, 0))
 +                      format = _("Cleared directory '%s'\n");
 +              else
 +                      format = _("Could not remove submodule work tree '%s'\n");
 +
 +              if (!(flags & OPT_QUIET))
 +                      printf(format, displaypath);
 +
 +              strbuf_release(&sb_rm);
 +      }
 +
 +      if (mkdir(path, 0777))
 +              printf(_("could not create empty submodule directory %s"),
 +                    displaypath);
 +
 +      cp_config.git_cmd = 1;
 +      argv_array_pushl(&cp_config.args, "config", "--get-regexp", NULL);
 +      argv_array_pushf(&cp_config.args, "submodule.%s\\.", sub->name);
 +
 +      /* remove the .git/config entries (unless the user already did it) */
 +      if (!capture_command(&cp_config, &sb_config, 0) && sb_config.len) {
 +              char *sub_key = xstrfmt("submodule.%s", sub->name);
 +              /*
 +               * remove the whole section so we have a clean state when
 +               * the user later decides to init this submodule again
 +               */
 +              git_config_rename_section_in_file(NULL, sub_key, NULL);
 +              if (!(flags & OPT_QUIET))
 +                      printf(_("Submodule '%s' (%s) unregistered for path '%s'\n"),
 +                               sub->name, sub->url, displaypath);
 +              free(sub_key);
 +      }
 +
 +cleanup:
 +      free(displaypath);
 +      free(sub_git_dir);
 +      strbuf_release(&sb_config);
 +}
 +
 +static void deinit_submodule_cb(const struct cache_entry *list_item,
 +                              void *cb_data)
 +{
 +      struct deinit_cb *info = cb_data;
 +      deinit_submodule(list_item->name, info->prefix, info->flags);
 +}
 +
 +static int module_deinit(int argc, const char **argv, const char *prefix)
 +{
 +      struct deinit_cb info = DEINIT_CB_INIT;
 +      struct pathspec pathspec;
 +      struct module_list list = MODULE_LIST_INIT;
 +      int quiet = 0;
 +      int force = 0;
 +      int all = 0;
 +
 +      struct option module_deinit_options[] = {
 +              OPT__QUIET(&quiet, N_("Suppress submodule status output")),
++              OPT__FORCE(&force, N_("Remove submodule working trees even if they contain local changes"), 0),
 +              OPT_BOOL(0, "all", &all, N_("Unregister all submodules")),
 +              OPT_END()
 +      };
 +
 +      const char *const git_submodule_helper_usage[] = {
 +              N_("git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"),
 +              NULL
 +      };
 +
 +      argc = parse_options(argc, argv, prefix, module_deinit_options,
 +                           git_submodule_helper_usage, 0);
 +
 +      if (all && argc) {
 +              error("pathspec and --all are incompatible");
 +              usage_with_options(git_submodule_helper_usage,
 +                                 module_deinit_options);
 +      }
 +
 +      if (!argc && !all)
 +              die(_("Use '--all' if you really want to deinitialize all submodules"));
 +
 +      if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
 +              BUG("module_list_compute should not choke on empty pathspec");
 +
 +      info.prefix = prefix;
 +      if (quiet)
 +              info.flags |= OPT_QUIET;
 +      if (force)
 +              info.flags |= OPT_FORCE;
 +
 +      for_each_listed_submodule(&list, deinit_submodule_cb, &info);
 +
 +      return 0;
 +}
 +
  static int clone_submodule(const char *path, const char *gitdir, const char *url,
                           const char *depth, struct string_list *reference,
                           int quiet, int progress)
diff --cc builtin/tag.c
Simple merge
Simple merge
index 66010707df2c15d9f79b797bafd62e48cc8a923e,2e30950299fd74a8f11b0cea86d6d8ffb6ca3226..f1981aa75df2128f93a3d6b5b3434ab6bda86576
@@@ -1072,6 -1105,7 +1105,7 @@@ __git_count_arguments (
  }
  
  __git_whitespacelist="nowarn warn error error-all fix"
 -__git_am_inprogress_options="--skip --continue --resolved --abort"
++__git_am_inprogress_options="--skip --continue --resolved --abort --quit --show-current-patch"
  
  _git_am ()
  {
@@@ -3094,20 -3012,17 +3012,20 @@@ _git_worktree (
        else
                case "$subcommand,$cur" in
                add,--*)
-                       __gitcomp "--detach"
+                       __gitcomp_builtin worktree_add
                        ;;
                list,--*)
-                       __gitcomp "--porcelain"
+                       __gitcomp_builtin worktree_list
                        ;;
                lock,--*)
-                       __gitcomp "--reason"
+                       __gitcomp_builtin worktree_lock
                        ;;
                prune,--*)
-                       __gitcomp "--dry-run --expire --verbose"
+                       __gitcomp_builtin worktree_prune
                        ;;
 +              remove,--*)
 +                      __gitcomp "--force"
 +                      ;;
                *)
                        ;;
                esac
diff --cc parse-options.c
Simple merge