]> 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
  ...

25 files changed:
apply.c
builtin/add.c
builtin/branch.c
builtin/checkout-index.c
builtin/checkout.c
builtin/clean.c
builtin/fetch.c
builtin/gc.c
builtin/grep.c
builtin/ls-remote.c
builtin/mv.c
builtin/notes.c
builtin/pull.c
builtin/push.c
builtin/remote.c
builtin/replace.c
builtin/rm.c
builtin/submodule--helper.c
builtin/tag.c
builtin/update-server-info.c
builtin/worktree.c
contrib/completion/git-completion.bash
parse-options.c
parse-options.h
t/t9902-completion.sh

diff --git a/apply.c b/apply.c
index f8f15edc7c7b2b409201b6168a68fdd96ed0c0ba..134dc7ba78cddd99406b78a97898bd8a32393b4c 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -4943,8 +4943,9 @@ int apply_parse_options(int argc, const char **argv,
                        N_("make sure the patch is applicable to the current index")),
                OPT_BOOL(0, "cached", &state->cached,
                        N_("apply a patch without touching the working tree")),
-               OPT_BOOL(0, "unsafe-paths", &state->unsafe_paths,
-                       N_("accept a patch that touches outside the working area")),
+               OPT_BOOL_F(0, "unsafe-paths", &state->unsafe_paths,
+                          N_("accept a patch that touches outside the working area"),
+                          PARSE_OPT_NOCOMPLETE),
                OPT_BOOL(0, "apply", force_apply,
                        N_("also apply the patch (use with --stat/--summary/--check)")),
                OPT_BOOL('3', "3way", &state->threeway,
index bf01d89e28eaef0f8113d42c6b9d4142b8e912e4..ac7c1c327766c6a729ab0377fd71c2f8e9042d00 100644 (file)
@@ -294,7 +294,7 @@ static struct option builtin_add_options[] = {
        OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
        OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
        OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
-       OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")),
+       OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
        OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
        OPT_BOOL(0, "renormalize", &add_renormalize, N_("renormalize EOL of tracked files (implies -u)")),
        OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
index 8dcc2ed058be6e653f885e48c9aa5f465a5f9749..6d0cea9d4bcc4eb866280d6424a6dec32b5f9c87 100644 (file)
@@ -615,7 +615,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                OPT_BOOL('l', "create-reflog", &reflog, N_("create the branch's reflog")),
                OPT_BOOL(0, "edit-description", &edit_description,
                         N_("edit the description for the branch")),
-               OPT__FORCE(&force, N_("force creation, move/rename, deletion")),
+               OPT__FORCE(&force, N_("force creation, move/rename, deletion"), PARSE_OPT_NOCOMPLETE),
                OPT_MERGED(&filter, N_("print only branches that are merged")),
                OPT_NO_MERGED(&filter, N_("print only branches that are not merged")),
                OPT_COLUMN(0, "column", &colopts, N_("list branches in columns")),
index b0e78b819db3138f1c5ac4fe4b5d850ab306b470..a730f6a1aa47a60d4c131ee47076411a129d8080 100644 (file)
@@ -157,7 +157,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
        struct option builtin_checkout_index_options[] = {
                OPT_BOOL('a', "all", &all,
                        N_("check out all files in the index")),
-               OPT__FORCE(&force, N_("force overwrite of existing files")),
+               OPT__FORCE(&force, N_("force overwrite of existing files"), 0),
                OPT__QUIET(&quiet,
                        N_("no warning for existing files and files not in index")),
                OPT_BOOL('n', "no-create", &not_new,
index 8f4dfb104662baa3f32c350cf58e0f2b797dff29..d76e13c8524003fcc5c55d706c1177f66520b9d4 100644 (file)
@@ -1117,9 +1117,12 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                            2),
                OPT_SET_INT('3', "theirs", &opts.writeout_stage, N_("checkout their version for unmerged files"),
                            3),
-               OPT__FORCE(&opts.force, N_("force checkout (throw away local modifications)")),
+               OPT__FORCE(&opts.force, N_("force checkout (throw away local modifications)"),
+                          PARSE_OPT_NOCOMPLETE),
                OPT_BOOL('m', "merge", &opts.merge, N_("perform a 3-way merge with the new branch")),
-               OPT_BOOL(0, "overwrite-ignore", &opts.overwrite_ignore, N_("update ignored files (default)")),
+               OPT_BOOL_F(0, "overwrite-ignore", &opts.overwrite_ignore,
+                          N_("update ignored files (default)"),
+                          PARSE_OPT_NOCOMPLETE),
                OPT_STRING(0, "conflict", &conflict_style, N_("style"),
                           N_("conflict style (merge or diff3)")),
                OPT_BOOL('p', "patch", &opts.patch_mode, N_("select hunks interactively")),
index 189e20628c07774089c5c925380b6b69af16fc7f..fad533a0a7382f10ecf48a738c955734ad5c0d96 100644 (file)
@@ -909,7 +909,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
        struct option options[] = {
                OPT__QUIET(&quiet, N_("do not print names of files removed")),
                OPT__DRY_RUN(&dry_run, N_("dry run")),
-               OPT__FORCE(&force, N_("force")),
+               OPT__FORCE(&force, N_("force"), PARSE_OPT_NOCOMPLETE),
                OPT_BOOL('i', "interactive", &interactive, N_("interactive cleaning")),
                OPT_BOOL('d', NULL, &remove_directories,
                                N_("remove whole directories")),
index d32d94692c7eae8372c4a8abac45f172e6693247..6d73656a486fed1afd031e6cf5e26e1c2039e0cb 100644 (file)
@@ -126,7 +126,7 @@ static struct option builtin_fetch_options[] = {
                 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__FORCE(&force, N_("force overwrite of local branch"), 0),
        OPT_BOOL('m', "multiple", &multiple,
                 N_("fetch from multiple remotes")),
        OPT_SET_INT('t', "tags", &tags,
index 77fa720bd0bf374db8a24338bde8686ee0d60377..f51e5a6500fc294cb719716671259de42f31bfe7 100644 (file)
@@ -360,8 +360,11 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
                        N_("prune unreferenced objects"),
                        PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire },
                OPT_BOOL(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")),
-               OPT_BOOL(0, "auto", &auto_gc, N_("enable auto-gc mode")),
-               OPT_BOOL(0, "force", &force, N_("force running gc even if there may be another gc running")),
+               OPT_BOOL_F(0, "auto", &auto_gc, N_("enable auto-gc mode"),
+                          PARSE_OPT_NOCOMPLETE),
+               OPT_BOOL_F(0, "force", &force,
+                          N_("force running gc even if there may be another gc running"),
+                          PARSE_OPT_NOCOMPLETE),
                OPT_END()
        };
 
index 9a0973e8f158c881059914614f006645646a2545..789a89133aca7b8eeb93a936fd2301bd3f37d0c7 100644 (file)
@@ -839,8 +839,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                OPT_BOOL('L', "files-without-match",
                        &opt.unmatch_name_only,
                        N_("show only the names of files without match")),
-               OPT_BOOL('z', "null", &opt.null_following_name,
-                       N_("print NUL after filenames")),
+               OPT_BOOL_F('z', "null", &opt.null_following_name,
+                          N_("print NUL after filenames"),
+                          PARSE_OPT_NOCOMPLETE),
                OPT_BOOL('c', "count", &opt.count,
                        N_("show the number of matches instead of matching lines")),
                OPT__COLOR(&opt.color, N_("highlight matches")),
@@ -891,9 +892,11 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                OPT_GROUP(""),
                { OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager,
                        N_("pager"), N_("show matching files in the pager"),
-                       PARSE_OPT_OPTARG, NULL, (intptr_t)default_pager },
-               OPT_BOOL(0, "ext-grep", &external_grep_allowed__ignored,
-                        N_("allow calling of grep(1) (ignored by this build)")),
+                       PARSE_OPT_OPTARG | PARSE_OPT_NOCOMPLETE,
+                       NULL, (intptr_t)default_pager },
+               OPT_BOOL_F(0, "ext-grep", &external_grep_allowed__ignored,
+                          N_("allow calling of grep(1) (ignored by this build)"),
+                          PARSE_OPT_NOCOMPLETE),
                OPT_END()
        };
 
index c4be98ab9e84fdcde2842b88d4bb60600f7bf627..540d56429f5cec4ace8655dd9a870089fc872d2c 100644 (file)
@@ -60,8 +60,9 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
                OPT_BIT(0, "refs", &flags, N_("do not show peeled tags"), REF_NORMAL),
                OPT_BOOL(0, "get-url", &get_url,
                         N_("take url.<base>.insteadOf into account")),
-               OPT_SET_INT(0, "exit-code", &status,
-                           N_("exit with exit code 2 if no matching refs are found"), 2),
+               OPT_SET_INT_F(0, "exit-code", &status,
+                             N_("exit with exit code 2 if no matching refs are found"),
+                             2, PARSE_OPT_NOCOMPLETE),
                OPT_BOOL(0, "symref", &show_symref_target,
                         N_("show underlying ref in addition to the object pointed by it")),
                OPT_END()
index 8ce6a2ddd4c5008c9d32d45dc21e11d97ff8b79d..8eceb310aae5f8007475f571a0146832eab0be49 100644 (file)
@@ -122,7 +122,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
        struct option builtin_mv_options[] = {
                OPT__VERBOSE(&verbose, N_("be verbose")),
                OPT__DRY_RUN(&show_only, N_("dry run")),
-               OPT__FORCE(&force, N_("force move/rename even if target exists")),
+               OPT__FORCE(&force, N_("force move/rename even if target exists"),
+                          PARSE_OPT_NOCOMPLETE),
                OPT_BOOL('k', NULL, &ignore_errors, N_("skip move/rename errors")),
                OPT_END(),
        };
index 39304ba743b34ad9ff73583f691c6f8d79379eb5..6d2fda4a7d7ba89633f5cfee73f39cacb9f27898 100644 (file)
@@ -413,7 +413,7 @@ static int add(int argc, const char **argv, const char *prefix)
                        parse_reuse_arg},
                OPT_BOOL(0, "allow-empty", &allow_empty,
                        N_("allow storing empty note")),
-               OPT__FORCE(&force, N_("replace existing notes")),
+               OPT__FORCE(&force, N_("replace existing notes"), PARSE_OPT_NOCOMPLETE),
                OPT_END()
        };
 
@@ -484,7 +484,7 @@ static int copy(int argc, const char **argv, const char *prefix)
        struct notes_tree *t;
        const char *rewrite_cmd = NULL;
        struct option options[] = {
-               OPT__FORCE(&force, N_("replace existing notes")),
+               OPT__FORCE(&force, N_("replace existing notes"), PARSE_OPT_NOCOMPLETE),
                OPT_BOOL(0, "stdin", &from_stdin, N_("read objects from stdin")),
                OPT_STRING(0, "for-rewrite", &rewrite_cmd, N_("command"),
                           N_("load rewriting config for <command> (implies "
index 1876271af9423dc58bb66d00bdd1eaa62a983dab..e32d6cd5b4c999bc45b961c1387af066c72a823a 100644 (file)
@@ -193,7 +193,7 @@ static struct option pull_options[] = {
        OPT_PASSTHRU(0, "upload-pack", &opt_upload_pack, N_("path"),
                N_("path to upload pack on remote end"),
                0),
-       OPT__FORCE(&opt_force, N_("force overwrite of local branch")),
+       OPT__FORCE(&opt_force, N_("force overwrite of local branch"), 0),
        OPT_PASSTHRU('t', "tags", &opt_tags, NULL,
                N_("fetch all tags and associated objects"),
                PARSE_OPT_NOARG),
index 1c28427d82ee73631fb02b5f126c40ebd2cb1774..013c20d6164f61dc404b89271c0281d28b5069a7 100644 (file)
@@ -548,7 +548,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
                { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, "check|on-demand|no",
                        N_("control recursive pushing of submodules"),
                        PARSE_OPT_OPTARG, option_parse_recurse_submodules },
-               OPT_BOOL( 0 , "thin", &thin, N_("use thin pack")),
+               OPT_BOOL_F( 0 , "thin", &thin, N_("use thin pack"), PARSE_OPT_NOCOMPLETE),
                OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", N_("receive pack program")),
                OPT_STRING( 0 , "exec", &receivepack, "receive-pack", N_("receive pack program")),
                OPT_BIT('u', "set-upstream", &flags, N_("set upstream for git pull/status"),
index 6487d92abdc8a9d86749e9e00af9f919d4b89486..805ffc05cdb80e4a69de4134e757f9c71e8033dc 100644 (file)
@@ -168,7 +168,7 @@ static int add(int argc, const char **argv)
                OPT_STRING('m', "master", &master, N_("branch"), N_("master branch")),
                { OPTION_CALLBACK, 0, "mirror", &mirror, N_("push|fetch"),
                        N_("set up remote as a mirror to push to or fetch from"),
-                       PARSE_OPT_OPTARG, parse_mirror_opt },
+                       PARSE_OPT_OPTARG | PARSE_OPT_COMP_ARG, parse_mirror_opt },
                OPT_END()
        };
 
index 9f01f3fc7f86ef6e13933524441f330d3dae1573..482f12018fa912eeea860721af2acbf5f8a2e87d 100644 (file)
@@ -439,7 +439,8 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
                OPT_CMDMODE('d', "delete", &cmdmode, N_("delete replace refs"), MODE_DELETE),
                OPT_CMDMODE('e', "edit", &cmdmode, N_("edit existing object"), MODE_EDIT),
                OPT_CMDMODE('g', "graft", &cmdmode, N_("change a commit's parents"), MODE_GRAFT),
-               OPT_BOOL('f', "force", &force, N_("replace the ref if it exists")),
+               OPT_BOOL_F('f', "force", &force, N_("replace the ref if it exists"),
+                          PARSE_OPT_NOCOMPLETE),
                OPT_BOOL(0, "raw", &raw, N_("do not pretty-print contents for --edit")),
                OPT_STRING(0, "format", &format, N_("format"), N_("use this format")),
                OPT_END()
index 4a2fcca27b3f722ca520c2411b80e6984ecf780a..a818efe230a0667b9e3e5f03efbb11b1db1df273 100644 (file)
@@ -242,7 +242,7 @@ static struct option builtin_rm_options[] = {
        OPT__DRY_RUN(&show_only, N_("dry run")),
        OPT__QUIET(&quiet, N_("do not list removed files")),
        OPT_BOOL( 0 , "cached",         &index_only, N_("only remove from the index")),
-       OPT__FORCE(&force, N_("override the up-to-date check")),
+       OPT__FORCE(&force, N_("override the up-to-date check"), PARSE_OPT_NOCOMPLETE),
        OPT_BOOL('r', NULL,             &recursive,  N_("allow recursive removal")),
        OPT_BOOL( 0 , "ignore-unmatch", &ignore_unmatch,
                                N_("exit with a zero status even if nothing matched")),
index b1daca995f2f46ceb15148b609c4a89ccaa13de4..ee020d4749623ba57a3a72d236504f0636ee9062 100644 (file)
@@ -1019,7 +1019,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
 
        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")),
+               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()
        };
index 8c493a569f75825133f611abc17ed267d2b1e08c..da186691ed8853bc5848c4106c752b015756eda3 100644 (file)
@@ -397,7 +397,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
                        N_("how to strip spaces and #comments from message")),
                OPT_STRING('u', "local-user", &keyid, N_("key-id"),
                                        N_("use another key to sign the tag")),
-               OPT__FORCE(&force, N_("replace the tag if exists")),
+               OPT__FORCE(&force, N_("replace the tag if exists"), 0),
                OPT_BOOL(0, "create-reflog", &create_reflog, N_("create a reflog")),
 
                OPT_GROUP(N_("Tag listing options")),
index 873070e517090cbb21bf53cbc03088da6f85ec1f..4321a344567ed83e6828be41eb150d90c4d7756a 100644 (file)
@@ -12,7 +12,7 @@ int cmd_update_server_info(int argc, const char **argv, const char *prefix)
 {
        int force = 0;
        struct option options[] = {
-               OPT__FORCE(&force, N_("update the info files from scratch")),
+               OPT__FORCE(&force, N_("update the info files from scratch"), 0),
                OPT_END()
        };
 
index 1c1e576fdb01ef1adc4207799d2d7ac97932a8cf..670555deddaca8ff8050c03ea68c83c7b4e459e6 100644 (file)
@@ -381,7 +381,9 @@ static int add(int ac, const char **av, const char *prefix)
        const char *branch;
        const char *opt_track = NULL;
        struct option options[] = {
-               OPT__FORCE(&opts.force, N_("checkout <branch> even if already checked out in other worktree")),
+               OPT__FORCE(&opts.force,
+                          N_("checkout <branch> even if already checked out in other worktree"),
+                          PARSE_OPT_NOCOMPLETE),
                OPT_STRING('b', NULL, &opts.new_branch, N_("branch"),
                           N_("create a new branch")),
                OPT_STRING('B', NULL, &new_branch_force, N_("branch"),
index 66010707df2c15d9f79b797bafd62e48cc8a923e..f1981aa75df2128f93a3d6b5b3434ab6bda86576 100644 (file)
@@ -280,6 +280,39 @@ __gitcomp ()
        esac
 }
 
+# This function is equivalent to
+#
+#    __gitcomp "$(git xxx --git-completion-helper) ..."
+#
+# except that the output is cached. Accept 1-3 arguments:
+# 1: the git command to execute, this is also the cache key
+# 2: extra options to be added on top (e.g. negative forms)
+# 3: options to be excluded
+__gitcomp_builtin ()
+{
+       # spaces must be replaced with underscore for multi-word
+       # commands, e.g. "git remote add" becomes remote_add.
+       local cmd="$1"
+       local incl="$2"
+       local excl="$3"
+
+       local var=__gitcomp_builtin_"${cmd/-/_}"
+       local options
+       eval "options=\$$var"
+
+       if [ -z "$options" ]; then
+               # leading and trailing spaces are significant to make
+               # option removal work correctly.
+               options=" $(__git ${cmd/_/ } --git-completion-helper) $incl "
+               for i in $excl; do
+                       options="${options/ $i / }"
+               done
+               eval "$var=\"$options\""
+       fi
+
+       __gitcomp "$options"
+}
+
 # Variation of __gitcomp_nl () that appends to the existing list of
 # completion candidates, COMPREPLY.
 __gitcomp_nl_append ()
@@ -1072,12 +1105,13 @@ __git_count_arguments ()
 }
 
 __git_whitespacelist="nowarn warn error error-all fix"
+__git_am_inprogress_options="--skip --continue --resolved --abort --quit --show-current-patch"
 
 _git_am ()
 {
        __git_find_repo_path
        if [ -d "$__git_repo_path"/rebase-apply ]; then
-               __gitcomp "--skip --continue --resolved --abort --quit --show-current-patch"
+               __gitcomp "$__git_am_inprogress_options"
                return
        fi
        case "$cur" in
@@ -1086,12 +1120,8 @@ _git_am ()
                return
                ;;
        --*)
-               __gitcomp "
-                       --3way --committer-date-is-author-date --ignore-date
-                       --ignore-whitespace --ignore-space-change
-                       --interactive --keep --no-utf8 --signoff --utf8
-                       --whitespace= --scissors
-                       "
+               __gitcomp_builtin am "--no-utf8" \
+                       "$__git_am_inprogress_options"
                return
        esac
 }
@@ -1104,14 +1134,7 @@ _git_apply ()
                return
                ;;
        --*)
-               __gitcomp "
-                       --stat --numstat --summary --check --index
-                       --cached --index-info --reverse --reject --unidiff-zero
-                       --apply --no-add --exclude=
-                       --ignore-whitespace --ignore-space-change
-                       --whitespace= --inaccurate-eof --verbose
-                       --recount --directory=
-                       "
+               __gitcomp_builtin apply
                return
        esac
 }
@@ -1120,10 +1143,7 @@ _git_add ()
 {
        case "$cur" in
        --*)
-               __gitcomp "
-                       --interactive --refresh --patch --update --dry-run
-                       --ignore-errors --intent-to-add --force --edit --chmod=
-                       "
+               __gitcomp_builtin add
                return
        esac
 
@@ -1200,12 +1220,8 @@ _git_branch ()
                __git_complete_refs --cur="${cur##--set-upstream-to=}"
                ;;
        --*)
