gc: automatically write commit-graph files
[gitweb.git] / contrib / completion / git-completion.bash
index 99dfedbd0bbb8fb7d12512331d4913a5ae3a8572..bc31e8973b25a8609fd9a6cb5eb4279de3eb332d 100644 (file)
@@ -94,6 +94,70 @@ __git ()
                ${__git_dir:+--git-dir="$__git_dir"} "$@" 2>/dev/null
 }
 
+# Removes backslash escaping, single quotes and double quotes from a word,
+# stores the result in the variable $dequoted_word.
+# 1: The word to dequote.
+__git_dequote ()
+{
+       local rest="$1" len ch
+
+       dequoted_word=""
+
+       while test -n "$rest"; do
+               len=${#dequoted_word}
+               dequoted_word="$dequoted_word${rest%%[\\\'\"]*}"
+               rest="${rest:$((${#dequoted_word}-$len))}"
+
+               case "${rest:0:1}" in
+               \\)
+                       ch="${rest:1:1}"
+                       case "$ch" in
+                       $'\n')
+                               ;;
+                       *)
+                               dequoted_word="$dequoted_word$ch"
+                               ;;
+                       esac
+                       rest="${rest:2}"
+                       ;;
+               \')
+                       rest="${rest:1}"
+                       len=${#dequoted_word}
+                       dequoted_word="$dequoted_word${rest%%\'*}"
+                       rest="${rest:$((${#dequoted_word}-$len+1))}"
+                       ;;
+               \")
+                       rest="${rest:1}"
+                       while test -n "$rest" ; do
+                               len=${#dequoted_word}
+                               dequoted_word="$dequoted_word${rest%%[\\\"]*}"
+                               rest="${rest:$((${#dequoted_word}-$len))}"
+                               case "${rest:0:1}" in
+                               \\)
+                                       ch="${rest:1:1}"
+                                       case "$ch" in
+                                       \"|\\|\$|\`)
+                                               dequoted_word="$dequoted_word$ch"
+                                               ;;
+                                       $'\n')
+                                               ;;
+                                       *)
+                                               dequoted_word="$dequoted_word\\$ch"
+                                               ;;
+                                       esac
+                                       rest="${rest:2}"
+                                       ;;
+                               \")
+                                       rest="${rest:1}"
+                                       break
+                                       ;;
+                               esac
+                       done
+                       ;;
+               esac
+       done
+}
+
 # The following function is based on code from:
 #
 #   bash_completion - programmable completion functions for bash 3.2+
@@ -346,6 +410,24 @@ __gitcomp_nl ()
        __gitcomp_nl_append "$@"
 }
 
+# Fills the COMPREPLY array with prefiltered paths without any additional
+# processing.
+# Callers must take care of providing only paths that match the current path
+# to be completed and adding any prefix path components, if necessary.
+# 1: List of newline-separated matching paths, complete with all prefix
+#    path componens.
+__gitcomp_file_direct ()
+{
+       local IFS=$'\n'
+
+       COMPREPLY=($1)
+
+       # use a hack to enable file mode in bash < 4
+       compopt -o filenames +o nospace 2>/dev/null ||
+       compgen -f /non-existing-dir/ >/dev/null ||
+       true
+}
+
 # Generates completion reply with compgen from newline-separated possible
 # completion filenames.
 # It accepts 1 to 3 arguments:
@@ -365,7 +447,8 @@ __gitcomp_file ()
 
        # use a hack to enable file mode in bash < 4
        compopt -o filenames +o nospace 2>/dev/null ||
-       compgen -f /non-existing-dir/ > /dev/null
+       compgen -f /non-existing-dir/ >/dev/null ||
+       true
 }
 
 # Execute 'git ls-files', unless the --committable option is specified, in
@@ -375,10 +458,12 @@ __gitcomp_file ()
 __git_ls_files_helper ()
 {
        if [ "$2" == "--committable" ]; then
-               __git -C "$1" diff-index --name-only --relative HEAD
+               __git -C "$1" -c core.quotePath=false diff-index \
+                       --name-only --relative HEAD -- "${3//\\/\\\\}*"
        else
                # NOTE: $2 is not quoted in order to support multiple options
-               __git -C "$1" ls-files --exclude-standard $2
+               __git -C "$1" -c core.quotePath=false ls-files \
+                       --exclude-standard $2 -- "${3//\\/\\\\}*"
        fi
 }
 
