Skip to content

Commit 53edde6

Browse files
dschoGit for Windows Build Agent
authored andcommitted
Merge branch 'jc/quote-path-cleanup'
This merges the `quote_path()` fixes (backported on top of v2.28.0) into Git for Windows' `main` branch early, i.e. before v2.29.0-rc0 is available, to be able to adjust our `builtin/clean.c` changes early (which would otherwise conflict). Signed-off-by: Johannes Schindelin <[email protected]>
2 parents 24d0974 + f38a11b commit 53edde6

File tree

7 files changed

+94
-60
lines changed

7 files changed

+94
-60
lines changed

builtin/clean.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
162162
if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) &&
163163
is_nonbare_repository_dir(path)) {
164164
if (!quiet) {
165-
quote_path_relative(path->buf, prefix, &quoted);
165+
quote_path(path->buf, prefix, &quoted, 0);
166166
printf(dry_run ? _(msg_would_skip_git_dir) : _(msg_skip_git_dir),
167167
quoted.buf);
168168
}
@@ -177,7 +177,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
177177
res = dry_run ? 0 : rmdir(path->buf);
178178
if (res) {
179179
int saved_errno = errno;
180-
quote_path_relative(path->buf, prefix, &quoted);
180+
quote_path(path->buf, prefix, &quoted, 0);
181181
errno = saved_errno;
182182
warning_errno(_(msg_warn_remove_failed), quoted.buf);
183183
*dir_gone = 0;
@@ -202,19 +202,19 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
202202
if (remove_dirs(path, prefix, force_flag, dry_run, quiet, &gone))
203203
ret = 1;
204204
if (gone) {
205-
quote_path_relative(path->buf, prefix, &quoted);
205+
quote_path(path->buf, prefix, &quoted, 0);
206206
string_list_append(&dels, quoted.buf);
207207
} else
208208
*dir_gone = 0;
209209
continue;
210210
} else {
211211
res = dry_run ? 0 : unlink(path->buf);
212212
if (!res) {
213-
quote_path_relative(path->buf, prefix, &quoted);
213+
quote_path(path->buf, prefix, &quoted, 0);
214214
string_list_append(&dels, quoted.buf);
215215
} else {
216216
int saved_errno = errno;
217-
quote_path_relative(path->buf, prefix, &quoted);
217+
quote_path(path->buf, prefix, &quoted, 0);
218218
errno = saved_errno;
219219
warning_errno(_(msg_warn_remove_failed), quoted.buf);
220220
*dir_gone = 0;
@@ -238,7 +238,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
238238
*dir_gone = 1;
239239
else {
240240
int saved_errno = errno;
241-
quote_path_relative(path->buf, prefix, &quoted);
241+
quote_path(path->buf, prefix, &quoted, 0);
242242
errno = saved_errno;
243243
warning_errno(_(msg_warn_remove_failed), quoted.buf);
244244
*dir_gone = 0;
@@ -266,7 +266,7 @@ static void pretty_print_dels(void)
266266
struct column_options copts;
267267

268268
for_each_string_list_item(item, &del_list) {
269-
qname = quote_path_relative(item->string, NULL, &buf);
269+
qname = quote_path(item->string, NULL, &buf, 0);
270270
string_list_append(&list, qname);
271271
}
272272

@@ -753,7 +753,7 @@ static int ask_each_cmd(void)
753753
for_each_string_list_item(item, &del_list) {
754754
/* Ctrl-D should stop removing files */
755755
if (!eof) {
756-
qname = quote_path_relative(item->string, NULL, &buf);
756+
qname = quote_path(item->string, NULL, &buf, 0);
757757
/* TRANSLATORS: Make sure to keep [y/N] as is */
758758
printf(_("Remove %s [y/N]? "), qname);
759759
if (git_read_line_interactively(&confirm) == EOF) {
@@ -1051,19 +1051,19 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
10511051
if (remove_dirs(&abs_path, prefix, rm_flags, dry_run, quiet, &gone))
10521052
errors++;
10531053
if (gone && !quiet) {
1054-
qname = quote_path_relative(item->string, NULL, &buf);
1054+
qname = quote_path(item->string, NULL, &buf, 0);
10551055
printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
10561056
}
10571057
} else {
10581058
res = dry_run ? 0 : unlink(abs_path.buf);
10591059
if (res) {
10601060
int saved_errno = errno;
1061-
qname = quote_path_relative(item->string, NULL, &buf);
1061+
qname = quote_path(item->string, NULL, &buf, 0);
10621062
errno = saved_errno;
10631063
warning_errno(_(msg_warn_remove_failed), qname);
10641064
errors++;
10651065
} else if (!quiet) {
1066-
qname = quote_path_relative(item->string, NULL, &buf);
1066+
qname = quote_path(item->string, NULL, &buf, 0);
10671067
printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
10681068
}
10691069
}

builtin/grep.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ static void grep_source_name(struct grep_opt *opt, const char *filename,
319319
}
320320

321321
if (opt->relative && opt->prefix_length)
322-
quote_path_relative(filename + tree_name_len, opt->prefix, out);
322+
quote_path(filename + tree_name_len, opt->prefix, out, 0);
323323
else
324324
quote_c_style(filename + tree_name_len, out, NULL, 0);
325325

diff.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -482,14 +482,14 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
482482

483483
static char *quote_two(const char *one, const char *two)
484484
{
485-
int need_one = quote_c_style(one, NULL, NULL, 1);
486-
int need_two = quote_c_style(two, NULL, NULL, 1);
485+
int need_one = quote_c_style(one, NULL, NULL, CQUOTE_NODQ);
486+
int need_two = quote_c_style(two, NULL, NULL, CQUOTE_NODQ);
487487
struct strbuf res = STRBUF_INIT;
488488

489489
if (need_one + need_two) {
490490
strbuf_addch(&res, '"');
491-
quote_c_style(one, &res, NULL, 1);
492-
quote_c_style(two, &res, NULL, 1);
491+
quote_c_style(one, &res, NULL, CQUOTE_NODQ);
492+
quote_c_style(two, &res, NULL, CQUOTE_NODQ);
493493
strbuf_addch(&res, '"');
494494
} else {
495495
strbuf_addstr(&res, one);

quote.c

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ int sq_dequote_to_strvec(char *arg, struct strvec *array)
210210
*/
211211
#define X8(x) x, x, x, x, x, x, x, x
212212
#define X16(x) X8(x), X8(x)
213-
static signed char const sq_lookup[256] = {
213+
static signed char const cq_lookup[256] = {
214214
/* 0 1 2 3 4 5 6 7 */
215215
/* 0x00 */ 1, 1, 1, 1, 1, 1, 1, 'a',
216216
/* 0x08 */ 'b', 't', 'n', 'v', 'f', 'r', 1, 1,
@@ -223,9 +223,9 @@ static signed char const sq_lookup[256] = {
223223
/* 0x80 */ /* set to 0 */
224224
};
225225

226-
static inline int sq_must_quote(char c)
226+
static inline int cq_must_quote(char c)
227227
{
228-
return sq_lookup[(unsigned char)c] + quote_path_fully > 0;
228+
return cq_lookup[(unsigned char)c] + quote_path_fully > 0;
229229
}
230230

231231
/* returns the longest prefix not needing a quote up to maxlen if positive.
@@ -235,9 +235,9 @@ static size_t next_quote_pos(const char *s, ssize_t maxlen)
235235
{
236236
size_t len;
237237
if (maxlen < 0) {
238-
for (len = 0; !sq_must_quote(s[len]); len++);
238+
for (len = 0; !cq_must_quote(s[len]); len++);
239239
} else {
240-
for (len = 0; len < maxlen && !sq_must_quote(s[len]); len++);
240+
for (len = 0; len < maxlen && !cq_must_quote(s[len]); len++);
241241
}
242242
return len;
243243
}
@@ -256,7 +256,7 @@ static size_t next_quote_pos(const char *s, ssize_t maxlen)
256256
* Return value is the same as in (1).
257257
*/
258258
static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
259-
struct strbuf *sb, FILE *fp, int no_dq)
259+
struct strbuf *sb, FILE *fp, unsigned flags)
260260
{
261261
#undef EMIT
262262
#define EMIT(c) \
@@ -272,6 +272,7 @@ static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
272272
count += (l); \
273273
} while (0)
274274

275+
int no_dq = !!(flags & CQUOTE_NODQ);
275276
size_t len, count = 0;
276277
const char *p = name;
277278

@@ -291,8 +292,8 @@ static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
291292
ch = (unsigned char)*p++;
292293
if (maxlen >= 0)
293294
maxlen -= len + 1;
294-
if (sq_lookup[ch] >= ' ') {
295-
EMIT(sq_lookup[ch]);
295+
if (cq_lookup[ch] >= ' ') {
296+
EMIT(cq_lookup[ch]);
296297
} else {
297298
EMIT(((ch >> 6) & 03) + '0');
298299
EMIT(((ch >> 3) & 07) + '0');
@@ -309,19 +310,21 @@ static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
309310
return count;
310311
}
311312

312-
size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, int nodq)
313+
size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, unsigned flags)
313314
{
314-
return quote_c_style_counted(name, -1, sb, fp, nodq);
315+
return quote_c_style_counted(name, -1, sb, fp, flags);
315316
}
316317

317-
void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path, int nodq)
318+
void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path,
319+
unsigned flags)
318320
{
321+
int nodq = !!(flags & CQUOTE_NODQ);
319322
if (quote_c_style(prefix, NULL, NULL, 0) ||
320323
quote_c_style(path, NULL, NULL, 0)) {
321324
if (!nodq)
322325
strbuf_addch(sb, '"');
323-
quote_c_style(prefix, sb, NULL, 1);
324-
quote_c_style(path, sb, NULL, 1);
326+
quote_c_style(prefix, sb, NULL, CQUOTE_NODQ);
327+
quote_c_style(path, sb, NULL, CQUOTE_NODQ);
325328
if (!nodq)
326329
strbuf_addch(sb, '"');
327330
} else {
@@ -352,13 +355,25 @@ void write_name_quoted_relative(const char *name, const char *prefix,
352355
}
353356

354357
/* quote path as relative to the given prefix */
355-
char *quote_path_relative(const char *in, const char *prefix,
356-
struct strbuf *out)
358+
char *quote_path(const char *in, const char *prefix, struct strbuf *out, unsigned flags)
357359
{
358360
struct strbuf sb = STRBUF_INIT;
359361
const char *rel = relative_path(in, prefix, &sb);
362+
int force_dq = ((flags & QUOTE_PATH_QUOTE_SP) && strchr(rel, ' '));
363+
360364
strbuf_reset(out);
361-
quote_c_style_counted(rel, strlen(rel), out, NULL, 0);
365+
366+
/*
367+
* If the caller wants us to enclose the output in a dq-pair
368+
* whether quote_c_style_counted() needs to, we do it ourselves
369+
* and tell quote_c_style_counted() not to.
370+
*/
371+
if (force_dq)
372+
strbuf_addch(out, '"');
373+
quote_c_style_counted(rel, strlen(rel), out, NULL,
374+
force_dq ? CQUOTE_NODQ : 0);
375+
if (force_dq)
376+
strbuf_addch(out, '"');
362377
strbuf_release(&sb);
363378

364379
return out->buf;

quote.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,19 @@ struct strvec;
6464
int sq_dequote_to_strvec(char *arg, struct strvec *);
6565

6666
int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);
67-
size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq);
68-
void quote_two_c_style(struct strbuf *, const char *, const char *, int);
67+
68+
/* Bits in the flags parameter to quote_c_style() */
69+
#define CQUOTE_NODQ 01
70+
size_t quote_c_style(const char *name, struct strbuf *, FILE *, unsigned);
71+
void quote_two_c_style(struct strbuf *, const char *, const char *, unsigned);
6972

7073
void write_name_quoted(const char *name, FILE *, int terminator);
7174
void write_name_quoted_relative(const char *name, const char *prefix,
7275
FILE *fp, int terminator);
7376

7477
/* quote path as relative to the given prefix */
75-
char *quote_path_relative(const char *in, const char *prefix,
76-
struct strbuf *out);
78+
char *quote_path(const char *in, const char *prefix, struct strbuf *out, unsigned flags);
79+
#define QUOTE_PATH_QUOTE_SP 01
7780

7881
/* quoting as a string literal for other languages */
7982
void perl_quote_buf(struct strbuf *sb, const char *src);

t/t7508-status.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,33 @@ test_expect_success 'status -s without relative paths' '
814814
815815
'
816816

817+
cat >expect <<\EOF
818+
M dir1/modified
819+
A dir2/added
820+
A "file with spaces"
821+
?? dir1/untracked
822+
?? dir2/modified
823+
?? dir2/untracked
824+
?? "file with spaces 2"
825+
?? untracked
826+
EOF
827+
828+
test_expect_success 'status -s without relative paths' '
829+
test_when_finished "git rm --cached \"file with spaces\"; rm -f file*" &&
830+
>"file with spaces" &&
831+
>"file with spaces 2" &&
832+
>"expect with spaces" &&
833+
git add "file with spaces" &&
834+
835+
git status -s >output &&
836+
test_cmp expect output &&
837+
838+
git status -s --ignored >output &&
839+
grep "^!! \"expect with spaces\"$" output &&
840+
grep -v "^!! " output >output-wo-ignored &&
841+
test_cmp expect output-wo-ignored
842+
'
843+
817844
test_expect_success 'dry-run of partial commit excluding new file in index' '
818845
cat >expect <<EOF &&
819846
On branch master

0 commit comments

Comments
 (0)