-               __gitcomp "
-                       --color --no-color --verbose --abbrev= --no-abbrev
-                       --track --no-track --contains --no-contains --merged --no-merged
-                       --set-upstream-to= --edit-description --list
-                       --unset-upstream --delete --move --copy --remotes
-                       --column --no-column --sort= --points-at
+               __gitcomp_builtin branch "--no-color --no-abbrev
+                       --no-track --no-column
                        "
                ;;
        *)
@@ -1247,11 +1263,7 @@ _git_checkout ()
                __gitcomp "diff3 merge" "" "${cur##--conflict=}"
                ;;
        --*)
-               __gitcomp "
-                       --quiet --ours --theirs --track --no-track --merge
-                       --conflict= --orphan --patch --detach --ignore-skip-worktree-bits
-                       --recurse-submodules --no-recurse-submodules
-                       "
+               __gitcomp_builtin checkout "--no-track --no-recurse-submodules"
                ;;
        *)
                # check if --track, --no-track, or --no-guess was specified
@@ -1271,16 +1283,19 @@ _git_cherry ()
        __git_complete_refs
 }
 
+__git_cherry_pick_inprogress_options="--continue --quit --abort"
+
 _git_cherry_pick ()
 {
        __git_find_repo_path
        if [ -f "$__git_repo_path"/CHERRY_PICK_HEAD ]; then
-               __gitcomp "--continue --quit --abort"
+               __gitcomp "$__git_cherry_pick_inprogress_options"
                return
        fi
        case "$cur" in
        --*)