@@ -389,12 +474,103 @@ __git_ls_files_helper ()
 #    If provided, only files within the specified directory are listed.
 #    Sub directories are never recursed.  Path must have a trailing
 #    slash.
+# 3: List only paths matching this path component (optional).
 __git_index_files ()
 {
-       local root="${2-.}" file
+       local root="$2" match="$3"
 
-       __git_ls_files_helper "$root" "$1" |
-       cut -f1 -d/ | sort | uniq
+       __git_ls_files_helper "$root" "$1" "$match" |
+       awk -F / -v pfx="${2//\\/\\\\}" '{
+               paths[$1] = 1
+       }
+       END {
+               for (p in paths) {
+                       if (substr(p, 1, 1) != "\"") {
+                               # No special characters, easy!
+                               print pfx p
+                               continue
+                       }
+
+                       # The path is quoted.
+                       p = dequote(p)
+                       if (p == "")
+                               continue
+
+                       # Even when a directory name itself does not contain
+                       # any special characters, it will still be quoted if
+                       # any of its (stripped) trailing path components do.
+                       # Because of this we may have seen the same direcory
+                       # both quoted and unquoted.
+                       if (p in paths)
+                               # We have seen the same directory unquoted,
+                               # skip it.
+                               continue
+                       else
+                               print pfx p
+               }
+       }
+       function dequote(p,    bs_idx, out, esc, esc_idx, dec) {
+               # Skip opening double quote.
+               p = substr(p, 2)
+
+               # Interpret backslash escape sequences.
+               while ((bs_idx = index(p, "\\")) != 0) {
+                       out = out substr(p, 1, bs_idx - 1)
+                       esc = substr(p, bs_idx + 1, 1)
+                       p = substr(p, bs_idx + 2)
+
+                       if ((esc_idx = index("abtvfr\"\\", esc)) != 0) {
+                               # C-style one-character escape sequence.
+                               out = out substr("\a\b\t\v\f\r\"\\",
+                                                esc_idx, 1)
+                       } else if (esc == "n") {
+                               # Uh-oh, a newline character.
+                               # We cant reliably put a pathname
+                               # containing a newline into COMPREPLY,
+                               # and the newline would create a mess.
+                               # Skip this path.
+                               return ""
+                       } else {
+                               # Must be a \nnn octal value, then.
+                               dec = esc             * 64 + \
+                                     substr(p, 1, 1) * 8  + \
+                                     substr(p, 2, 1)
+                               out = out sprintf("%c", dec)
+                               p = substr(p, 3)
+                       }
+               }
+               # Drop closing double quote, if there is one.
+               # (There isnt any if this is a directory, as it was
+               # already stripped with the trailing path components.)
+               if (substr(p, length(p), 1) == "\"")
+                       out = out substr(p, 1, length(p) - 1)
+               else
+                       out = out p
+
+               return out
+       }'
+}
+
+# __git_complete_index_file requires 1 argument:
+# 1: the options to pass to ls-file
+#
+# The exception is --committable, which finds the files appropriate commit.
+__git_complete_index_file ()
+{
+       local dequoted_word pfx="" cur_
+
+       __git_dequote "$cur"
+
+       case "$dequoted_word" in
+       ?*/*)
+               pfx="${dequoted_word%/*}/"
+               cur_="${dequoted_word##*/}"
+               ;;
+       *)
+               cur_="$dequoted_word"
+       esac
+
+       __gitcomp_file_direct "$(__git_index_files "$1" "$pfx" "$cur_")"
 }
 
 # Lists branches from the local repository.
@@ -713,26 +889,6 @@ __git_complete_revlist_file ()
        esac
 }
 
-
-# __git_complete_index_file requires 1 argument:
-# 1: the options to pass to ls-file
-#
-# The exception is --committable, which finds the files appropriate commit.
-__git_complete_index_file ()
-{
-       local pfx="" cur_="$cur"
-
-       case "$cur_" in
-       ?*/*)
-               pfx="${cur_%/*}"
-               cur_="${cur_##*/}"
-               pfx="${pfx}/"
-               ;;
-       esac
-
-       __gitcomp_file "$(__git_index_files "$1" ${pfx:+"$pfx"})" "$pfx" "$cur_"
-}
-
 __git_complete_file ()
 {
        __git_complete_revlist_file
@@ -1986,9 +2142,24 @@ __git_config_get_set_variables ()
        __git config $config_file --name-only --list
 }
 
