diff options
Diffstat (limited to 'contrib')
33 files changed, 750 insertions, 223 deletions
diff --git a/contrib/coccinelle/array.cocci b/contrib/coccinelle/array.cocci index 4ba98b7eaf..01586821dc 100644 --- a/contrib/coccinelle/array.cocci +++ b/contrib/coccinelle/array.cocci @@ -4,7 +4,7 @@ T *dst; T *src; expression n; @@ -- memcpy(dst, src, n * sizeof(*dst)); +- memcpy(dst, src, (n) * sizeof(*dst)); + COPY_ARRAY(dst, src, n); @@ @@ -13,7 +13,7 @@ T *dst; T *src; expression n; @@ -- memcpy(dst, src, n * sizeof(*src)); +- memcpy(dst, src, (n) * sizeof(*src)); + COPY_ARRAY(dst, src, n); @@ @@ -22,15 +22,32 @@ T *dst; T *src; expression n; @@ -- memcpy(dst, src, n * sizeof(T)); +- memcpy(dst, src, (n) * sizeof(T)); + COPY_ARRAY(dst, src, n); @@ type T; +T *dst; +T *src; +expression n; +@@ +( +- memmove(dst, src, (n) * sizeof(*dst)); ++ MOVE_ARRAY(dst, src, n); +| +- memmove(dst, src, (n) * sizeof(*src)); ++ MOVE_ARRAY(dst, src, n); +| +- memmove(dst, src, (n) * sizeof(T)); ++ MOVE_ARRAY(dst, src, n); +) + +@@ +type T; T *ptr; expression n; @@ -- ptr = xmalloc(n * sizeof(*ptr)); +- ptr = xmalloc((n) * sizeof(*ptr)); + ALLOC_ARRAY(ptr, n); @@ @@ -38,5 +55,5 @@ type T; T *ptr; expression n; @@ -- ptr = xmalloc(n * sizeof(T)); +- ptr = xmalloc((n) * sizeof(T)); + ALLOC_ARRAY(ptr, n); diff --git a/contrib/coccinelle/free.cocci b/contrib/coccinelle/free.cocci index c03ba737e5..4490069df9 100644 --- a/contrib/coccinelle/free.cocci +++ b/contrib/coccinelle/free.cocci @@ -9,3 +9,10 @@ expression E; @@ - if (!E) free(E); + +@@ +expression E; +@@ +- free(E); ++ FREE_AND_NULL(E); +- E = NULL; diff --git a/contrib/completion/.gitattributes b/contrib/completion/.gitattributes new file mode 100644 index 0000000000..19116944c1 --- /dev/null +++ b/contrib/completion/.gitattributes @@ -0,0 +1 @@ +*.bash eol=lf diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 41ee52991d..6f890c0f50 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -28,27 +28,55 @@ # completion style. For example '!f() { : git commit ; ... }; f' will # tell the completion to use commit completion. This also works with aliases # of form "!sh -c '...'". For example, "!sh -c ': git commit ; ... '". +# +# You can set the following environment variables to influence the behavior of +# the completion routines: +# +# GIT_COMPLETION_CHECKOUT_NO_GUESS +# +# When set to "1", do not include "DWIM" suggestions in git-checkout +# completion (e.g., completing "foo" when "origin/foo" exists). case "$COMP_WORDBREAKS" in *:*) : great ;; *) COMP_WORDBREAKS="$COMP_WORDBREAKS:" esac +# Discovers the path to the git repository taking any '--git-dir=<path>' and +# '-C <path>' options into account and stores it in the $__git_repo_path +# variable. +__git_find_repo_path () +{ + if [ -n "$__git_repo_path" ]; then + # we already know where it is + return + fi + + if [ -n "${__git_C_args-}" ]; then + __git_repo_path="$(git "${__git_C_args[@]}" \ + ${__git_dir:+--git-dir="$__git_dir"} \ + rev-parse --absolute-git-dir 2>/dev/null)" + elif [ -n "${__git_dir-}" ]; then + test -d "$__git_dir" && + __git_repo_path="$__git_dir" + elif [ -n "${GIT_DIR-}" ]; then + test -d "${GIT_DIR-}" && + __git_repo_path="$GIT_DIR" + elif [ -d .git ]; then + __git_repo_path=.git + else + __git_repo_path="$(git rev-parse --git-dir 2>/dev/null)" + fi +} + +# Deprecated: use __git_find_repo_path() and $__git_repo_path instead # __gitdir accepts 0 or 1 arguments (i.e., location) # returns location of .git repo __gitdir () { if [ -z "${1-}" ]; then - if [ -n "${__git_dir-}" ]; then - echo "$__git_dir" - elif [ -n "${GIT_DIR-}" ]; then - test -d "${GIT_DIR-}" || return 1 - echo "$GIT_DIR" - elif [ -d .git ]; then - echo .git - else - git rev-parse --git-dir 2>/dev/null - fi + __git_find_repo_path || return 1 + echo "$__git_repo_path" elif [ -d "$1/.git" ]; then echo "$1/.git" else @@ -56,6 +84,14 @@ __gitdir () fi } +# Runs git with all the options given as argument, respecting any +# '--git-dir=<path>' and '-C <path>' options present on the command line +__git () +{ + git ${__git_C_args:+"${__git_C_args[@]}"} \ + ${__git_dir:+--git-dir="$__git_dir"} "$@" 2>/dev/null +} + # The following function is based on code from: # # bash_completion - programmable completion functions for bash 3.2+ @@ -75,8 +111,7 @@ __gitdir () # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program; if not, see <http://www.gnu.org/licenses/>. # # The latest version of this software can be obtained here: # @@ -185,6 +220,20 @@ _get_comp_words_by_ref () } fi +# Fills the COMPREPLY array with prefiltered words without any additional +# processing. +# Callers must take care of providing only words that match the current word +# to be completed and adding any prefix and/or suffix (trailing space!), if +# necessary. +# 1: List of newline-separated matching completion words, complete with +# prefix and suffix. +__gitcomp_direct () +{ + local IFS=$'\n' + + COMPREPLY=($1) +} + __gitcompappend () { local x i=${#COMPREPLY[@]} @@ -283,11 +332,11 @@ __gitcomp_file () __git_ls_files_helper () { if [ "$2" == "--committable" ]; then - git -C "$1" diff-index --name-only --relative HEAD + __git -C "$1" diff-index --name-only --relative HEAD else # NOTE: $2 is not quoted in order to support multiple options - git -C "$1" ls-files --exclude-standard $2 - fi 2>/dev/null + __git -C "$1" ls-files --exclude-standard $2 + fi } @@ -299,100 +348,195 @@ __git_ls_files_helper () # slash. __git_index_files () { - local dir="$(__gitdir)" root="${2-.}" file + local root="${2-.}" file - if [ -d "$dir" ]; then - __git_ls_files_helper "$root" "$1" | - while read -r file; do - case "$file" in - ?*/*) echo "${file%%/*}" ;; - *) echo "$file" ;; - esac - done | sort | uniq - fi + __git_ls_files_helper "$root" "$1" | + while read -r file; do + case "$file" in + ?*/*) echo "${file%%/*}" ;; + *) echo "$file" ;; + esac + done | sort | uniq } +# Lists branches from the local repository. +# 1: A prefix to be added to each listed branch (optional). +# 2: List only branches matching this word (optional; list all branches if +# unset or empty). +# 3: A suffix to be appended to each listed branch (optional). __git_heads () { - local dir="$(__gitdir)" - if [ -d "$dir" ]; then - git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ - refs/heads - return - fi + local pfx="${1-}" cur_="${2-}" sfx="${3-}" + + __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \ + "refs/heads/$cur_*" "refs/heads/$cur_*/**" } +# Lists tags from the local repository. +# Accepts the same positional parameters as __git_heads() above. __git_tags () { - local dir="$(__gitdir)" - if [ -d "$dir" ]; then - git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ - refs/tags - return - fi + local pfx="${1-}" cur_="${2-}" sfx="${3-}" + + __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \ + "refs/tags/$cur_*" "refs/tags/$cur_*/**" } -# __git_refs accepts 0, 1 (to pass to __gitdir), or 2 arguments -# presence of 2nd argument means use the guess heuristic employed -# by checkout for tracking branches +# Lists refs from the local (by default) or from a remote repository. +# It accepts 0, 1 or 2 arguments: +# 1: The remote to list refs from (optional; ignored, if set but empty). +# Can be the name of a configured remote, a path, or a URL. +# 2: In addition to local refs, list unique branches from refs/remotes/ for +# 'git checkout's tracking DWIMery (optional; ignored, if set but empty). +# 3: A prefix to be added to each listed ref (optional). +# 4: List only refs matching this word (optional; list all refs if unset or +# empty). +# 5: A suffix to be appended to each listed ref (optional; ignored, if set +# but empty). +# +# Use __git_complete_refs() instead. __git_refs () { - local i hash dir="$(__gitdir "${1-}")" track="${2-}" - local format refs pfx - if [ -d "$dir" ]; then - case "$cur" in + local i hash dir track="${2-}" + local list_refs_from=path remote="${1-}" + local format refs + local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}" + local match="${4-}" + local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers + + __git_find_repo_path + dir="$__git_repo_path" + + if [ -z "$remote" ]; then + if [ -z "$dir" ]; then + return + fi + else + if __git_is_configured_remote "$remote"; then + # configured remote takes precedence over a + # local directory with the same name + list_refs_from=remote + elif [ -d "$remote/.git" ]; then + dir="$remote/.git" + elif [ -d "$remote" ]; then + dir="$remote" + else + list_refs_from=url + fi + fi + + if [ "$list_refs_from" = path ]; then + if [[ "$cur_" == ^* ]]; then + pfx="$pfx^" + fer_pfx="$fer_pfx^" + cur_=${cur_#^} + match=${match#^} + fi + case "$cur_" in refs|refs/*) format="refname" - refs="${cur%/*}" + refs=("$match*" "$match*/**") track="" ;; *) - [[ "$cur" == ^* ]] && pfx="^" for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do - if [ -e "$dir/$i" ]; then echo $pfx$i; fi + case "$i" in + $match*) + if [ -e "$dir/$i" ]; then + echo "$pfx$i$sfx" + fi + ;; + esac done - format="refname:short" - refs="refs/tags refs/heads refs/remotes" + format="refname:strip=2" + refs=("refs/tags/$match*" "refs/tags/$match*/**" + "refs/heads/$match*" "refs/heads/$match*/**" + "refs/remotes/$match*" "refs/remotes/$match*/**") ;; esac - git --git-dir="$dir" for-each-ref --format="$pfx%($format)" \ - $refs + __git_dir="$dir" __git for-each-ref --format="$fer_pfx%($format)$sfx" \ + "${refs[@]}" if [ -n "$track" ]; then # employ the heuristic used by git checkout # Try to find a remote branch that matches the completion word # but only output if the branch name is unique - local ref entry - git --git-dir="$dir" for-each-ref --shell --format="ref=%(refname:short)" \ - "refs/remotes/" | \ - while read -r entry; do - eval "$entry" - ref="${ref#*/}" - if [[ "$ref" == "$cur"* ]]; then - echo "$ref" - fi - done | sort | uniq -u + __git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \ + --sort="refname:strip=3" \ + "refs/remotes/*/$match*" "refs/remotes/*/$match*/**" | \ + uniq -u fi return fi - case "$cur" in + case "$cur_" in refs|refs/*) - git ls-remote "$dir" "$cur*" 2>/dev/null | \ + __git ls-remote "$remote" "$match*" | \ while read -r hash i; do case "$i" in *^{}) ;; - *) echo "$i" ;; + *) echo "$pfx$i$sfx" ;; esac done ;; *) - echo "HEAD" - git for-each-ref --format="%(refname:short)" -- \ - "refs/remotes/$dir/" 2>/dev/null | sed -e "s#^$dir/##" + if [ "$list_refs_from" = remote ]; then + case "HEAD" in + $match*) echo "${pfx}HEAD$sfx" ;; + esac + __git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \ + "refs/remotes/$remote/$match*" \ + "refs/remotes/$remote/$match*/**" + else + local query_symref + case "HEAD" in + $match*) query_symref="HEAD" ;; + esac + __git ls-remote "$remote" $query_symref \ + "refs/tags/$match*" "refs/heads/$match*" \ + "refs/remotes/$match*" | + while read -r hash i; do + case "$i" in + *^{}) ;; + refs/*) echo "$pfx${i#refs/*/}$sfx" ;; + *) echo "$pfx$i$sfx" ;; # symbolic refs + esac + done + fi ;; esac } +# Completes refs, short and long, local and remote, symbolic and pseudo. +# +# Usage: __git_complete_refs [<option>]... +# --remote=<remote>: The remote to list refs from, can be the name of a +# configured remote, a path, or a URL. +# --track: List unique remote branches for 'git checkout's tracking DWIMery. +# --pfx=<prefix>: A prefix to be added to each ref. +# --cur=<word>: The current ref to be completed. Defaults to the current +# word to be completed. +# --sfx=<suffix>: A suffix to be appended to each ref instead of the default +# space. +__git_complete_refs () +{ + local remote track pfx cur_="$cur" sfx=" " + + while test $# != 0; do + case "$1" in + --remote=*) remote="${1##--remote=}" ;; + --track) track="yes" ;; + --pfx=*) pfx="${1##--pfx=}" ;; + --cur=*) cur_="${1##--cur=}" ;; + --sfx=*) sfx="${1##--sfx=}" ;; + *) return 1 ;; + esac + shift + done + + __gitcomp_direct "$(__git_refs "$remote" "$track" "$pfx" "$cur_" "$sfx")" +} + # __git_refs2 requires 1 argument (to pass to __git_refs) +# Deprecated: use __git_complete_fetch_refspecs() instead. __git_refs2 () { local i @@ -401,11 +545,29 @@ __git_refs2 () done } +# Completes refspecs for fetching from a remote repository. +# 1: The remote repository. +# 2: A prefix to be added to each listed refspec (optional). +# 3: The ref to be completed as a refspec instead of the current word to be +# completed (optional) +# 4: A suffix to be appended to each listed refspec instead of the default +# space (optional). +__git_complete_fetch_refspecs () +{ + local i remote="$1" pfx="${2-}" cur_="${3-$cur}" sfx="${4- }" + + __gitcomp_direct "$( + for i in $(__git_refs "$remote" "" "" "$cur_") ; do + echo "$pfx$i:$i$sfx" + done + )" +} + # __git_refs_remotes requires 1 argument (to pass to ls-remote) __git_refs_remotes () { local i hash - git ls-remote "$1" 'refs/heads/*' 2>/dev/null | \ + __git ls-remote "$1" 'refs/heads/*' | \ while read -r hash i; do echo "$i:refs/remotes/$1/${i#refs/heads/}" done @@ -413,9 +575,21 @@ __git_refs_remotes () __git_remotes () { - local d="$(__gitdir)" - test -d "$d/remotes" && ls -1 "$d/remotes" - git --git-dir="$d" remote + __git_find_repo_path + test -d "$__git_repo_path/remotes" && ls -1 "$__git_repo_path/remotes" + __git remote +} + +# Returns true if $1 matches the name of a configured remote, false otherwise. +__git_is_configured_remote () +{ + local remote + for remote in $(__git_remotes); do + if [ "$remote" = "$1" ]; then + return 0 + fi + done + return 1 } __git_list_merge_strategies () @@ -469,7 +643,7 @@ __git_complete_revlist_file () *) pfx="$ref:$pfx" ;; esac - __gitcomp_nl "$(git --git-dir="$(__gitdir)" ls-tree "$ls" 2>/dev/null \ + __gitcomp_nl "$(__git ls-tree "$ls" \ | sed '/^100... blob /{ s,^.* ,, s,$, , @@ -488,15 +662,15 @@ __git_complete_revlist_file () *...*) pfx="${cur_%...*}..." cur_="${cur_#*...}" - __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + __git_complete_refs --pfx="$pfx" --cur="$cur_" ;; *..*) pfx="${cur_%..*}.." cur_="${cur_#*..}" - __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + __git_complete_refs --pfx="$pfx" --cur="$cur_" ;; *) - __gitcomp_nl "$(__git_refs)" + __git_complete_refs ;; esac } @@ -542,6 +716,7 @@ __git_complete_remote_or_refspec () i="${words[c]}" case "$i" in --mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;; + -d|--delete) [ "$cmd" = "push" ] && lhs=0 ;; --all) case "$cmd" in push) no_complete_refspec=1 ;; @@ -581,23 +756,23 @@ __git_complete_remote_or_refspec () case "$cmd" in fetch) if [ $lhs = 1 ]; then - __gitcomp_nl "$(__git_refs2 "$remote")" "$pfx" "$cur_" + __git_complete_fetch_refspecs "$remote" "$pfx" "$cur_" else - __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + __git_complete_refs --pfx="$pfx" --cur="$cur_" fi ;; pull|remote) if [ $lhs = 1 ]; then - __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_" + __git_complete_refs --remote="$remote" --pfx="$pfx" --cur="$cur_" else - __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + __git_complete_refs --pfx="$pfx" --cur="$cur_" fi ;; push) if [ $lhs = 1 ]; then - __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + __git_complete_refs --pfx="$pfx" --cur="$cur_" else - __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_" + __git_complete_refs --remote="$remote" --pfx="$pfx" --cur="$cur_" fi ;; esac @@ -747,7 +922,7 @@ __git_compute_porcelain_commands () __git_get_config_variables () { local section="$1" i IFS=$'\n' - for i in $(git --git-dir="$(__gitdir)" config --name-only --get-regexp "^$section\..*" 2>/dev/null); do + for i in $(__git config --name-only --get-regexp "^$section\..*"); do echo "${i#$section.}" done } @@ -765,8 +940,7 @@ __git_aliases () # __git_aliased_command requires 1 argument __git_aliased_command () { - local word cmdline=$(git --git-dir="$(__gitdir)" \ - config --get "alias.$1") + local word cmdline=$(__git config --get "alias.$1") for word in $cmdline; do case "$word" in \!gitk|gitk) @@ -842,7 +1016,7 @@ __git_get_option_value () done if [ -n "$config_key" ] && [ -z "$result" ]; then - result="$(git --git-dir="$(__gitdir)" config "$config_key")" + result="$(__git config "$config_key")" fi echo "$result" @@ -901,8 +1075,8 @@ __git_whitespacelist="nowarn warn error error-all fix" _git_am () { - local dir="$(__gitdir)" - if [ -d "$dir"/rebase-apply ]; then + __git_find_repo_path + if [ -d "$__git_repo_path"/rebase-apply ]; then __gitcomp "--skip --continue --resolved --abort" return fi @@ -990,7 +1164,8 @@ _git_bisect () local subcommands="start bad good skip reset visualize replay log run" local subcommand="$(__git_find_on_cmdline "$subcommands")" if [ -z "$subcommand" ]; then - if [ -f "$(__gitdir)"/BISECT_START ]; then + __git_find_repo_path + if [ -f "$__git_repo_path"/BISECT_START ]; then __gitcomp "$subcommands" else __gitcomp "replay start" @@ -1000,7 +1175,7 @@ _git_bisect () case "$subcommand" in bad|good|reset|skip|start) - __gitcomp_nl "$(__git_refs)" + __git_complete_refs ;; *) ;; @@ -1022,12 +1197,12 @@ _git_branch () case "$cur" in --set-upstream-to=*) - __gitcomp_nl "$(__git_refs)" "" "${cur##--set-upstream-to=}" + __git_complete_refs --cur="${cur##--set-upstream-to=}" ;; --*) __gitcomp " --color --no-color --verbose --abbrev= --no-abbrev - --track --no-track --contains --merged --no-merged + --track --no-track --contains --no-contains --merged --no-merged --set-upstream-to= --edit-description --list --unset-upstream --delete --move --remotes --column --no-column --sort= --points-at @@ -1035,9 +1210,9 @@ _git_branch () ;; *) if [ $only_local_ref = "y" -a $has_r = "n" ]; then - __gitcomp_nl "$(__git_heads)" + __gitcomp_direct "$(__git_heads "" "$cur" " ")" else - __gitcomp_nl "$(__git_refs)" + __git_complete_refs fi ;; esac @@ -1074,30 +1249,32 @@ _git_checkout () --*) __gitcomp " --quiet --ours --theirs --track --no-track --merge - --conflict= --orphan --patch + --conflict= --orphan --patch --detach --ignore-skip-worktree-bits + --recurse-submodules --no-recurse-submodules " ;; *) # check if --track, --no-track, or --no-guess was specified # if so, disable DWIM mode - local flags="--track --no-track --no-guess" track=1 - if [ -n "$(__git_find_on_cmdline "$flags")" ]; then - track='' + local flags="--track --no-track --no-guess" track_opt="--track" + if [ "$GIT_COMPLETION_CHECKOUT_NO_GUESS" = "1" ] || + [ -n "$(__git_find_on_cmdline "$flags")" ]; then + track_opt='' fi - __gitcomp_nl "$(__git_refs '' $track)" + __git_complete_refs $track_opt ;; esac } _git_cherry () { - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_cherry_pick () { - local dir="$(__gitdir)" - if [ -f "$dir"/CHERRY_PICK_HEAD ]; then + __git_find_repo_path + if [ -f "$__git_repo_path"/CHERRY_PICK_HEAD ]; then __gitcomp "--continue --quit --abort" return fi @@ -1106,7 +1283,7 @@ _git_cherry_pick () __gitcomp "--edit --no-commit --signoff --strategy= --mainline" ;; *) - __gitcomp_nl "$(__git_refs)" + __git_complete_refs ;; esac } @@ -1142,6 +1319,7 @@ _git_clone () --template= --depth --single-branch + --no-tags --branch --recurse-submodules --no-single-branch @@ -1158,7 +1336,7 @@ _git_commit () { case "$prev" in -c|-C) - __gitcomp_nl "$(__git_refs)" "" "${cur}" + __git_complete_refs return ;; esac @@ -1171,7 +1349,7 @@ _git_commit () ;; --reuse-message=*|--reedit-message=*|\ --fixup=*|--squash=*) - __gitcomp_nl "$(__git_refs)" "" "${cur#*=}" + __git_complete_refs --cur="${cur#*=}" return ;; --untracked-files=*) @@ -1192,7 +1370,7 @@ _git_commit () return esac - if git rev-parse --verify --quiet HEAD >/dev/null; then + if __git rev-parse --verify --quiet HEAD >/dev/null; then __git_complete_index_file "--committable" else # This is the first commit @@ -1207,10 +1385,11 @@ _git_describe () __gitcomp " --all --tags --contains --abbrev= --candidates= --exact-match --debug --long --match --always --first-parent + --exclude --dirty --broken " return esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } __git_diff_algorithms="myers minimal patience histogram" @@ -1221,7 +1400,7 @@ __git_diff_common_options="--stat --numstat --shortstat --summary --patch-with-stat --name-only --name-status --color --no-color --color-words --no-renames --check --full-index --binary --abbrev --diff-filter= - --find-copies-harder + --find-copies-harder --ignore-cr-at-eol --text --ignore-space-at-eol --ignore-space-change --ignore-all-space --ignore-blank-lines --exit-code --quiet --ext-diff --no-ext-diff @@ -1361,8 +1540,43 @@ _git_gitk () _gitk } -__git_match_ctag() { - awk "/^${1//\//\\/}/ { print \$1 }" "$2" +# Lists matching symbol names from a tag (as in ctags) file. +# 1: List symbol names matching this word. +# 2: The tag file to list symbol names from. +# 3: A prefix to be added to each listed symbol name (optional). +# 4: A suffix to be appended to each listed symbol name (optional). +__git_match_ctag () { + awk -v pfx="${3-}" -v sfx="${4-}" " + /^${1//\//\\/}/ { print pfx \$1 sfx } + " "$2" +} + +# Complete symbol names from a tag file. +# Usage: __git_complete_symbol [<option>]... +# --tags=<file>: The tag file to list symbol names from instead of the +# default "tags". +# --pfx=<prefix>: A prefix to be added to each symbol name. +# --cur=<word>: The current symbol name to be completed. Defaults to +# the current word to be completed. +# --sfx=<suffix>: A suffix to be appended to each symbol name instead +# of the default space. +__git_complete_symbol () { + local tags=tags pfx="" cur_="${cur-}" sfx=" " + + while test $# != 0; do + case "$1" in + --tags=*) tags="${1##--tags=}" ;; + --pfx=*) pfx="${1##--pfx=}" ;; + --cur=*) cur_="${1##--cur=}" ;; + --sfx=*) sfx="${1##--sfx=}" ;; + *) return 1 ;; + esac + shift + done + + if test -r "$tags"; then + __gitcomp_direct "$(__git_match_ctag "$cur_" "$tags" "$pfx" "$sfx")" + fi } _git_grep () @@ -1392,14 +1606,11 @@ _git_grep () case "$cword,$prev" in 2,*|*,-*) - if test -r tags; then - __gitcomp_nl "$(__git_match_ctag "$cur" tags)" - return - fi + __git_complete_symbol && return ;; esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_help () @@ -1500,12 +1711,25 @@ __git_log_date_formats="relative iso8601 rfc2822 short local default raw" _git_log () { __git_has_doubledash && return + __git_find_repo_path - local g="$(git rev-parse --git-dir 2>/dev/null)" local merge="" - if [ -f "$g/MERGE_HEAD" ]; then + if [ -f "$__git_repo_path/MERGE_HEAD" ]; then merge="--merge" fi + case "$prev,$cur" in + -L,:*:*) + return # fall back to Bash filename completion + ;; + -L,:*) + __git_complete_symbol --cur="${cur#:}" --sfx=":" + return + ;; + -G,*|-S,*) + __git_complete_symbol + return + ;; + esac case "$cur" in --pretty=*|--format=*) __gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases) @@ -1551,6 +1775,21 @@ _git_log () " return ;; + -L:*:*) + return # fall back to Bash filename completion + ;; + -L:*) + __git_complete_symbol --cur="${cur#-L:}" --sfx=":" + return + ;; + -G*) + __git_complete_symbol --pfx="-G" --cur="${cur#-G}" + return + ;; + -S*) + __git_complete_symbol --pfx="-S" --cur="${cur#-S}" + return + ;; esac __git_complete_revlist } @@ -1573,7 +1812,7 @@ _git_merge () --rerere-autoupdate --no-rerere-autoupdate --abort --continue" return esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_mergetool () @@ -1598,7 +1837,7 @@ _git_merge_base () return ;; esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_mv () @@ -1636,7 +1875,7 @@ _git_notes () ,*) case "$prev" in --ref) - __gitcomp_nl "$(__git_refs)" + __git_complete_refs ;; *) __gitcomp "$subcommands --ref" @@ -1645,7 +1884,7 @@ _git_notes () ;; add,--reuse-message=*|append,--reuse-message=*|\ add,--reedit-message=*|append,--reedit-message=*) - __gitcomp_nl "$(__git_refs)" "" "${cur#*=}" + __git_complete_refs --cur="${cur#*=}" ;; add,--*|append,--*) __gitcomp '--file= --message= --reedit-message= @@ -1664,7 +1903,7 @@ _git_notes () -m|-F) ;; *) - __gitcomp_nl "$(__git_refs)" + __git_complete_refs ;; esac ;; @@ -1702,10 +1941,10 @@ __git_complete_force_with_lease () --*=) ;; *:*) - __gitcomp_nl "$(__git_refs)" "" "${cur_#*:}" + __git_complete_refs --cur="${cur_#*:}" ;; *) - __gitcomp_nl "$(__git_refs)" "" "$cur_" + __git_complete_refs --cur="$cur_" ;; esac } @@ -1750,11 +1989,12 @@ _git_push () _git_rebase () { - local dir="$(__gitdir)" - if [ -f "$dir"/rebase-merge/interactive ]; then + __git_find_repo_path + if [ -f "$__git_repo_path"/rebase-merge/interactive ]; then __gitcomp "--continue --skip --abort --quit --edit-todo" return - elif [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then + elif [ -d "$__git_repo_path"/rebase-apply ] || \ + [ -d "$__git_repo_path"/rebase-merge ]; then __gitcomp "--continue --skip --abort --quit" return fi @@ -1780,7 +2020,7 @@ _git_rebase () return esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_reflog () @@ -1791,7 +2031,7 @@ _git_reflog () if [ -z "$subcommand" ]; then __gitcomp "$subcommands" else - __gitcomp_nl "$(__git_refs)" + __git_complete_refs fi } @@ -1802,9 +2042,7 @@ _git_send_email () { case "$prev" in --to|--cc|--bcc|--from) - __gitcomp " - $(git --git-dir="$(__gitdir)" send-email --dump-aliases 2>/dev/null) - " + __gitcomp "$(__git send-email --dump-aliases)" return ;; esac @@ -1834,9 +2072,7 @@ _git_send_email () return ;; --to=*|--cc=*|--bcc=*|--from=*) - __gitcomp " - $(git --git-dir="$(__gitdir)" send-email --dump-aliases 2>/dev/null) - " "" "${cur#--*=}" + __gitcomp "$(__git send-email --dump-aliases)" "" "${cur#--*=}" return ;; --*) @@ -1930,7 +2166,7 @@ __git_config_get_set_variables () c=$((--c)) done - git --git-dir="$(__gitdir)" config $config_file --name-only --list 2>/dev/null + __git config $config_file --name-only --list } _git_config () @@ -1941,7 +2177,7 @@ _git_config () return ;; branch.*.merge) - __gitcomp_nl "$(__git_refs)" + __git_complete_refs return ;; branch.*.rebase) @@ -1965,9 +2201,8 @@ _git_config () remote.*.push) local remote="${prev#remote.}" remote="${remote%.push}" - __gitcomp_nl "$(git --git-dir="$(__gitdir)" \ - for-each-ref --format='%(refname):%(refname)' \ - refs/heads)" + __gitcomp_nl "$(__git for-each-ref \ + --format='%(refname):%(refname)' refs/heads)" return ;; pull.twohead|pull.octopus) @@ -2046,7 +2281,7 @@ _git_config () ;; branch.*) local pfx="${cur%.*}." cur_="${cur#*.}" - __gitcomp_nl "$(__git_heads)" "$pfx" "$cur_" "." + __gitcomp_direct "$(__git_heads "$pfx" "$cur_" ".")" __gitcomp_nl_append $'autosetupmerge\nautosetuprebase\n' "$pfx" "$cur_" return ;; @@ -2101,14 +2336,24 @@ _git_config () esac __gitcomp " add.ignoreErrors + advice.amWorkDir advice.commitBeforeMerge advice.detachedHead advice.implicitIdentity - advice.pushNonFastForward + 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 @@ -2153,19 +2398,26 @@ _git_config () 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.compression core.createObject core.deltaBaseCacheLimit @@ -2175,6 +2427,8 @@ _git_config () core.fileMode core.fsyncobjectfiles core.gitProxy + core.hideDotFiles + core.hooksPath core.ignoreStat core.ignorecase core.logAllRefUpdates @@ -2182,20 +2436,30 @@ _git_config () 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 @@ -2227,15 +2491,19 @@ _git_config () 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 @@ -2373,7 +2641,10 @@ _git_config () sendemail.suppressfrom sendemail.thread sendemail.to + sendemail.tocmd sendemail.validate + sendemail.smtpbatchsize + sendemail.smtprelogindelay showbranch.default status.relativePaths status.showUntrackedFiles @@ -2453,7 +2724,7 @@ _git_replace () return ;; esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_rerere () @@ -2477,13 +2748,13 @@ _git_reset () return ;; esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_revert () { - local dir="$(__gitdir)" - if [ -f "$dir"/REVERT_HEAD ]; then + __git_find_repo_path + if [ -f "$__git_repo_path"/REVERT_HEAD ]; then __gitcomp "--continue --quit --abort" return fi @@ -2496,7 +2767,7 @@ _git_revert () return ;; esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_rm () @@ -2576,7 +2847,7 @@ _git_show_branch () _git_stash () { local save_opts='--all --keep-index --no-keep-index --quiet --patch --include-untracked' - local subcommands='save list show apply clear drop pop create branch' + local subcommands='push save list show apply clear drop pop create branch' local subcommand="$(__git_find_on_cmdline "$subcommands")" if [ -z "$subcommand" ]; then case "$cur" in @@ -2591,6 +2862,9 @@ _git_stash () esac else case "$subcommand,$cur" in + push,--*) + __gitcomp "$save_opts --message" + ;; save,--*) __gitcomp "$save_opts" ;; @@ -2604,14 +2878,14 @@ _git_stash () ;; branch,*) if [ $cword -eq 3 ]; then - __gitcomp_nl "$(__git_refs)"; + __git_complete_refs else - __gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \ + __gitcomp_nl "$(__git stash list \ | sed -n -e 's/:.*//p')" fi ;; show,*|apply,*|drop,*|pop,*) - __gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \ + __gitcomp_nl "$(__git stash list \ | sed -n -e 's/:.*//p')" ;; *) @@ -2771,7 +3045,7 @@ _git_tag () i="${words[c]}" case "$i" in -d|-v) - __gitcomp_nl "$(__git_tags)" + __gitcomp_direct "$(__git_tags "" "$cur" " ")" return ;; -f) @@ -2786,11 +3060,11 @@ _git_tag () ;; -*|tag) if [ $f = 1 ]; then - __gitcomp_nl "$(__git_tags)" + __gitcomp_direct "$(__git_tags "" "$cur" " ")" fi ;; *) - __gitcomp_nl "$(__git_refs)" + __git_complete_refs ;; esac @@ -2799,7 +3073,7 @@ _git_tag () __gitcomp " --list --delete --verify --annotate --message --file --sign --cleanup --local-user --force --column --sort= - --contains --points-at --merged --no-merged --create-reflog + --contains --no-contains --points-at --merged --no-merged --create-reflog " ;; esac @@ -2838,7 +3112,8 @@ _git_worktree () __git_main () { - local i c=1 command __git_dir + local i c=1 command __git_dir __git_repo_path + local __git_C_args C_args_count=0 while [ $c -lt $cword ]; do i="${words[c]}" @@ -2848,6 +3123,10 @@ __git_main () --bare) __git_dir="." ;; --help) command="help"; break ;; -c|--work-tree|--namespace) ((c++)) ;; + -C) __git_C_args[C_args_count++]=-C + ((c++)) + __git_C_args[C_args_count++]="${words[c]}" + ;; -*) ;; *) command="$i"; break ;; esac @@ -2855,6 +3134,17 @@ __git_main () done if [ -z "$command" ]; then + case "$prev" in + --git-dir|-C|--work-tree) + # these need a path argument, let's fall back to + # Bash filename completion + return + ;; + -c|--namespace) + # we don't support completing these options' arguments + return + ;; + esac case "$cur" in --*) __gitcomp " --paginate @@ -2880,13 +3170,13 @@ __git_main () fi local completion_func="_git_${command//-/_}" - declare -f $completion_func >/dev/null && $completion_func && return + declare -f $completion_func >/dev/null 2>/dev/null && $completion_func && return local expansion=$(__git_aliased_command "$command") if [ -n "$expansion" ]; then words[1]=$expansion completion_func="_git_${expansion//-/_}" - declare -f $completion_func >/dev/null && $completion_func + declare -f $completion_func >/dev/null 2>/dev/null && $completion_func fi } @@ -2894,9 +3184,11 @@ __gitk_main () { __git_has_doubledash && return - local g="$(__gitdir)" + local __git_repo_path + __git_find_repo_path + local merge="" - if [ -f "$g/MERGE_HEAD" ]; then + if [ -f "$__git_repo_path/MERGE_HEAD" ]; then merge="--merge" fi case "$cur" in @@ -2943,6 +3235,15 @@ if [[ -n ${ZSH_VERSION-} ]]; then esac } + __gitcomp_direct () + { + emulate -L zsh + + local IFS=$'\n' + compset -P '*[=:]' + compadd -Q -- ${=1} && _ret=0 + } + __gitcomp_nl () { emulate -L zsh diff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh index e25541308a..c3521fbfc4 100644 --- a/contrib/completion/git-completion.zsh +++ b/contrib/completion/git-completion.zsh @@ -67,6 +67,15 @@ __gitcomp () esac } +__gitcomp_direct () +{ + emulate -L zsh + + local IFS=$'\n' + compset -P '*[=:]' + compadd -Q -- ${=1} && _ret=0 +} + __gitcomp_nl () { emulate -L zsh diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 97eacd7832..c6cbef38c2 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -82,6 +82,7 @@ # contains relative to newer annotated tag (v1.6.3.2~35) # branch relative to newer tag or branch (master~4) # describe relative to older annotated tag (v1.6.3.1-13-gdd42c2f) +# tag relative to any older tag (v1.6.3.1-13-gdd42c2f) # default exactly matching tag # # If you would like a colored hint about the current dirty state, set @@ -443,6 +444,8 @@ __git_ps1 () git describe --contains HEAD ;; (branch) git describe --contains --all HEAD ;; + (tag) + git describe --tags HEAD ;; (describe) git describe HEAD ;; (* | default) diff --git a/contrib/contacts/git-contacts b/contrib/contacts/git-contacts index dbe2abf277..85ad732fc0 100755 --- a/contrib/contacts/git-contacts +++ b/contrib/contacts/git-contacts @@ -11,7 +11,7 @@ use IPC::Open2; my $since = '5-years-ago'; my $min_percent = 10; -my $labels_rx = qr/Signed-off-by|Reviewed-by|Acked-by|Cc/i; +my $labels_rx = qr/Signed-off-by|Reviewed-by|Acked-by|Cc|Reported-by/i; my %seen; sub format_contact { diff --git a/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c b/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c index 2a317fca44..d389bfadce 100644 --- a/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c +++ b/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c @@ -13,8 +13,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program; if not, see <http://www.gnu.org/licenses/>. */ /* diff --git a/contrib/credential/libsecret/git-credential-libsecret.c b/contrib/credential/libsecret/git-credential-libsecret.c index 4c56979d8a..e6598b6383 100644 --- a/contrib/credential/libsecret/git-credential-libsecret.c +++ b/contrib/credential/libsecret/git-credential-libsecret.c @@ -14,8 +14,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program; if not, see <http://www.gnu.org/licenses/>. */ /* @@ -104,7 +103,7 @@ static int keyring_get(struct credential *c) items = secret_service_search_sync(service, SECRET_SCHEMA_COMPAT_NETWORK, attributes, - SECRET_SEARCH_LOAD_SECRETS, + SECRET_SEARCH_LOAD_SECRETS | SECRET_SEARCH_UNLOCK, NULL, &error); g_hash_table_unref(attributes); diff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c index 006134043a..86518cd93d 100644 --- a/contrib/credential/wincred/git-credential-wincred.c +++ b/contrib/credential/wincred/git-credential-wincred.c @@ -94,6 +94,12 @@ static WCHAR *wusername, *password, *protocol, *host, *path, target[1024]; static void write_item(const char *what, LPCWSTR wbuf, int wlen) { char *buf; + + if (!wbuf || !wlen) { + printf("%s=\n", what); + return; + } + int len = WideCharToMultiByte(CP_UTF8, 0, wbuf, wlen, NULL, 0, NULL, FALSE); buf = xmalloc(len); @@ -160,7 +166,7 @@ static int match_part_last(LPCWSTR *ptarget, LPCWSTR want, LPCWSTR delim) static int match_cred(const CREDENTIALW *cred) { LPCWSTR target = cred->TargetName; - if (wusername && wcscmp(wusername, cred->UserName)) + if (wusername && wcscmp(wusername, cred->UserName ? cred->UserName : L"")) return 0; return match_part(&target, L"git", L":") && @@ -183,7 +189,7 @@ static void get_credential(void) for (i = 0; i < num_creds; ++i) if (match_cred(creds[i])) { write_item("username", creds[i]->UserName, - wcslen(creds[i]->UserName)); + creds[i]->UserName ? wcslen(creds[i]->UserName) : 0); write_item("password", (LPCWSTR)creds[i]->CredentialBlob, creds[i]->CredentialBlobSize / sizeof(WCHAR)); diff --git a/contrib/diff-highlight/.gitignore b/contrib/diff-highlight/.gitignore new file mode 100644 index 0000000000..c07454824e --- /dev/null +++ b/contrib/diff-highlight/.gitignore @@ -0,0 +1,2 @@ +shebang.perl +diff-highlight diff --git a/contrib/diff-highlight/diff-highlight b/contrib/diff-highlight/DiffHighlight.pm index 81bd8040e3..663992e530 100755..100644 --- a/contrib/diff-highlight/diff-highlight +++ b/contrib/diff-highlight/DiffHighlight.pm @@ -1,4 +1,4 @@ -#!/usr/bin/perl +package DiffHighlight; use 5.008; use warnings FATAL => 'all'; @@ -29,13 +29,14 @@ my @removed; my @added; my $in_hunk; -# Some scripts may not realize that SIGPIPE is being ignored when launching the -# pager--for instance scripts written in Python. -$SIG{PIPE} = 'DEFAULT'; +our $line_cb = sub { print @_ }; +our $flush_cb = sub { local $| = 1 }; + +sub handle_line { + local $_ = shift; -while (<>) { if (!$in_hunk) { - print; + $line_cb->($_); $in_hunk = /^$GRAPH*$COLOR*\@\@ /; } elsif (/^$GRAPH*$COLOR*-/) { @@ -49,7 +50,7 @@ while (<>) { @removed = (); @added = (); - print; + $line_cb->($_); $in_hunk = /^$GRAPH*$COLOR*[\@ ]/; } @@ -62,15 +63,22 @@ while (<>) { # place to flush. Flushing on a blank line is a heuristic that # happens to match git-log output. if (!length) { - local $| = 1; + $flush_cb->(); } } -# Flush any queued hunk (this can happen when there is no trailing context in -# the final diff of the input). -show_hunk(\@removed, \@added); +sub flush { + # Flush any queued hunk (this can happen when there is no trailing + # context in the final diff of the input). + show_hunk(\@removed, \@added); +} -exit 0; +sub highlight_stdin { + while (<STDIN>) { + handle_line($_); + } + flush(); +} # Ideally we would feed the default as a human-readable color to # git-config as the fallback value. But diff-highlight does @@ -88,7 +96,7 @@ sub show_hunk { # If one side is empty, then there is nothing to compare or highlight. if (!@$a || !@$b) { - print @$a, @$b; + $line_cb->(@$a, @$b); return; } @@ -97,17 +105,17 @@ sub show_hunk { # stupid, and only handle multi-line hunks that remove and add the same # number of lines. if (@$a != @$b) { - print @$a, @$b; + $line_cb->(@$a, @$b); return; } my @queue; for (my $i = 0; $i < @$a; $i++) { my ($rm, $add) = highlight_pair($a->[$i], $b->[$i]); - print $rm; + $line_cb->($rm); push @queue, $add; } - print @queue; + $line_cb->(@queue); } sub highlight_pair { diff --git a/contrib/diff-highlight/Makefile b/contrib/diff-highlight/Makefile index 9018724524..f2be7cc924 100644 --- a/contrib/diff-highlight/Makefile +++ b/contrib/diff-highlight/Makefile @@ -1,5 +1,23 @@ -# nothing to build -all: +all: diff-highlight -test: +PERL_PATH = /usr/bin/perl +-include ../../config.mak + +PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH)) + +diff-highlight: shebang.perl DiffHighlight.pm diff-highlight.perl + cat $^ >$@+ + chmod +x $@+ + mv $@+ $@ + +shebang.perl: FORCE + @echo '#!$(PERL_PATH_SQ)' >$@+ + @cmp $@+ $@ >/dev/null 2>/dev/null || mv $@+ $@ + +test: all $(MAKE) -C t + +clean: + $(RM) diff-highlight + +.PHONY: FORCE diff --git a/contrib/diff-highlight/README b/contrib/diff-highlight/README index 836b97a730..d4c2343175 100644 --- a/contrib/diff-highlight/README +++ b/contrib/diff-highlight/README @@ -99,6 +99,36 @@ newHighlight = "black #aaffaa" --------------------------------------------- +Using diff-highlight as a module +-------------------------------- + +If you want to pre- or post- process the highlighted lines as part of +another perl script, you can use the DiffHighlight module. You can +either "require" it or just cat the module together with your script (to +avoid run-time dependencies). + +Your script may set up one or more of the following variables: + + - $DiffHighlight::line_cb - this should point to a function which is + called whenever DiffHighlight has lines (which may contain + highlights) to output. The default function prints each line to + stdout. Note that the function may be called with multiple lines. + + - $DiffHighlight::flush_cb - this should point to a function which + flushes the output (because DiffHighlight believes it has completed + processing a logical chunk of input). The default function flushes + stdout. + +The script may then feed lines, one at a time, to DiffHighlight::handle_line(). +When lines are done processing, they will be fed to $line_cb. Note that +DiffHighlight may queue up many input lines (to analyze a whole hunk) +before calling $line_cb. After providing all lines, call +DiffHighlight::flush() to flush any unprocessed lines. + +If you just want to process stdin, DiffHighlight::highlight_stdin() +is a convenience helper which will loop and flush for you. + + Bugs ---- diff --git a/contrib/diff-highlight/diff-highlight.perl b/contrib/diff-highlight/diff-highlight.perl new file mode 100644 index 0000000000..9b3e9c1f4d --- /dev/null +++ b/contrib/diff-highlight/diff-highlight.perl @@ -0,0 +1,8 @@ +package main; + +# Some scripts may not realize that SIGPIPE is being ignored when launching the +# pager--for instance scripts written in Python. +$SIG{PIPE} = 'DEFAULT'; + +DiffHighlight::highlight_stdin(); +exit 0; diff --git a/contrib/emacs/git-blame.el b/contrib/emacs/git-blame.el index e671f6c1c6..510e0f7103 100644 --- a/contrib/emacs/git-blame.el +++ b/contrib/emacs/git-blame.el @@ -25,9 +25,8 @@ ;; PURPOSE. See the GNU General Public License for more details. ;; You should have received a copy of the GNU General Public -;; License along with this program; if not, write to the Free -;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, -;; MA 02111-1307 USA +;; License along with this program; if not, see +;; <http://www.gnu.org/licenses/>. ;; http://www.fsf.org/copyleft/gpl.html diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index 5ffc506f6d..97919f2d73 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -15,9 +15,8 @@ ;; PURPOSE. See the GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public -;; License along with this program; if not, write to the Free -;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, -;; MA 02111-1307 USA +;; License along with this program; if not, see +;; <http://www.gnu.org/licenses/>. ;;; Commentary: diff --git a/contrib/examples/git-merge.sh b/contrib/examples/git-merge.sh index ee99f1a4ee..932e78dbfe 100755 --- a/contrib/examples/git-merge.sh +++ b/contrib/examples/git-merge.sh @@ -399,7 +399,7 @@ case "$allow_fast_forward,$#,$common,$no_commit" in ?,1,"$1",*) # If head can reach all the merge then we are up to date. # but first the most common case of merging one remote. - finish_up_to_date "Already up-to-date." + finish_up_to_date "Already up to date." exit 0 ;; t,1,"$head",*) @@ -459,7 +459,7 @@ t,1,"$head",*) done if test "$up_to_date" = t then - finish_up_to_date "Already up-to-date. Yeeah!" + finish_up_to_date "Already up to date. Yeeah!" exit 0 fi ;; diff --git a/contrib/examples/git-resolve.sh b/contrib/examples/git-resolve.sh index 70fdc27b72..3099dc851a 100755 --- a/contrib/examples/git-resolve.sh +++ b/contrib/examples/git-resolve.sh @@ -41,7 +41,7 @@ fi case "$common" in "$merge") - echo "Already up-to-date. Yeeah!" + echo "Already up to date. Yeeah!" dropheads exit 0 ;; diff --git a/contrib/fast-import/import-directories.perl b/contrib/fast-import/import-directories.perl index 4dec1f18e4..a16f79cfdc 100755 --- a/contrib/fast-import/import-directories.perl +++ b/contrib/fast-import/import-directories.perl @@ -14,8 +14,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# along with this program; if not, see <http://www.gnu.org/licenses/>. # # ------------------------------------------------------------------------ diff --git a/contrib/git-jump/README b/contrib/git-jump/README index 225e3f0954..4484bda410 100644 --- a/contrib/git-jump/README +++ b/contrib/git-jump/README @@ -63,6 +63,9 @@ git jump grep foo_bar # same as above, but case-insensitive; you can give # arbitrary grep options git jump grep -i foo_bar + +# use the silver searcher for git jump grep +git config jump.grepCmd "ag --column" -------------------------------------------------- @@ -92,3 +95,10 @@ how to activate it. The shell snippets to generate the quickfix lines will almost certainly choke on filenames with exotic characters (like newlines). + +Contributing +------------ + +Bug fixes, bug reports, and feature requests should be discussed on the +Git mailing list <git@vger.kernel.org>, and cc'd to the git-jump +maintainer, Jeff King <peff@peff.net>. diff --git a/contrib/git-jump/git-jump b/contrib/git-jump/git-jump index 427f206a45..80ab0590bc 100755 --- a/contrib/git-jump/git-jump +++ b/contrib/git-jump/git-jump @@ -11,7 +11,8 @@ diff: elements are diff hunks. Arguments are given to diff. merge: elements are merge conflicts. Arguments are ignored. -grep: elements are grep hits. Arguments are given to grep. +grep: elements are grep hits. Arguments are given to git grep or, if + configured, to the command in `jump.grepCmd`. ws: elements are whitespace errors. Arguments are given to diff --check. EOF @@ -50,7 +51,9 @@ mode_merge() { # but let's clean up extra whitespace, so they look better if the # editor shows them to us in the status bar. mode_grep() { - git grep -n "$@" | + cmd=$(git config jump.grepCmd) + test -n "$cmd" || cmd="git grep -n" + $cmd "$@" | perl -pe ' s/[ \t]+/ /g; s/^ *//; diff --git a/contrib/git-resurrect.sh b/contrib/git-resurrect.sh index d7e97bbc76..8c171dd959 100755 --- a/contrib/git-resurrect.sh +++ b/contrib/git-resurrect.sh @@ -26,13 +26,13 @@ n,dry-run don't recreate the branch" . git-sh-setup search_reflog () { - sed -ne 's~^\([^ ]*\) .*\tcheckout: moving from '"$1"' .*~\1~p' \ + sed -ne 's~^\([^ ]*\) .* checkout: moving from '"$1"' .*~\1~p' \ < "$GIT_DIR"/logs/HEAD } search_reflog_merges () { git rev-parse $( - sed -ne 's~^[^ ]* \([^ ]*\) .*\tmerge '"$1"':.*~\1^2~p' \ + sed -ne 's~^[^ ]* \([^ ]*\) .* merge '"$1"':.*~\1^2~p' \ < "$GIT_DIR"/logs/HEAD ) } diff --git a/contrib/hg-to-git/hg-to-git.py b/contrib/hg-to-git/hg-to-git.py index 60dec86d37..de3f81667e 100755 --- a/contrib/hg-to-git/hg-to-git.py +++ b/contrib/hg-to-git/hg-to-git.py @@ -15,8 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program; if not, see <http://www.gnu.org/licenses/>. """ import os, os.path, sys diff --git a/contrib/hooks/multimail/git_multimail.py b/contrib/hooks/multimail/git_multimail.py index c7f86403cf..73fdda6b14 100755 --- a/contrib/hooks/multimail/git_multimail.py +++ b/contrib/hooks/multimail/git_multimail.py @@ -2964,7 +2964,7 @@ class StaticRecipientsEnvironmentMixin(Environment): class CLIRecipientsEnvironmentMixin(Environment): - """Mixin storing recipients information comming from the + """Mixin storing recipients information coming from the command-line.""" def __init__(self, cli_recipients=None, **kw): diff --git a/contrib/mw-to-git/Git/Mediawiki.pm b/contrib/mw-to-git/Git/Mediawiki.pm index d13c4dfa7d..917d9e2d32 100644 --- a/contrib/mw-to-git/Git/Mediawiki.pm +++ b/contrib/mw-to-git/Git/Mediawiki.pm @@ -2,6 +2,7 @@ package Git::Mediawiki; use 5.008; use strict; +use POSIX; use Git; BEGIN { @@ -52,7 +53,7 @@ sub smudge_filename { $filename =~ s/ /_/g; # Decode forbidden characters encoded in clean_filename $filename =~ s/_%_([0-9a-fA-F][0-9a-fA-F])/sprintf('%c', hex($1))/ge; - return $filename; + return substr($filename, 0, NAME_MAX-length('.mw')); } sub connect_maybe { diff --git a/contrib/mw-to-git/git-remote-mediawiki.perl b/contrib/mw-to-git/git-remote-mediawiki.perl index 41e74fba1e..af9cbc9d0f 100755 --- a/contrib/mw-to-git/git-remote-mediawiki.perl +++ b/contrib/mw-to-git/git-remote-mediawiki.perl @@ -63,6 +63,11 @@ chomp(@tracked_pages); my @tracked_categories = split(/[ \n]/, run_git("config --get-all remote.${remotename}.categories")); chomp(@tracked_categories); +# Just like @tracked_categories, but for MediaWiki namespaces. +my @tracked_namespaces = split(/[ \n]/, run_git("config --get-all remote.${remotename}.namespaces")); +for (@tracked_namespaces) { s/_/ /g; } +chomp(@tracked_namespaces); + # Import media files on pull my $import_media = run_git("config --get --bool remote.${remotename}.mediaimport"); chomp($import_media); @@ -256,6 +261,32 @@ sub get_mw_tracked_categories { return; } +sub get_mw_tracked_namespaces { + my $pages = shift; + foreach my $local_namespace (sort @tracked_namespaces) { + my $namespace_id; + if ($local_namespace eq "(Main)") { + $namespace_id = 0; + } else { + $namespace_id = get_mw_namespace_id($local_namespace); + } + # virtual namespaces don't support allpages + next if !defined($namespace_id) || $namespace_id < 0; + my $mw_pages = $mediawiki->list( { + action => 'query', + list => 'allpages', + apnamespace => $namespace_id, + aplimit => 'max' } ) + || die $mediawiki->{error}->{code} . ': ' + . $mediawiki->{error}->{details} . "\n"; + print {*STDERR} "$#{$mw_pages} found in namespace $local_namespace ($namespace_id)\n"; + foreach my $page (@{$mw_pages}) { + $pages->{$page->{title}} = $page; + } + } + return; +} + sub get_mw_all_pages { my $pages = shift; # No user-provided list, get the list of pages from the API. @@ -319,6 +350,10 @@ sub get_mw_pages { $user_defined = 1; get_mw_tracked_categories(\%pages); } + if (@tracked_namespaces) { + $user_defined = 1; + get_mw_tracked_namespaces(\%pages); + } if (!$user_defined) { get_mw_all_pages(\%pages); } @@ -857,7 +892,7 @@ sub mw_import_revids { my $n = 0; my $n_actual = 0; - my $last_timestamp = 0; # Placeholer in case $rev->timestamp is undefined + my $last_timestamp = 0; # Placeholder in case $rev->timestamp is undefined foreach my $pagerevid (@{$revision_ids}) { # Count page even if we skip it, since we display @@ -1308,7 +1343,8 @@ sub get_mw_namespace_id { my $id; if (!defined $ns) { - print {*STDERR} "No such namespace ${name} on MediaWiki.\n"; + my @namespaces = map { s/ /_/g; $_; } sort keys %namespace_id; + print {*STDERR} "No such namespace ${name} on MediaWiki, known namespaces: @namespaces\n"; $ns = {is_namespace => 0}; $namespace_id{$name} = $ns; } diff --git a/contrib/mw-to-git/t/README b/contrib/mw-to-git/t/README index 03f6ee5d72..2ee34be7e4 100644 --- a/contrib/mw-to-git/t/README +++ b/contrib/mw-to-git/t/README @@ -121,4 +121,4 @@ How to write a new test Please, follow the standards given by git. See git/t/README. New file should be named as t936[0-9]-*.sh. -Be sure to reset your wiki regulary with the function `wiki_reset`. +Be sure to reset your wiki regularly with the function `wiki_reset`. diff --git a/contrib/persistent-https/README b/contrib/persistent-https/README index f784dd2e66..7c4cd8d257 100644 --- a/contrib/persistent-https/README +++ b/contrib/persistent-https/README @@ -35,6 +35,16 @@ to use persistent-https: [url "persistent-http"] insteadof = http +You may also want to allow the use of the persistent-https helper for +submodule URLs (since any https URLs pointing to submodules will be +rewritten, and Git's out-of-the-box defaults forbid submodules from +using unknown remote helpers): + +[protocol "persistent-https"] + allow = always +[protocol "persistent-http"] + allow = always + ##################################################################### # BUILDING FROM SOURCE diff --git a/contrib/rerere-train.sh b/contrib/rerere-train.sh index 52ad9e41fb..eeee45dd34 100755 --- a/contrib/rerere-train.sh +++ b/contrib/rerere-train.sh @@ -3,10 +3,56 @@ # Prime rerere database from existing merge commits me=rerere-train -USAGE="$me rev-list-args" +USAGE=$(cat <<-EOF +usage: $me [--overwrite] <rev-list-args> + + -h, --help show the help + -o, --overwrite overwrite any existing rerere cache +EOF +) SUBDIRECTORY_OK=Yes -OPTIONS_SPEC= + +overwrite=0 + +while test $# -gt 0 +do + opt="$1" + case "$opt" in + -h|--help) + echo "$USAGE" + exit 0 + ;; + -o|--overwrite) + overwrite=1 + shift + break + ;; + --) + shift + break + ;; + *) + break + ;; + esac +done + +# Overwrite or help options are not valid except as first arg +for opt in "$@" +do + case "$opt" in + -h|--help) + echo "$USAGE" + exit 0 + ;; + -o|--overwrite) + echo "$USAGE" + exit 0 + ;; + esac +done + . "$(git --exec-path)/git-sh-setup" require_work_tree cd_to_toplevel @@ -34,6 +80,10 @@ do # Cleanly merges continue fi + if test $overwrite = 1 + then + git rerere forget . + fi if test -s "$GIT_DIR/MERGE_RR" then git show -s --pretty=format:"Learning from %h %s" "$commit" diff --git a/contrib/subtree/Makefile b/contrib/subtree/Makefile index 6afa9aafdf..5c6cc4ab2c 100644 --- a/contrib/subtree/Makefile +++ b/contrib/subtree/Makefile @@ -19,15 +19,27 @@ htmldir ?= $(prefix)/share/doc/git-doc INSTALL ?= install RM ?= rm -f -ASCIIDOC = asciidoc -XMLTO = xmlto +ASCIIDOC = asciidoc +ASCIIDOC_CONF = -f ../../Documentation/asciidoc.conf +ASCIIDOC_HTML = xhtml11 +ASCIIDOC_DOCBOOK = docbook +ASCIIDOC_EXTRA = +XMLTO = xmlto + +ifdef USE_ASCIIDOCTOR +ASCIIDOC = asciidoctor +ASCIIDOC_CONF = +ASCIIDOC_HTML = xhtml5 +ASCIIDOC_DOCBOOK = docbook45 +ASCIIDOC_EXTRA += -I../../Documentation -rasciidoctor-extensions +ASCIIDOC_EXTRA += -alitdd='&\#x2d;&\#x2d;' +endif ifndef SHELL_PATH SHELL_PATH = /bin/sh endif SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) -ASCIIDOC_CONF = ../../Documentation/asciidoc.conf MANPAGE_XSL = ../../Documentation/manpage-normal.xsl GIT_SUBTREE_SH := git-subtree.sh @@ -65,12 +77,12 @@ $(GIT_SUBTREE_DOC): $(GIT_SUBTREE_XML) $(XMLTO) -m $(MANPAGE_XSL) man $^ $(GIT_SUBTREE_XML): $(GIT_SUBTREE_TXT) - $(ASCIIDOC) -b docbook -d manpage -f $(ASCIIDOC_CONF) \ - -agit_version=$(GIT_VERSION) $^ + $(ASCIIDOC) -b $(ASCIIDOC_DOCBOOK) -d manpage $(ASCIIDOC_CONF) \ + -agit_version=$(GIT_VERSION) $(ASCIIDOC_EXTRA) $^ $(GIT_SUBTREE_HTML): $(GIT_SUBTREE_TXT) - $(ASCIIDOC) -b xhtml11 -d manpage -f $(ASCIIDOC_CONF) \ - -agit_version=$(GIT_VERSION) $^ + $(ASCIIDOC) -b $(ASCIIDOC_HTML) -d manpage $(ASCIIDOC_CONF) \ + -agit_version=$(GIT_VERSION) $(ASCIIDOC_EXTRA) $^ $(GIT_SUBTREE_TEST): $(GIT_SUBTREE) cp $< $@ diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index 3c87ebaf57..d05c613c97 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -253,7 +253,7 @@ test_expect_success 'merge the added subproj again, should do nothing' ' # this shouldn not actually do anything, since FETCH_HEAD # is already a parent result=$(git merge -s ours -m "merge -s -ours" FETCH_HEAD) && - check_equal "${result}" "Already up-to-date." + check_equal "${result}" "Already up to date." ) ' diff --git a/contrib/workdir/.gitattributes b/contrib/workdir/.gitattributes new file mode 100644 index 0000000000..1f78c5d1bd --- /dev/null +++ b/contrib/workdir/.gitattributes @@ -0,0 +1 @@ +/git-new-workdir eol=lf |