-               __gitcomp "--edit --no-commit --signoff --strategy= --mainline"
+               __gitcomp_builtin cherry-pick "" \
+                       "$__git_cherry_pick_inprogress_options"
                ;;
        *)
                __git_complete_refs
@@ -1292,7 +1307,7 @@ _git_clean ()
 {
        case "$cur" in
        --*)
-               __gitcomp "--dry-run --quiet"
+               __gitcomp_builtin clean
                return
                ;;
        esac
@@ -1305,26 +1320,7 @@ _git_clone ()
 {
        case "$cur" in
        --*)
-               __gitcomp "
-                       --local
-                       --no-hardlinks
-                       --shared
-                       --reference
-                       --quiet
-                       --no-checkout
-                       --bare
-                       --mirror
-                       --origin
-                       --upload-pack
-                       --template=
-                       --depth
-                       --single-branch
-                       --no-tags
-                       --branch
-                       --recurse-submodules
-                       --no-single-branch
-                       --shallow-submodules
-                       "
+               __gitcomp_builtin clone "--no-single-branch"
                return
                ;;
        esac
@@ -1357,16 +1353,7 @@ _git_commit ()
                return
                ;;
        --*)
-               __gitcomp "
-                       --all --author= --signoff --verify --no-verify
-                       --edit --no-edit
-                       --amend --include --only --interactive
-                       --dry-run --reuse-message= --reedit-message=
-                       --reset-author --file= --message= --template=
-                       --cleanup= --untracked-files --untracked-files=
-                       --verbose --quiet --fixup= --squash=
-                       --patch --short --date --allow-empty
-                       "
+               __gitcomp_builtin commit "--no-edit --verify"
                return
        esac
 