+__git_config_vars=
+__git_compute_config_vars ()
+{
+       test -n "$__git_config_vars" ||
+       __git_config_vars="$(git help --config-for-completion | sort | uniq)"
+}
+
 _git_config ()
 {
-       case "$prev" in
+       local varname
+
+       if [ "${BASH_VERSINFO[0]:-0}" -ge 4 ]; then
+               varname="${prev,,}"
+       else
+               varname="$(echo "$prev" |tr A-Z a-z)"
+       fi
+
+       case "$varname" in
        branch.*.remote|branch.*.pushremote)
                __gitcomp_nl "$(__git_remotes)"
                return
@@ -2086,20 +2257,20 @@ _git_config ()
                ;;
        branch.*.*)
                local pfx="${cur%.*}." cur_="${cur##*.}"
-               __gitcomp "remote pushremote merge mergeoptions rebase" "$pfx" "$cur_"
+               __gitcomp "remote pushRemote merge mergeOptions rebase" "$pfx" "$cur_"
                return
                ;;
        branch.*)
                local pfx="${cur%.*}." cur_="${cur#*.}"
                __gitcomp_direct "$(__git_heads "$pfx" "$cur_" ".")"
-               __gitcomp_nl_append $'autosetupmerge\nautosetuprebase\n' "$pfx" "$cur_"
+               __gitcomp_nl_append $'autoSetupMerge\nautoSetupRebase\n' "$pfx" "$cur_"
                return
                ;;
        guitool.*.*)
                local pfx="${cur%.*}." cur_="${cur##*.}"
                __gitcomp "
-                       argprompt cmd confirm needsfile noconsole norescan
-                       prompt revprompt revunmerged title
+                       argPrompt cmd confirm needsFile noConsole noRescan
+                       prompt revPrompt revUnmerged title
                        " "$pfx" "$cur_"
                return
                ;;
@@ -2128,14 +2299,14 @@ _git_config ()
                local pfx="${cur%.*}." cur_="${cur##*.}"
                __gitcomp "
                        url proxy fetch push mirror skipDefaultUpdate
-                       receivepack uploadpack tagopt pushurl
+                       receivepack uploadpack tagOpt pushurl
                        " "$pfx" "$cur_"
                return
                ;;
        remote.*)
                local pfx="${cur%.*}." cur_="${cur#*.}"
                __gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "."
-               __gitcomp_nl_append "pushdefault" "$pfx" "$cur_"
+               __gitcomp_nl_append "pushDefault" "$pfx" "$cur_"
                return
                ;;
        url.*.*)
@@ -2143,333 +2314,14 @@ _git_config ()
                __gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur_"
                return
                ;;
+       *.*)
+               __git_compute_config_vars
+               __gitcomp "$__git_config_vars"
+               ;;
+       *)
+               __git_compute_config_vars
+               __gitcomp "$(echo "$__git_config_vars" | sed 's/\.[^ ]*/./g')"
        esac
