@matheusbsbs / matheus-bagliano / commits / 8851f4800c
Fork 0

git-add -i/-p: learn to unwrap C-quoted paths

The underlying plumbing commands are not run with -z option, so the paths returned from them need to be unquoted as needed. Remove the now stale BUGS section from git-add documentaiton as suggested by Teemu Likonen. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Feb 16, 2009 at 22:43 UTC 8851f4800c15fe91b6a53e9e284787b983226c41
2 files changed +52 -10
Documentation/git-add.txt
-7
@@ -263,13 +263,6 @@ diff::
263 This lets you review what will be committed (i.e. between
264 HEAD and index).
265
266 -Bugs
267 -----
268 -The interactive mode does not work with files whose names contain
269 -characters that need C-quoting. `core.quotepath` configuration can be
270 -used to work this limitation around to some degree, but backslash,
271 -double-quote and control characters will still have problems.
272 -
266 SEE ALSO
267 --------
268 linkgit:git-status[1]
git-add--interactive.perl
+52 -3
@@ -3,6 +3,8 @@
3 use strict;
4 use Git;
5
6 +binmode(STDOUT, ":raw");
7 +
8 my $repo = Git->repository();
9
10 my $menu_use_color = $repo->get_colorbool('color.interactive');
@@ -91,6 +93,47 @@ if (!defined $GIT_DIR) {
93 }
94 chomp($GIT_DIR);
95
96 +my %cquote_map = (
97 + "b" => chr(8),
98 + "t" => chr(9),
99 + "n" => chr(10),
100 + "v" => chr(11),
101 + "f" => chr(12),
102 + "r" => chr(13),
103 + "\\" => "\\",
104 + "\042" => "\042",
105 +);
106 +
107 +sub unquote_path {
108 + local ($_) = @_;
109 + my ($retval, $remainder);
110 + if (!/^\042(.*)\042$/) {
111 + return $_;
112 + }
113 + ($_, $retval) = ($1, "");
114 + while (/^([^\\]*)\\(.*)$/) {
115 + $remainder = $2;
116 + $retval .= $1;
117 + for ($remainder) {
118 + if (/^([0-3][0-7][0-7])(.*)$/) {
119 + $retval .= chr(oct($1));
120 + $_ = $2;
121 + last;
122 + }
123 + if (/^([\\\042btnvfr])(.*)$/) {
124 + $retval .= $cquote_map{$1};
125 + $_ = $2;
126 + last;
127 + }
128 + # This is malformed -- just return it as-is for now.
129 + return $_[0];
130 + }
131 + $_ = $remainder;
132 + }
133 + $retval .= $_;
134 + return $retval;
135 +}
136 +
137 sub refresh {
138 my $fh;
139 open $fh, 'git update-index --refresh |'
@@ -104,7 +147,7 @@ sub refresh {
147 sub list_untracked {
148 map {
149 chomp $_;
107 - $_;
150 + unquote_path($_);
151 }
152 run_cmd_pipe(qw(git ls-files --others --exclude-standard --), @ARGV);
153 }
@@ -141,7 +184,8 @@ sub list_modified {
184
185 if (@ARGV) {
186 @tracked = map {
144 - chomp $_; $_;
187 + chomp $_;
188 + unquote_path($_);
189 } run_cmd_pipe(qw(git ls-files --exclude-standard --), @ARGV);
190 return if (!@tracked);
191 }
@@ -153,6 +197,7 @@ sub list_modified {
197 if (($add, $del, $file) =
198 /^([-\d]+) ([-\d]+) (.*)/) {
199 my ($change, $bin);
200 + $file = unquote_path($file);
201 if ($add eq '-' && $del eq '-') {
202 $change = 'binary';
203 $bin = 1;
@@ -168,6 +213,7 @@ sub list_modified {
213 }
214 elsif (($adddel, $file) =
215 /^ (create|delete) mode [0-7]+ (.*)$/) {
216 + $file = unquote_path($file);
217 $data{$file}{INDEX_ADDDEL} = $adddel;
218 }
219 }
@@ -175,6 +221,7 @@ sub list_modified {
221 for (run_cmd_pipe(qw(git diff-files --numstat --summary --), @tracked)) {
222 if (($add, $del, $file) =
223 /^([-\d]+) ([-\d]+) (.*)/) {
224 + $file = unquote_path($file);
225 if (!exists $data{$file}) {
226 $data{$file} = +{
227 INDEX => 'unchanged',
@@ -196,6 +243,7 @@ sub list_modified {
243 }
244 elsif (($adddel, $file) =
245 /^ (create|delete) mode [0-7]+ (.*)$/) {
246 + $file = unquote_path($file);
247 $data{$file}{FILE_ADDDEL} = $adddel;
248 }
249 }
@@ -302,7 +350,8 @@ sub find_unique_prefixes {
350 }
351 %search = %{$search{$letter}};
352 }
305 - if ($soft_limit && $j + 1 > $soft_limit) {
353 + if (ord($letters[0]) > 127 ||
354 + ($soft_limit && $j + 1 > $soft_limit)) {
355 $prefix = undef;
356 $remainder = $ret;
357 }