@@ -1382,11 +1369,7 @@ _git_describe ()
 {
        case "$cur" in
        --*)
-               __gitcomp "
-                       --all --tags --contains --abbrev= --candidates=
-                       --exact-match --debug --long --match --always --first-parent
-                       --exclude --dirty --broken
-                       "
+               __gitcomp_builtin describe
                return
        esac
        __git_complete_refs
@@ -1411,7 +1394,7 @@ __git_diff_common_options="--stat --numstat --shortstat --summary
                        --dirstat --dirstat= --dirstat-by-file
                        --dirstat-by-file= --cumulative
                        --diff-algorithm=
-                       --submodule --submodule=
+                       --submodule --submodule= --ignore-submodules
 "
 
 _git_diff ()
@@ -1452,11 +1435,11 @@ _git_difftool ()
                return
                ;;
        --*)
-               __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
-                       --base --ours --theirs
-                       --no-renames --diff-filter= --find-copies-harder
-                       --relative --ignore-submodules
-                       --tool="
+               __gitcomp_builtin difftool "$__git_diff_common_options
+                                       --base --cached --ours --theirs
+                                       --pickaxe-all --pickaxe-regex
+                                       --relative --staged
+                                       "
                return
                ;;
        esac
@@ -1465,12 +1448,6 @@ _git_difftool ()
 
 __git_fetch_recurse_submodules="yes on-demand no"
 
