From e8943e7007d27143d17cf66acf659e92fcea1fe9 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 4 Jun 2016 16:57:48 +0000 Subject: 38609: vcs_info quilt: Factor out a helper function. No functional change. --- Functions/VCS_Info/VCS_INFO_quilt | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'Functions/VCS_Info') diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index c3c3d864d..e31deb0bd 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -80,6 +80,23 @@ function VCS_INFO_quilt-dirfind() { return ${ret} } +# This function takes as an argument a filename of a patch and sets $REPLY to +# a single-line "subject", or unsets it if no subject could be extracted. +function VCS_INFO_quilt-patch2subject() { + local line + if [[ -f "$1" ]] && read -r line < "$1"; then + if [[ $line != (#b)(---|Index:)* ]]; then + REPLY=$line + else + unset REPLY + return 0 + fi + else + unset REPLY + return 1 + fi +} + function VCS_INFO_quilt() { emulate -L zsh setopt extendedglob @@ -147,27 +164,19 @@ function VCS_INFO_quilt() { if [[ -n $patches ]]; then () { - local i line + local i for ((i=1; i<=$#applied; i++)); do - if [[ -f "$patches/$applied[$i]" ]] && - read -r line < "$patches/$applied[$i]" && - [[ $line != (#b)(---|Index:)* ]] && - true - ; + if VCS_INFO_quilt-patch2subject "$patches/$applied[$i]" && (( $+REPLY )) then - applied[$i]+=" $line" + applied[$i]+=" $REPLY" else applied[$i]+=" ?" fi done for ((i=1; i<=$#unapplied; i++)); do - if [[ -f "$patches/$unapplied[$i]" ]] && - read -r line < "$patches/$unapplied[$i]" && - [[ $line != (#b)(---|Index:)* ]] && - true - ; + if VCS_INFO_quilt-patch2subject "$patches/$unapplied[$i]" && (( $+REPLY )) then - unapplied[$i]+=" $line" + unapplied[$i]+=" $REPLY" else unapplied[$i]+=" ?" fi -- cgit v1.2.3 From 7a5ecf4909bb73550012c4b580f054a29a255380 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 4 Jun 2016 16:57:49 +0000 Subject: 38610: vcs_info quilt: Extract a patch subject, 2.0. --- ChangeLog | 3 +++ Functions/VCS_Info/VCS_INFO_quilt | 42 +++++++++++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 4 deletions(-) (limited to 'Functions/VCS_Info') diff --git a/ChangeLog b/ChangeLog index 5f0cae6ce..5ff60c6f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-06-06 Daniel Shahaf + * 38610: Functions/VCS_Info/VCS_INFO_quilt: vcs_info quilt: + Extract a patch subject, 2.0. + * 38609: Functions/VCS_Info/VCS_INFO_quilt: vcs_info quilt: Factor out a helper function. No functional change. diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index e31deb0bd..e7cd89f78 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -83,15 +83,49 @@ function VCS_INFO_quilt-dirfind() { # This function takes as an argument a filename of a patch and sets $REPLY to # a single-line "subject", or unsets it if no subject could be extracted. function VCS_INFO_quilt-patch2subject() { - local line - if [[ -f "$1" ]] && read -r line < "$1"; then - if [[ $line != (#b)(---|Index:)* ]]; then - REPLY=$line + integer i + integer -r LIMIT=10 + local -a lines + local needle + if [[ -f "$1" ]]; then + # Extract the first LIMIT lines, or up to the first empty line or the start of the unidiffs, + # whichever comes first. + while (( i++ < LIMIT )); do + IFS= read -r "lines[$i]" + if [[ -z ${lines[$i]} ]] || [[ ${lines[$i]} == (#b)(---|Index:)* ]]; then + lines[$i]=() + break + fi + done < "$1" + + if needle=${lines[(i)Subject:*]}; (( needle <= $#lines )); then + # "Subject: foo" line, plus rfc822 whitespace unfolding. + # + # Example: 'git format-patch' patches. + REPLY=${lines[needle]} + REPLY=${REPLY#*: } + REPLY=${REPLY#\[PATCH\] } + while [[ ${${lines[++needle]}[1]} == ' ' ]]; do + REPLY+=${lines[needle]} + done + elif needle=${lines[(r)Description:*]}; [[ -n $needle ]]; then + # "Description: foo" line. + # + # Example: DEP-3 patches. + REPLY=${needle#*: } + elif [[ ${lines[1]} == '# HG changeset patch' ]] && { needle=${${lines:#([#]*)}[1]}; [[ -n $needle ]] }; then + # Mercurial patch + REPLY=$needle + elif (( ${+lines[1]} )); then + # The first line of the file is not part of the diff. + REPLY=${lines[1]} else + # The patch has no subject. unset REPLY return 0 fi else + # The patch cannot be examined, or invalid arguments. unset REPLY return 1 fi -- cgit v1.2.3 From 7154052ebe3d810390164a05c39ff83f98a1d858 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 30 Jul 2016 16:16:22 +0000 Subject: 39046 + 39061: New :P history modifier. --- ChangeLog | 10 ++++++++++ Completion/Base/Completer/_external_pwds | 2 +- Completion/Zsh/Type/_history_modifiers | 5 +++-- Doc/Zsh/contrib.yo | 2 +- Doc/Zsh/expn.yo | 9 +++++++++ Functions/MIME/zsh-mime-handler | 2 +- Functions/VCS_Info/VCS_INFO_quilt | 2 +- Functions/Zle/expand-absolute-path | 2 +- NEWS | 11 +++++++++++ Src/params.c | 2 +- Src/subst.c | 13 +++++++++++++ Src/utils.c | 14 ++++++++------ Test/D02glob.ztst | 8 ++++++++ 13 files changed, 68 insertions(+), 14 deletions(-) (limited to 'Functions/VCS_Info') diff --git a/ChangeLog b/ChangeLog index 65263033a..d3a7d3356 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2016-08-22 Daniel Shahaf + + * 39046 + 39061: Completion/Base/Completer/_external_pwds, + Completion/Zsh/Type/_history_modifiers, Doc/Zsh/contrib.yo, + Doc/Zsh/expn.yo, Functions/MIME/zsh-mime-handler, + Functions/VCS_Info/VCS_INFO_quilt, + Functions/Zle/expand-absolute-path, NEWS, Src/params.c, + Src/subst.c, Src/utils.c, Test/D02glob.ztst: New :P history + modifier. + 2016-08-20 Jun-ichi Takimoto * 39064: configure.ac, Src/Modules/mathfuc.c: use scalbn() instead diff --git a/Completion/Base/Completer/_external_pwds b/Completion/Base/Completer/_external_pwds index 4ad50f02b..79e3ba0eb 100644 --- a/Completion/Base/Completer/_external_pwds +++ b/Completion/Base/Completer/_external_pwds @@ -22,7 +22,7 @@ case $OSTYPE in ) ;; linux*) - dirs=( /proc/${^$(pidof zsh):#$$}/cwd(N:A) ) + dirs=( /proc/${^$(pidof zsh):#$$}/cwd(N:P) ) dirs=( $^dirs(N^@) ) ;; *) diff --git a/Completion/Zsh/Type/_history_modifiers b/Completion/Zsh/Type/_history_modifiers index 658f9f346..1a049d6cb 100644 --- a/Completion/Zsh/Type/_history_modifiers +++ b/Completion/Zsh/Type/_history_modifiers @@ -64,8 +64,8 @@ while true; do ) if (( ! global )); then list+=( - "a:absolute path" - "A:absolute path resolving symbolic links" + "a:absolute path, resolve '..' lexically" + "A:as ':a', then resolve symlinks" "c:PATH search for command" "g:globally apply s or &" "h:head - strip trailing path element" @@ -73,6 +73,7 @@ while true; do "r:root - strip suffix" "e:leave only extension" "Q:strip quotes" + "P:realpath, resolve '..' physically" "l:lower case all words" "u:upper case all words" ) diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 00ed08029..63df292ac 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -3477,7 +3477,7 @@ will ensure that any files found in that area will be executed as MIME types even if they are executable. As this example shows, the complete file name is matched against the pattern, regardless of how the file was passed to the handler. The file is resolved to a full path using -the tt(:A) modifier described in +the tt(:P) modifier described in ifzman(the subsection Modifiers in zmanref(zshexpn))\ ifnzman(noderef(Modifiers)); this means that symbolic links are resolved where possible, so that diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index ca4b94f5e..ecb1877a2 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -240,6 +240,7 @@ function, symbolic links are not resolved, so on those systems `tt(a)' and `tt(A)' are equivalent. Note: tt(foo:A) and tt(realpath+LPAR()foo+RPAR()) are different on some inputs. +For tt(realpath+LPAR()foo+RPAR()) semantics, see the `tt(P)` modifier. ) item(tt(c))( Resolve a command name into an absolute path by searching the command @@ -265,6 +266,14 @@ item(tt(p))( Print the new command but do not execute it. Only works with history expansion. ) +item(tt(P))( +Turn a file name into an absolute path, like tt(realpath+LPAR()3+RPAR()). +The resulting path will be absolute, have neither `tt(.)' nor `tt(..)' components, +and refer to the same directory entry as the input filename. + +Unlike tt(realpath+LPAR()3+RPAR()), non-existent trailing components are +permitted and preserved. +) item(tt(q))( Quote the substituted words, escaping further substitutions. Works with history expansion and parameter expansion, though for parameters diff --git a/Functions/MIME/zsh-mime-handler b/Functions/MIME/zsh-mime-handler index 24e5184fc..288a0796d 100644 --- a/Functions/MIME/zsh-mime-handler +++ b/Functions/MIME/zsh-mime-handler @@ -127,7 +127,7 @@ for pattern in $exec_asis; do files=(${dirpref}${~pattern}) if [[ -n ${files[(r)$1]} ]]; then for pattern in $exec_never; do - [[ ${1:A} = ${~pattern} ]] && break 2 + [[ ${1:P} = ${~pattern} ]] && break 2 done if (( list )); then for (( i = 1; i <= $#; i++ )); do diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index e7cd89f78..6adf0a358 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -170,7 +170,7 @@ function VCS_INFO_quilt() { applied=() fi patches=$(<$pc/.quilt_patches) - patches=`builtin cd -q "${pc:h}" && print -r - ${patches:A}` + patches=`builtin cd -q "${pc:h}" && print -r - ${patches:P}` fi if zstyle -t "${context}" get-unapplied; then # This zstyle call needs to be moved further up if `quilt' needs diff --git a/Functions/Zle/expand-absolute-path b/Functions/Zle/expand-absolute-path index b85757600..4887f3c60 100644 --- a/Functions/Zle/expand-absolute-path +++ b/Functions/Zle/expand-absolute-path @@ -10,7 +10,7 @@ autoload -Uz modify-current-argument if (( ! ${+functions[glob-expand-absolute-path]} )); then glob-expand-absolute-path() { local -a files - files=(${~1}(N:A)) + files=(${~1}(N:P)) (( ${#files} )) || return REPLY=${(D)files[1]} } diff --git a/NEWS b/NEWS index 15822ad34..65b246d33 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,17 @@ CHANGES FROM PREVIOUS VERSIONS OF ZSH Note also the list of incompatibilities in the README file. +Changes from 5.2 to 5.3 +----------------------- + +The new word modifier ':P' computes the physical path of the argument. +It is different from the existing ':a' modifier which always resolves +'/before/here/../after' to '/before/after', and differs from the +existing ':A' modifier which resolves symlinks only after 'here/..' is +removed, even when /before/here is itself a symbolic link. It is +recommended to review uses of ':A' and, if appropriate, convert them +to ':P' as soon as compatibility with 5.2 is no longer a requirement. + Changes from 5.1.1 to 5.2 ------------------------- diff --git a/Src/params.c b/Src/params.c index 0eda7848f..842b2f0d1 100644 --- a/Src/params.c +++ b/Src/params.c @@ -4336,7 +4336,7 @@ void homesetfn(UNUSED(Param pm), char *x) { zsfree(home); - if (x && isset(CHASELINKS) && (home = xsymlink(x))) + if (x && isset(CHASELINKS) && (home = xsymlink(x, 0))) zsfree(x); else home = x ? x : ztrdup(""); diff --git a/Src/subst.c b/Src/subst.c index c61551bf6..15eb59b64 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -4081,6 +4081,7 @@ modify(char **str, char **ptr) case 'u': case 'q': case 'Q': + case 'P': c = **ptr; break; @@ -4287,6 +4288,12 @@ modify(char **str, char **ptr) untokenize(copy); } break; + case 'P': + if (*copy != '/') { + copy = zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP), "/", copy); + } + copy = xsymlink(copy, 1); + break; } tc = *tt; *tt = '\0'; @@ -4363,6 +4370,12 @@ modify(char **str, char **ptr) untokenize(*str); } break; + case 'P': + if (**str != '/') { + *str = zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP), "/", *str); + } + *str = xsymlink(*str, 1); + break; } } if (rec < 0) { diff --git a/Src/utils.c b/Src/utils.c index 0a5954f65..45fd19286 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -801,9 +801,9 @@ findpwd(char *s) char *t; if (*s == '/') - return xsymlink(s); + return xsymlink(s, 0); s = tricat((pwd[1]) ? pwd : "", "/", s); - t = xsymlink(s); + t = xsymlink(s, 0); zsfree(s); return t; } @@ -969,11 +969,13 @@ xsymlinks(char *s, int full) /* * expand symlinks in s, and remove other weird things: * note that this always expands symlinks. + * + * 'heap' indicates whether to malloc() or allocate on the heap. */ /**/ char * -xsymlink(char *s) +xsymlink(char *s, int heap) { if (*s != '/') return NULL; @@ -981,8 +983,8 @@ xsymlink(char *s) if (xsymlinks(s + 1, 1) < 0) zwarn("path expansion failed, using root directory"); if (!*xbuf) - return ztrdup("/"); - return ztrdup(xbuf); + return heap ? dupstring("/") : ztrdup("/"); + return heap ? dupstring(xbuf) : ztrdup(xbuf); } /**/ @@ -1260,7 +1262,7 @@ getnameddir(char *name) /* Retrieve an entry from the password table/database for this user. */ struct passwd *pw; if ((pw = getpwnam(name))) { - char *dir = isset(CHASELINKS) ? xsymlink(pw->pw_dir) + char *dir = isset(CHASELINKS) ? xsymlink(pw->pw_dir, 0) : ztrdup(pw->pw_dir); if (dir) { adduserdir(name, dir, ND_USERNAME, 1); diff --git a/Test/D02glob.ztst b/Test/D02glob.ztst index 7befbc21f..1385d57d9 100644 --- a/Test/D02glob.ztst +++ b/Test/D02glob.ztst @@ -678,3 +678,11 @@ rm glob.tmp/link 0:modifier ':A' resolves '..' components before symlinks # There should be no output + + ln -s dir3/subdir glob.tmp/link + () { + print ${1:P} + } glob.tmp/link/../../hello/world + rm glob.tmp/link +0:modifier ':P' resolves symlinks before '..' components +*>*glob.tmp/hello/world -- cgit v1.2.3 From 889f6690fd678ed2fdeb4d467e5b8db49b9c6667 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 23 Sep 2016 06:47:31 +0000 Subject: 39423: vcs_info git: Produce nicer applied-string messages for 'exec' actions. This changes the behaviour on "unknown" git-rebase actions (those other than pick/reword/edit/fixup/squash/execute). --- ChangeLog | 6 ++++++ Functions/VCS_Info/Backends/VCS_INFO_get_data_git | 8 ++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'Functions/VCS_Info') diff --git a/ChangeLog b/ChangeLog index 608a296e0..8362d3e7b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2016-09-24 Daniel Shahaf + + * 39423: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: + vcs_info git: Produce nicer applied-string messages for 'exec' + actions. + 2016-09-23 Daniel Shahaf * 39412: Src/Zle/computil.c: Fix directory completion when diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git index 472c10d5d..18ba89a9a 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -213,8 +213,12 @@ elif [[ -d "${gitdir}/rebase-merge" ]]; then local p [[ -f "${patchdir}/done" ]] && for p in ${(f)"$(< "${patchdir}/done")"}; do - # remove action - git_patches_applied+=("${${(s: :)p}[2,-1]}") + # pick/edit/fixup/squash/reword: Add "$hash $subject" to $git_patches_applied. + # exec: Add "exec ${command}" to $git_patches_applied. + # (anything else): As 'exec'. + p=${p/(#s)(p|pick|e|edit|r|reword|f|fixup|s|squash) /} + p=${p/(#s)x /exec } + git_patches_applied+=("$p") done if [[ -f "${patchdir}/git-rebase-todo" ]] ; then git_patches_unapplied=(${(f)"$(grep -v '^$' "${patchdir}/git-rebase-todo" | grep -v '^#')"}) -- cgit v1.2.3 From 74aa45910b3711622e9eb5ccf8adef9566db6f62 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 31 Oct 2016 18:35:19 +0000 Subject: 39786: vcs_info (hg): Use native hexdump implementation instead of external command. Fixes issue whereby the external command would print "*" for repeated octets. Includes comment change, cf 39790. --- ChangeLog | 7 +++++++ Functions/VCS_Info/Backends/VCS_INFO_get_data_hg | 7 ++++--- Functions/VCS_Info/VCS_INFO_hexdump | 16 ++++++++++++++++ Functions/VCS_Info/vcs_info | 1 + 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 Functions/VCS_Info/VCS_INFO_hexdump (limited to 'Functions/VCS_Info') diff --git a/ChangeLog b/ChangeLog index e08cafd30..9dd63251e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2016-10-31 Daniel Shahaf + + * 39786: Functions/VCS_Info/Backends/VCS_INFO_get_data_hg, + Functions/VCS_Info/VCS_INFO_hexdump, Functions/VCS_Info/vcs_info: + vcs_info (hg): Use native hexdump implementation instead of + external command. + 2016-10-30 Peter Stephenson * 39777: Src/parse.c, Test/D08cmdsubst.ztst: $() is a valid diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg index f35ad5965..69b7db304 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg @@ -40,9 +40,10 @@ VCS_INFO_adjust # Disabled by default anyway, so no harm done. if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision ; then if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" use-simple \ - && ( VCS_INFO_check_com hexdump ) && [[ -r ${dirstatefile} ]] ; then - # Calling hexdump is (much) faster than hg but doesn't get the local rev - r_csetid=$(hexdump -n 20 -e '1/1 "%02x"' ${dirstatefile}) + && VCS_INFO_hexdump ${dirstatefile} 20 ; then + # Calling VCS_INFO_hexdump is (much) faster than hg but doesn't get + # the local rev + r_csetid=$REPLY else # Settling for a short (but unique!) hash because getting the full # 40-char hash in addition to all the other info we want isn't diff --git a/Functions/VCS_Info/VCS_INFO_hexdump b/Functions/VCS_Info/VCS_INFO_hexdump new file mode 100644 index 000000000..11f1c1a50 --- /dev/null +++ b/Functions/VCS_Info/VCS_INFO_hexdump @@ -0,0 +1,16 @@ +## vim:ft=zsh + +# VCS_INFO_hexdump FILENAME BYTECOUNT +# +# Return in $REPLY a hexadecimal representation (lowercase, no whitespace) +# of the first BYTECOUNT bytes of FILENAME. + +if [[ -r $1 ]]; then + setopt localoptions nomultibyte extendedglob + local val + read -k $2 -u 0 val <$1 + REPLY=${(Lj::)${(l:2::0:)${(@s//)val}//(#m)*/$(( [##16] ##$MATCH ))}} +else + return 1 +fi + diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info index f13f6b501..c0c1182e6 100644 --- a/Functions/VCS_Info/vcs_info +++ b/Functions/VCS_Info/vcs_info @@ -19,6 +19,7 @@ static_functions=( VCS_INFO_check_com VCS_INFO_formats VCS_INFO_get_cmd + VCS_INFO_hexdump VCS_INFO_hook VCS_INFO_maxexports VCS_INFO_nvcsformats -- cgit v1.2.3 From 8891f5a33d2617b7c7bb4f37c4340a1dd159529e Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 1 Dec 2016 17:11:58 +0000 Subject: unposted: vcs_info: Break out VCS_INFO_quilt-patch2subject into VCS_INFO_patch2subject ... so other places can use it; compare 40030 in the 39990 thread. --- ChangeLog | 7 +++++ Functions/VCS_Info/VCS_INFO_patch2subject | 50 +++++++++++++++++++++++++++++++ Functions/VCS_Info/VCS_INFO_quilt | 49 +----------------------------- Functions/VCS_Info/vcs_info | 1 + 4 files changed, 59 insertions(+), 48 deletions(-) create mode 100644 Functions/VCS_Info/VCS_INFO_patch2subject (limited to 'Functions/VCS_Info') diff --git a/ChangeLog b/ChangeLog index fc49df000..98baf3ed1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2016-12-01 Daniel Shahaf + + * unposted: Functions/VCS_Info/VCS_INFO_patch2subject, + Functions/VCS_Info/VCS_INFO_quilt, Functions/VCS_Info/vcs_info: + vcs_info: Break out VCS_INFO_quilt-patch2subject into + VCS_INFO_patch2subject + 2016-12-01 Mikael Magnusson * 40024: Completion/Unix/Type/_path_files: Update _path_files diff --git a/Functions/VCS_Info/VCS_INFO_patch2subject b/Functions/VCS_Info/VCS_INFO_patch2subject new file mode 100644 index 000000000..583467bc8 --- /dev/null +++ b/Functions/VCS_Info/VCS_INFO_patch2subject @@ -0,0 +1,50 @@ +# This function takes as an argument a filename of a patch and sets $REPLY to +# a single-line "subject", or unsets it if no subject could be extracted. +{ + integer i + integer -r LIMIT=10 + local -a lines + local needle + if [[ -f "$1" ]]; then + # Extract the first LIMIT lines, or up to the first empty line or the start of the unidiffs, + # whichever comes first. + while (( i++ < LIMIT )); do + IFS= read -r "lines[$i]" + if [[ -z ${lines[$i]} ]] || [[ ${lines[$i]} == (#b)(---|Index:)* ]]; then + lines[$i]=() + break + fi + done < "$1" + + if needle=${lines[(i)Subject:*]}; (( needle <= $#lines )); then + # "Subject: foo" line, plus rfc822 whitespace unfolding. + # + # Example: 'git format-patch' patches. + REPLY=${lines[needle]} + REPLY=${REPLY#*: } + REPLY=${REPLY#\[PATCH\] } + while [[ ${${lines[++needle]}[1]} == ' ' ]]; do + REPLY+=${lines[needle]} + done + elif needle=${lines[(r)Description:*]}; [[ -n $needle ]]; then + # "Description: foo" line. + # + # Example: DEP-3 patches. + REPLY=${needle#*: } + elif [[ ${lines[1]} == '# HG changeset patch' ]] && { needle=${${lines:#([#]*)}[1]}; [[ -n $needle ]] }; then + # Mercurial patch + REPLY=$needle + elif (( ${+lines[1]} )); then + # The first line of the file is not part of the diff. + REPLY=${lines[1]} + else + # The patch has no subject. + unset REPLY + return 0 + fi + else + # The patch cannot be examined, or invalid arguments. + unset REPLY + return 1 + fi +} diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index 6adf0a358..4c61506cd 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -80,55 +80,8 @@ function VCS_INFO_quilt-dirfind() { return ${ret} } -# This function takes as an argument a filename of a patch and sets $REPLY to -# a single-line "subject", or unsets it if no subject could be extracted. function VCS_INFO_quilt-patch2subject() { - integer i - integer -r LIMIT=10 - local -a lines - local needle - if [[ -f "$1" ]]; then - # Extract the first LIMIT lines, or up to the first empty line or the start of the unidiffs, - # whichever comes first. - while (( i++ < LIMIT )); do - IFS= read -r "lines[$i]" - if [[ -z ${lines[$i]} ]] || [[ ${lines[$i]} == (#b)(---|Index:)* ]]; then - lines[$i]=() - break - fi - done < "$1" - - if needle=${lines[(i)Subject:*]}; (( needle <= $#lines )); then - # "Subject: foo" line, plus rfc822 whitespace unfolding. - # - # Example: 'git format-patch' patches. - REPLY=${lines[needle]} - REPLY=${REPLY#*: } - REPLY=${REPLY#\[PATCH\] } - while [[ ${${lines[++needle]}[1]} == ' ' ]]; do - REPLY+=${lines[needle]} - done - elif needle=${lines[(r)Description:*]}; [[ -n $needle ]]; then - # "Description: foo" line. - # - # Example: DEP-3 patches. - REPLY=${needle#*: } - elif [[ ${lines[1]} == '# HG changeset patch' ]] && { needle=${${lines:#([#]*)}[1]}; [[ -n $needle ]] }; then - # Mercurial patch - REPLY=$needle - elif (( ${+lines[1]} )); then - # The first line of the file is not part of the diff. - REPLY=${lines[1]} - else - # The patch has no subject. - unset REPLY - return 0 - fi - else - # The patch cannot be examined, or invalid arguments. - unset REPLY - return 1 - fi + VCS_INFO_patch2subject "$@" } function VCS_INFO_quilt() { diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info index c0c1182e6..24ae98e52 100644 --- a/Functions/VCS_Info/vcs_info +++ b/Functions/VCS_Info/vcs_info @@ -23,6 +23,7 @@ static_functions=( VCS_INFO_hook VCS_INFO_maxexports VCS_INFO_nvcsformats + VCS_INFO_patch2subject VCS_INFO_quilt VCS_INFO_realpath VCS_INFO_reposub -- cgit v1.2.3