-       __gitcomp "
-               add.ignoreErrors
-               advice.amWorkDir
-               advice.commitBeforeMerge
-               advice.detachedHead
-               advice.implicitIdentity
-               advice.pushAlreadyExists
-               advice.pushFetchFirst
-               advice.pushNeedsForce
-               advice.pushNonFFCurrent
-               advice.pushNonFFMatching
-               advice.pushUpdateRejected
-               advice.resolveConflict
-               advice.rmHints
-               advice.statusHints
-               advice.statusUoption
-               advice.ignoredHook
-               alias.
-               am.keepcr
-               am.threeWay
-               apply.ignorewhitespace
-               apply.whitespace
-               branch.autosetupmerge
-               branch.autosetuprebase
-               browser.
-               clean.requireForce
-               color.branch
-               color.branch.current
-               color.branch.local
-               color.branch.plain
-               color.branch.remote
-               color.decorate.HEAD
-               color.decorate.branch
-               color.decorate.remoteBranch
-               color.decorate.stash
-               color.decorate.tag
-               color.diff
-               color.diff.commit
-               color.diff.frag
-               color.diff.func
-               color.diff.meta
-               color.diff.new
-               color.diff.old
-               color.diff.plain
-               color.diff.whitespace
-               color.grep
-               color.grep.context
-               color.grep.filename
-               color.grep.function
-               color.grep.linenumber
-               color.grep.match
-               color.grep.selected
-               color.grep.separator
-               color.interactive
-               color.interactive.error
-               color.interactive.header
-               color.interactive.help
-               color.interactive.prompt
-               color.pager
-               color.showbranch
-               color.status
-               color.status.added
-               color.status.changed
-               color.status.header
-               color.status.localBranch
-               color.status.nobranch
-               color.status.remoteBranch
-               color.status.unmerged
-               color.status.untracked
-               color.status.updated
-               color.ui
-               commit.cleanup
-               commit.gpgSign
-               commit.status
-               commit.template
-               commit.verbose
-               core.abbrev
-               core.askpass
-               core.attributesfile
-               core.autocrlf
-               core.bare
-               core.bigFileThreshold
-               core.checkStat
-               core.commentChar
-               core.commitGraph
-               core.compression
-               core.createObject
-               core.deltaBaseCacheLimit
-               core.editor
-               core.eol
-               core.excludesfile
-               core.fileMode
-               core.fsyncobjectfiles
-               core.gitProxy
-               core.hideDotFiles
-               core.hooksPath
-               core.ignoreStat
-               core.ignorecase
-               core.logAllRefUpdates
-               core.loosecompression
-               core.notesRef
-               core.packedGitLimit
-               core.packedGitWindowSize
-               core.packedRefsTimeout
-               core.pager
-               core.precomposeUnicode
-               core.preferSymlinkRefs
-               core.preloadindex
-               core.protectHFS
-               core.protectNTFS
-               core.quotepath
-               core.repositoryFormatVersion
-               core.safecrlf
-               core.sharedRepository
-               core.sparseCheckout
-               core.splitIndex
-               core.sshCommand
-               core.symlinks
-               core.trustctime
-               core.untrackedCache
-               core.warnAmbiguousRefs
-               core.whitespace
-               core.worktree
-               credential.helper
-               credential.useHttpPath
-               credential.username
-               credentialCache.ignoreSIGHUP
-               diff.autorefreshindex
-               diff.external
-               diff.ignoreSubmodules
-               diff.mnemonicprefix
-               diff.noprefix
-               diff.renameLimit
-               diff.renames
-               diff.statGraphWidth
-               diff.submodule
-               diff.suppressBlankEmpty
-               diff.tool
-               diff.wordRegex
-               diff.algorithm
-               difftool.
-               difftool.prompt
-               fetch.recurseSubmodules
-               fetch.unpackLimit
-               format.attach
-               format.cc
-               format.coverLetter
-               format.from
-               format.headers
-               format.numbered
-               format.pretty
-               format.signature
-               format.signoff
-               format.subjectprefix
-               format.suffix
-               format.thread
-               format.to
-               gc.
-               gc.aggressiveDepth
-               gc.aggressiveWindow
-               gc.auto
-               gc.autoDetach
-               gc.autopacklimit
-               gc.logExpiry
-               gc.packrefs
-               gc.pruneexpire
-               gc.reflogexpire
-               gc.reflogexpireunreachable
-               gc.rerereresolved
-               gc.rerereunresolved
-               gc.worktreePruneExpire
-               gitcvs.allbinary
-               gitcvs.commitmsgannotation
-               gitcvs.dbTableNamePrefix
-               gitcvs.dbdriver
-               gitcvs.dbname
-               gitcvs.dbpass
-               gitcvs.dbuser
-               gitcvs.enabled
-               gitcvs.logfile
-               gitcvs.usecrlfattr
-               guitool.
-               gui.blamehistoryctx
-               gui.commitmsgwidth
-               gui.copyblamethreshold
-               gui.diffcontext
-               gui.encoding
-               gui.fastcopyblame
-               gui.matchtrackingbranch
-               gui.newbranchtemplate
-               gui.pruneduringfetch
-               gui.spellingdictionary
-               gui.trustmtime
-               help.autocorrect
-               help.browser
-               help.format
-               http.lowSpeedLimit
-               http.lowSpeedTime
-               http.maxRequests
-               http.minSessions
-               http.noEPSV
-               http.postBuffer
-               http.proxy
-               http.sslCipherList
-               http.sslVersion
-               http.sslCAInfo
-               http.sslCAPath
-               http.sslCert
-               http.sslCertPasswordProtected
-               http.sslKey
-               http.sslVerify
-               http.useragent
-               i18n.commitEncoding
-               i18n.logOutputEncoding
-               imap.authMethod
-               imap.folder
-               imap.host
-               imap.pass
-               imap.port
-               imap.preformattedHTML
-               imap.sslverify
-               imap.tunnel
-               imap.user
-               init.templatedir
-               instaweb.browser
-               instaweb.httpd
-               instaweb.local
-               instaweb.modulepath
-               instaweb.port
-               interactive.singlekey
-               log.date
-               log.decorate
-               log.showroot
-               mailmap.file
-               man.
-               man.viewer
-               merge.
-               merge.conflictstyle
-               merge.log
-               merge.renameLimit
-               merge.renormalize
-               merge.stat
-               merge.tool
-               merge.verbosity
-               mergetool.
-               mergetool.keepBackup
-               mergetool.keepTemporaries
-               mergetool.prompt
-               notes.displayRef
-               notes.rewrite.
-               notes.rewrite.amend
-               notes.rewrite.rebase
-               notes.rewriteMode
-               notes.rewriteRef
-               pack.compression
-               pack.deltaCacheLimit
-               pack.deltaCacheSize
-               pack.depth
-               pack.indexVersion
-               pack.packSizeLimit
-               pack.threads
-               pack.window
-               pack.windowMemory
-               pager.
-               pretty.
-               pull.octopus
-               pull.twohead
-               push.default
-               push.followTags
-               rebase.autosquash
-               rebase.stat
-               receive.autogc
-               receive.denyCurrentBranch
-               receive.denyDeleteCurrent
-               receive.denyDeletes
-               receive.denyNonFastForwards
-               receive.fsckObjects
-               receive.unpackLimit
-               receive.updateserverinfo
-               remote.pushdefault
-               remotes.
-               repack.usedeltabaseoffset
-               rerere.autoupdate
-               rerere.enabled
-               sendemail.
-               sendemail.aliasesfile
-               sendemail.aliasfiletype
-               sendemail.bcc
-               sendemail.cc
-               sendemail.cccmd
-               sendemail.chainreplyto
-               sendemail.confirm
-               sendemail.envelopesender
-               sendemail.from
-               sendemail.identity
-               sendemail.multiedit
-               sendemail.signedoffbycc
-               sendemail.smtpdomain
-               sendemail.smtpencryption
-               sendemail.smtppass
-               sendemail.smtpserver
-               sendemail.smtpserveroption
-               sendemail.smtpserverport
-               sendemail.smtpuser
-               sendemail.suppresscc
-               sendemail.suppressfrom
-               sendemail.thread
-               sendemail.to
-               sendemail.tocmd
-               sendemail.validate
-               sendemail.smtpbatchsize
-               sendemail.smtprelogindelay
-               showbranch.default
-               status.relativePaths
-               status.showUntrackedFiles
-               status.submodulesummary
-               submodule.
-               tar.umask
-               transfer.unpackLimit
-               url.
-               user.email
-               user.name
-               user.signingkey
-               web.browser
-               branch. remote.
-       "
 }
 
 _git_remote ()