-__git_fetch_options="
-       --quiet --verbose --append --upload-pack --force --keep --depth=
-       --tags --no-tags --all --prune --dry-run --recurse-submodules=
-       --unshallow --update-shallow --prune-tags
-"
-
 _git_fetch ()
 {
        case "$cur" in
@@ -1479,7 +1456,7 @@ _git_fetch ()
                return
                ;;
        --*)
-               __gitcomp "$__git_fetch_options"
+               __gitcomp_builtin fetch "--no-tags"
                return
                ;;
        esac
@@ -1516,10 +1493,7 @@ _git_fsck ()
 {
        case "$cur" in
        --*)
-               __gitcomp "
-                       --tags --root --unreachable --cache --no-reflogs --full
-                       --strict --verbose --lost-found --name-objects
-                       "
+               __gitcomp_builtin fsck "--no-reflogs"
                return
                ;;
        esac
@@ -1529,7 +1503,7 @@ _git_gc ()
 {
        case "$cur" in
        --*)
-               __gitcomp "--prune --aggressive"
+               __gitcomp_builtin gc
                return
                ;;
        esac
@@ -1585,21 +1559,7 @@ _git_grep ()
 
        case "$cur" in
        --*)
-               __gitcomp "
-                       --cached
-                       --text --ignore-case --word-regexp --invert-match
-                       --full-name --line-number
-                       --extended-regexp --basic-regexp --fixed-strings
-                       --perl-regexp
-                       --threads
-                       --files-with-matches --name-only
-                       --files-without-match
-                       --max-depth
-                       --count
-                       --and --or --not --all-match
-                       --break --heading --show-function --function-context
-                       --untracked --no-index
-                       "
+               __gitcomp_builtin grep
                return
                ;;
        esac
@@ -1617,7 +1577,7 @@ _git_help ()
 {
        case "$cur" in
        --*)
-               __gitcomp "--all --guides --info --man --web"
+               __gitcomp_builtin help
                return
                ;;
        esac
@@ -1640,7 +1600,7 @@ _git_init ()
                return
                ;;
        --*)
-               __gitcomp "--quiet --bare --template= --shared --shared="
+               __gitcomp_builtin init
                return
                ;;
        esac
@@ -1650,13 +1610,7 @@ _git_ls_files ()
 {
        case "$cur" in
        --*)
-               __gitcomp "--cached --deleted --modified --others --ignored
-                       --stage --directory --no-empty-directory --unmerged
-                       --killed --exclude= --exclude-from=
-                       --exclude-per-directory= --exclude-standard
-                       --error-unmatch --with-tree= --full-name
-                       --abbrev --ignored --exclude-per-directory
-                       "
+               __gitcomp_builtin ls-files "--no-empty-directory"
                return
                ;;
        esac
@@ -1670,7 +1624,7 @@ _git_ls_remote ()
 {
        case "$cur" in
        --*)
