completion: treat results of git ls-tree as file paths
Let's say there are files named 'foo bar.txt', and 'abc def/test.txt' in
repository. When following commands trigger a completion:
    git show HEAD:fo<Tab>
    git show HEAD:ab<Tab>
The completion results in bash/zsh:
    git show HEAD:foo bar.txt
    git show HEAD:abc def/
Where the both of them have an unescaped space in paths, so they'll be
misread by git. All entries of git ls-tree either a filename or a
directory, so __gitcomp_file() is proper rather than __gitcomp_nl().
Note the commit f12785a3, which handles quoted paths properly. Like this
case, we should dequote $cur_ for ?*:* case. For example, let's say
there is untracked directory 'abc deg', then trigger a completion:
    git show HEAD:abc\ de<Tab>
    git show HEAD:'abc de<Tab>
    git show HEAD:"abc de<Tab>
should uniquely complete 'abc def', but bash completes 'abc def' and
'abc deg' instead. In zsh, triggering a completion:
    git show HEAD:abc\ def/<Tab>
should complete 'test.txt', but nothing comes. The both problems will be
resolved by dequoting paths.
__git_complete_revlist_file() passes arguments to __gitcomp_nl() where
the first one is a list something like:
    abc def/Z
    foo bar.txt Z
where Z is the mark of the EOL.
- The trailing space of blob in __git ls-tree | sed.
  It makes the completion results become:
      git show HEAD:foo\ bar.txt\ <CURSOR>
  So git will try to find a file named 'foo bar.txt ' instead.
- The trailing slash of tree in __git ls-tree | sed.
  It makes the completion results on zsh become:
      git show HEAD:abc\ def/ <CURSOR>
  So that the last space on command like should be removed on zsh to
  complete filenames under 'abc def/'.
Signed-off-by: Chayoung You <yousbe@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
			
			
This commit is contained in:
		 Chayoung You
					Chayoung You
				
			
				
					committed by
					
						 Junio C Hamano
						Junio C Hamano
					
				
			
			
				
	
			
			
			 Junio C Hamano
						Junio C Hamano
					
				
			
						parent
						
							7a478b36aa
						
					
				
				
					commit
					6d54f528c7
				
			| @ -855,7 +855,7 @@ __git_compute_merge_strategies () | |||||||
|  |  | ||||||
| __git_complete_revlist_file () | __git_complete_revlist_file () | ||||||
| { | { | ||||||
| 	local pfx ls ref cur_="$cur" | 	local dequoted_word pfx ls ref cur_="$cur" | ||||||
| 	case "$cur_" in | 	case "$cur_" in | ||||||
| 	*..?*:*) | 	*..?*:*) | ||||||
| 		return | 		return | ||||||
| @ -863,14 +863,18 @@ __git_complete_revlist_file () | |||||||
| 	?*:*) | 	?*:*) | ||||||
| 		ref="${cur_%%:*}" | 		ref="${cur_%%:*}" | ||||||
| 		cur_="${cur_#*:}" | 		cur_="${cur_#*:}" | ||||||
| 		case "$cur_" in |  | ||||||
|  | 		__git_dequote "$cur_" | ||||||
|  |  | ||||||
|  | 		case "$dequoted_word" in | ||||||
| 		?*/*) | 		?*/*) | ||||||
| 			pfx="${cur_%/*}" | 			pfx="${dequoted_word%/*}" | ||||||
| 			cur_="${cur_##*/}" | 			cur_="${dequoted_word##*/}" | ||||||
| 			ls="$ref:$pfx" | 			ls="$ref:$pfx" | ||||||
| 			pfx="$pfx/" | 			pfx="$pfx/" | ||||||
| 			;; | 			;; | ||||||
| 		*) | 		*) | ||||||
|  | 			cur_="$dequoted_word" | ||||||
| 			ls="$ref" | 			ls="$ref" | ||||||
| 			;; | 			;; | ||||||
| 		esac | 		esac | ||||||
| @ -880,21 +884,10 @@ __git_complete_revlist_file () | |||||||
| 		*)   pfx="$ref:$pfx" ;; | 		*)   pfx="$ref:$pfx" ;; | ||||||
| 		esac | 		esac | ||||||
|  |  | ||||||
| 		__gitcomp_nl "$(__git ls-tree "$ls" \ | 		__gitcomp_file "$(__git ls-tree "$ls" \ | ||||||
| 				| sed '/^100... blob /{ | 				| sed 's/^.*	// | ||||||
| 				           s,^.*	,, | 				       s/$//')" \ | ||||||
| 				           s,$, , | 			"$pfx" "$cur_" | ||||||
| 				       } |  | ||||||
| 				       /^120000 blob /{ |  | ||||||
| 				           s,^.*	,, |  | ||||||
| 				           s,$, , |  | ||||||
| 				       } |  | ||||||
| 				       /^040000 tree /{ |  | ||||||
| 				           s,^.*	,, |  | ||||||
| 				           s,$,/, |  | ||||||
| 				       } |  | ||||||
| 				       s/^.*	//')" \ |  | ||||||
| 			"$pfx" "$cur_" "" |  | ||||||
| 		;; | 		;; | ||||||
| 	*...*) | 	*...*) | ||||||
| 		pfx="${cur_%...*}..." | 		pfx="${cur_%...*}..." | ||||||
|  | |||||||
| @ -1515,8 +1515,8 @@ test_expect_success 'show completes all refs' ' | |||||||
|  |  | ||||||
| test_expect_success '<ref>: completes paths' ' | test_expect_success '<ref>: completes paths' ' | ||||||
| 	test_completion "git show mytag:f" <<-\EOF | 	test_completion "git show mytag:f" <<-\EOF | ||||||
| 	file1 Z | 	file1Z | ||||||
| 	file2 Z | 	file2Z | ||||||
| 	EOF | 	EOF | ||||||
| ' | ' | ||||||
|  |  | ||||||
| @ -1525,7 +1525,7 @@ test_expect_success 'complete tree filename with spaces' ' | |||||||
| 	git add "name with spaces" && | 	git add "name with spaces" && | ||||||
| 	git commit -m spaces && | 	git commit -m spaces && | ||||||
| 	test_completion "git show HEAD:nam" <<-\EOF | 	test_completion "git show HEAD:nam" <<-\EOF | ||||||
| 	name with spaces Z | 	name with spacesZ | ||||||
| 	EOF | 	EOF | ||||||
| ' | ' | ||||||
|  |  | ||||||
| @ -1534,8 +1534,8 @@ test_expect_success 'complete tree filename with metacharacters' ' | |||||||
| 	git add "name with \${meta}" && | 	git add "name with \${meta}" && | ||||||
| 	git commit -m meta && | 	git commit -m meta && | ||||||
| 	test_completion "git show HEAD:nam" <<-\EOF | 	test_completion "git show HEAD:nam" <<-\EOF | ||||||
| 	name with ${meta} Z | 	name with ${meta}Z | ||||||
| 	name with spaces Z | 	name with spacesZ | ||||||
| 	EOF | 	EOF | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user