@@ -2510,7 +2362,7 @@ _git_remote ()
                __gitcomp_builtin remote_update
                ;;
        update,*)
-               __gitcomp "$(__git_get_config_variables "remotes")"
+               __gitcomp "$(__git_remotes) $(__git_get_config_variables "remotes")"
                ;;
        set-url,--*)
                __gitcomp_builtin remote_set-url
@@ -3067,7 +2919,10 @@ __gitk_main ()
        __git_complete_revlist
 }
 
-if [[ -n ${ZSH_VERSION-} ]]; then
+if [[ -n ${ZSH_VERSION-} ]] &&
+   # Don't define these functions when sourced from 'git-completion.zsh',
+   # it has its own implementations.
+   [[ -z ${GIT_SOURCING_ZSH_COMPLETION-} ]]; then
        echo "WARNING: this script is deprecated, please see git-completion.zsh" 1>&2
 
        autoload -U +X compinit && compinit
@@ -3116,6 +2971,15 @@ if [[ -n ${ZSH_VERSION-} ]]; then
                compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0
        }
 
+       __gitcomp_file_direct ()
+       {
+               emulate -L zsh
+
+               local IFS=$'\n'
+               compset -P '*[=:]'
+               compadd -Q -f -- ${=1} && _ret=0
+       }
+
        __gitcomp_file ()
        {
                emulate -L zsh