-               __gitcomp "--heads --tags --refs --get-url --symref"
+               __gitcomp_builtin ls-remote
                return
                ;;
        esac
@@ -1794,22 +1748,18 @@ _git_log ()
        __git_complete_revlist
 }
 
-# Common merge options shared by git-merge(1) and git-pull(1).
-__git_merge_options="
-       --no-commit --no-stat --log --no-log --squash --strategy
-       --commit --stat --no-squash --ff --no-ff --ff-only --edit --no-edit
-       --verify-signatures --no-verify-signatures --gpg-sign
-       --quiet --verbose --progress --no-progress
-"
-
 _git_merge ()
 {
        __git_complete_strategy && return
 
        case "$cur" in
        --*)
-               __gitcomp "$__git_merge_options
-                       --rerere-autoupdate --no-rerere-autoupdate --abort --continue"
+               __gitcomp_builtin merge "--no-rerere-autoupdate
+                               --no-commit --no-edit --no-ff
+                               --no-log --no-progress
+                               --no-squash --no-stat
+                               --no-verify-signatures
+                               "
                return
        esac
        __git_complete_refs
@@ -1833,7 +1783,7 @@ _git_merge_base ()
 {
        case "$cur" in
        --*)
-               __gitcomp "--octopus --independent --is-ancestor --fork-point"
+               __gitcomp_builtin merge-base
                return
                ;;
        esac
@@ -1844,7 +1794,7 @@ _git_mv ()
 {
        case "$cur" in
        --*)
-               __gitcomp "--dry-run"
+               __gitcomp_builtin mv
                return
                ;;
        esac
@@ -1860,17 +1810,17 @@ _git_mv ()
 
 _git_name_rev ()
 {
-       __gitcomp "--tags --all --stdin"
+       __gitcomp_builtin name-rev
 }
 
 _git_notes ()
 {
-       local subcommands='add append copy edit list prune remove show'
+       local subcommands='add append copy edit get-ref list merge prune remove show'
        local subcommand="$(__git_find_on_cmdline "$subcommands")"
 
        case "$subcommand,$cur" in
        ,--*)
-               __gitcomp '--ref'
+               __gitcomp_builtin notes
                ;;
        ,*)
                case "$prev" in
@@ -1882,21 +1832,14 @@ _git_notes ()
                        ;;
                esac
                ;;
-       add,--reuse-message=*|append,--reuse-message=*|\
-       add,--reedit-message=*|append,--reedit-message=*)
+       *,--reuse-message=*|*,--reedit-message=*)
                __git_complete_refs --cur="${cur#*=}"
                ;;
-       add,--*|append,--*)
-               __gitcomp '--file= --message= --reedit-message=
-                               --reuse-message='
+       *,--*)
+               __gitcomp_builtin notes_$subcommand
                ;;
-       copy,--*)
-               __gitcomp '--stdin'
-               ;;
-       prune,--*)
-               __gitcomp '--dry-run --verbose'
-               ;;
-       prune,*)
+       prune,*|get-ref,*)
+               # this command does not take a ref, do not complete it
                ;;
        *)
                case "$prev" in
@@ -1920,12 +1863,11 @@ _git_pull ()
                return
                ;;
        --*)
-               __gitcomp "
-                       --rebase --no-rebase
-                       --autostash --no-autostash
-                       $__git_merge_options
-                       $__git_fetch_options
-               "
+               __gitcomp_builtin pull "--no-autostash --no-commit --no-edit
+                                       --no-ff --no-log --no-progress --no-rebase
+                                       --no-squash --no-stat --no-tags
+                                       --no-verify-signatures"
+
                return
                ;;
        esac
@@ -1976,12 +1918,7 @@ _git_push ()
                return
                ;;
        --*)
-               __gitcomp "
-                       --all --mirror --tags --dry-run --force --verbose
-                       --quiet --prune --delete --follow-tags
-                       --receive-pack= --repo= --set-upstream
-                       --force-with-lease --force-with-lease= --recurse-submodules=
-               "
+               __gitcomp_builtin push
                return
                ;;
        esac
@@ -2016,6 +1953,7 @@ _git_rebase ()
                        --autostash --no-autostash
                        --verify --no-verify
                        --keep-empty --root --force-rebase --no-ff
+                       --rerere-autoupdate
                        --exec
                        "
 
@@ -2119,11 +2057,7 @@ _git_status ()
                return
                ;;
        --*)
-               __gitcomp "
-                       --short --branch --porcelain --long --verbose
-                       --untracked-files= --ignore-submodules= --ignored
-                       --column= --no-column
-                       "
+               __gitcomp_builtin status "--no-column"
                return
                ;;
        esac
@@ -2265,14 +2199,7 @@ _git_config ()
        esac
        case "$cur" in
        --*)
-               __gitcomp "
-                       --system --global --local --file=
-                       --list --replace-all
-                       --get --get-all --get-regexp
-                       --add --unset --unset-all
-                       --remove-section --rename-section
-                       --name-only
-                       "
+               __gitcomp_builtin config
                return
                ;;
        branch.*.*)
@@ -2672,7 +2599,7 @@ _git_remote ()
        if [ -z "$subcommand" ]; then
                case "$cur" in
                --*)
-                       __gitcomp "--verbose"
+                       __gitcomp_builtin remote
                        ;;
                *)
                        __gitcomp "$subcommands"
@@ -2683,33 +2610,33 @@ _git_remote ()
 
        case "$subcommand,$cur" in
        add,--*)
-               __gitcomp "--track --master --fetch --tags --no-tags --mirror="
+               __gitcomp_builtin remote_add "--no-tags"
                ;;
        add,*)
                ;;
        set-head,--*)
-               __gitcomp "--auto --delete"
+               __gitcomp_builtin remote_set-head
                ;;
        set-branches,--*)
-               __gitcomp "--add"
+               __gitcomp_builtin remote_set-branches
                ;;
        set-head,*|set-branches,*)
                __git_complete_remote_or_refspec
                ;;
        update,--*)
-               __gitcomp "--prune"
+               __gitcomp_builtin remote_update
                ;;
        update,*)
                __gitcomp "$(__git_get_config_variables "remotes")"
                ;;
        set-url,--*)
-               __gitcomp "--push --add --delete"
+               __gitcomp_builtin remote_set-url
                ;;
        get-url,--*)
-               __gitcomp "--push --all"
+               __gitcomp_builtin remote_get-url
                ;;
        prune,--*)
-               __gitcomp "--dry-run"
+               __gitcomp_builtin remote_prune
                ;;
        *)
                __gitcomp_nl "$(__git_remotes)"
@@ -2721,7 +2648,7 @@ _git_replace ()
 {
        case "$cur" in
        --*)
-               __gitcomp "--edit --graft --format= --list --delete"
+               __gitcomp_builtin replace
                return
                ;;
        esac
@@ -2745,26 +2672,26 @@ _git_reset ()
 
        case "$cur" in
        --*)
-               __gitcomp "--merge --mixed --hard --soft --patch --keep"
+               __gitcomp_builtin reset
                return
                ;;
        esac
        __git_complete_refs
 }
 
+__git_revert_inprogress_options="--continue --quit --abort"
+
 _git_revert ()
 {
        __git_find_repo_path
        if [ -f "$__git_repo_path"/REVERT_HEAD ]; then
-               __gitcomp "--continue --quit --abort"
+               __gitcomp "$__git_revert_inprogress_options"
                return
        fi
        case "$cur" in
        --*)
-               __gitcomp "
-                       --edit --mainline --no-edit --no-commit --signoff
-                       --strategy= --strategy-option=
-                       "
+               __gitcomp_builtin revert "--no-edit" \
+                       "$__git_revert_inprogress_options"
                return
                ;;
        esac
@@ -2775,7 +2702,7 @@ _git_rm ()
 {
        case "$cur" in
        --*)
-               __gitcomp "--cached --dry-run --ignore-unmatch --quiet"
+               __gitcomp_builtin rm
                return
                ;;
        esac
@@ -2833,12 +2760,7 @@ _git_show_branch ()
 {
        case "$cur" in
        --*)
-               __gitcomp "
-                       --all --remotes --topo-order --date-order --current --more=
-                       --list --independent --merge-base --no-name
-                       --color --no-color
-                       --sha1-name --sparse --topics --reflog
-                       "
+               __gitcomp_builtin show-branch "--no-color"
                return
                ;;
        esac
@@ -3071,11 +2993,7 @@ _git_tag ()
 
        case "$cur" in
        --*)
-               __gitcomp "
-                       --list --delete --verify --annotate --message --file
-                       --sign --cleanup --local-user --force --column --sort=
-                       --contains --no-contains --points-at --merged --no-merged --create-reflog
-                       "
+               __gitcomp_builtin tag
                ;;
        esac
 }
@@ -3094,16 +3012,16 @@ _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"
index d02eb8b0151626bab833489d7139a9be34209a32..125e84f98451b4eb12e9d8a6cb4da58b2d8db51e 100644 (file)
@@ -425,6 +425,48 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,
        parse_options_check(options);
 }
 
+/*
+ * TODO: we are not completing the --no-XXX form yet because there are
+ * many options that do not suppress it properly.
+ */
+static int show_gitcomp(struct parse_opt_ctx_t *ctx,
+                       const struct option *opts)
+{
+       for (; opts->type != OPTION_END; opts++) {
+               const char *suffix = "";
+
+               if (!opts->long_name)
+                       continue;
+               if (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE))
+                       continue;
+
+               switch (opts->type) {
+               case OPTION_GROUP:
+                       continue;
+               case OPTION_STRING:
+               case OPTION_FILENAME:
+               case OPTION_INTEGER:
+               case OPTION_MAGNITUDE:
+               case OPTION_CALLBACK:
+                       if (opts->flags & PARSE_OPT_NOARG)
+                               break;
+                       if (opts->flags & PARSE_OPT_OPTARG)
+                               break;
+                       if (opts->flags & PARSE_OPT_LASTARG_DEFAULT)
+                               break;
+                       suffix = "=";
+                       break;
+               default:
+                       break;
+               }
+               if (opts->flags & PARSE_OPT_COMP_ARG)
+                       suffix = "=";
+               printf(" --%s%s", opts->long_name, suffix);
+       }
+       fputc('\n', stdout);
+       exit(0);
+}
+
 static int usage_with_options_internal(struct parse_opt_ctx_t *,
                                       const char * const *,
                                       const struct option *, int, int);
@@ -455,6 +497,10 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
                if (internal_help && ctx->total == 1 && !strcmp(arg + 1, "h"))
                        goto show_usage;
 
+               /* lone --git-completion-helper is asked by git-completion.bash */
+               if (ctx->total == 1 && !strcmp(arg + 1, "-git-completion-helper"))
+                       return show_gitcomp(ctx, options);
+
                if (arg[1] != '-') {
                        ctx->opt = arg + 1;
                        switch (parse_short_opt(ctx, options)) {
index af711227ae3aac7af07de0322a364ccac03b819d..ab1cc362bf2918c28a14dd851c1b1a13dfa0c863 100644 (file)
@@ -38,7 +38,9 @@ enum parse_opt_option_flags {
        PARSE_OPT_LASTARG_DEFAULT = 16,
        PARSE_OPT_NODASH = 32,
        PARSE_OPT_LITERAL_ARGHELP = 64,
-       PARSE_OPT_SHELL_EVAL = 256
+       PARSE_OPT_SHELL_EVAL = 256,
+       PARSE_OPT_NOCOMPLETE = 512,
+       PARSE_OPT_COMP_ARG = 1024
 };
 
 struct option;
@@ -89,6 +91,11 @@ typedef int parse_opt_ll_cb(struct parse_opt_ctx_t *ctx,
  *   PARSE_OPT_LITERAL_ARGHELP: says that argh shouldn't be enclosed in brackets
  *                             (i.e. '<argh>') in the help message.
  *                             Useful for options with multiple parameters.
+ *   PARSE_OPT_NOCOMPLETE: by default all visible options are completable
+ *                        by git-completion.bash. This option suppresses that.
+ *   PARSE_OPT_COMP_ARG: this option forces to git-completion.bash to
+ *                      complete an option as --name= not --name even if
+ *                      the option takes optional argument.
  *
  * `callback`::
  *   pointer to the callback to use for OPTION_CALLBACK or
@@ -112,19 +119,24 @@ struct option {
        intptr_t defval;
 };
 
+#define OPT_BIT_F(s, l, v, h, b, f) { OPTION_BIT, (s), (l), (v), NULL, (h), \
+                                     PARSE_OPT_NOARG|(f), NULL, (b) }
+#define OPT_COUNTUP_F(s, l, v, h, f) { OPTION_COUNTUP, (s), (l), (v), NULL, \
+                                      (h), PARSE_OPT_NOARG|(f) }
+#define OPT_SET_INT_F(s, l, v, h, i, f) { OPTION_SET_INT, (s), (l), (v), NULL, \
+                                         (h), PARSE_OPT_NOARG | (f), NULL, (i) }
+#define OPT_BOOL_F(s, l, v, h, f)   OPT_SET_INT_F(s, l, v, h, 1, f)
+
 #define OPT_END()                   { OPTION_END }
 #define OPT_ARGUMENT(l, h)          { OPTION_ARGUMENT, 0, (l), NULL, NULL, \
                                      (h), PARSE_OPT_NOARG}
 #define OPT_GROUP(h)                { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
-#define OPT_BIT(s, l, v, h, b)      { OPTION_BIT, (s), (l), (v), NULL, (h), \
-                                     PARSE_OPT_NOARG, NULL, (b) }
+#define OPT_BIT(s, l, v, h, b)      OPT_BIT_F(s, l, v, h, b, 0)
 #define OPT_NEGBIT(s, l, v, h, b)   { OPTION_NEGBIT, (s), (l), (v), NULL, \
                                      (h), PARSE_OPT_NOARG, NULL, (b) }
-#define OPT_COUNTUP(s, l, v, h)     { OPTION_COUNTUP, (s), (l), (v), NULL, \
-                                     (h), PARSE_OPT_NOARG }
-#define OPT_SET_INT(s, l, v, h, i)  { OPTION_SET_INT, (s), (l), (v), NULL, \
-                                     (h), PARSE_OPT_NOARG, NULL, (i) }
-#define OPT_BOOL(s, l, v, h)        OPT_SET_INT(s, l, v, h, 1)
+#define OPT_COUNTUP(s, l, v, h)     OPT_COUNTUP_F(s, l, v, h, 0)
+#define OPT_SET_INT(s, l, v, h, i)  OPT_SET_INT_F(s, l, v, h, i, 0)
+#define OPT_BOOL(s, l, v, h)        OPT_BOOL_F(s, l, v, h, 0)
 #define OPT_HIDDEN_BOOL(s, l, v, h) { OPTION_SET_INT, (s), (l), (v), NULL, \
                                      (h), PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1}
 #define OPT_CMDMODE(s, l, v, h, i)  { OPTION_CMDMODE, (s), (l), (v), NULL, \
@@ -240,7 +252,7 @@ extern int parse_opt_passthru_argv(const struct option *, const char *, int);
        { OPTION_CALLBACK, 'q', "quiet", (var), NULL, N_("be more quiet"), \
          PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 }
 #define OPT__DRY_RUN(var, h)  OPT_BOOL('n', "dry-run", (var), (h))
-#define OPT__FORCE(var, h)    OPT_COUNTUP('f', "force",   (var), (h))
+#define OPT__FORCE(var, h, f) OPT_COUNTUP_F('f', "force",   (var), (h), (f))
 #define OPT__ABBREV(var)  \
        { OPTION_CALLBACK, 0, "abbrev", (var), N_("n"), \
          N_("use <n> digits to display SHA-1s"),       \
index fc614dcbfa74c39e120ff2fc80cdec07ea16a338..e6485feb0a0599769b8fba1a0ccd1f9fe41ba1fd 100755 (executable)
@@ -1237,17 +1237,19 @@ test_expect_success 'double dash "git" itself' '
 test_expect_success 'double dash "git checkout"' '
        test_completion "git checkout --" <<-\EOF
        --quiet Z
+       --detach Z
+       --track Z
+       --orphan=Z
        --ours Z
        --theirs Z
-       --track Z
-       --no-track Z
        --merge Z
-       --conflict=
-       --orphan Z
+       --conflict=Z
        --patch Z
-       --detach Z
        --ignore-skip-worktree-bits Z
+       --ignore-other-worktrees Z
        --recurse-submodules Z
+       --progress Z
+       --no-track Z
        --no-recurse-submodules Z
        EOF
 '