@@ -2210,7 +2210,7 @@ static int parse_mapped_oid_hex(const char *hex, struct object_id *oid, const ch
2210
2210
*
2211
2211
* idnum ::= ':' bigint;
2212
2212
*
2213
- * Return the first character after the value in *endptr .
2213
+ * Update *endptr to point to the first character after the value.
2214
2214
*
2215
2215
* Complain if the following character is not what is expected,
2216
2216
* either a space or end of the string.
@@ -2243,8 +2243,8 @@ static uintmax_t parse_mark_ref_eol(const char *p)
2243
2243
}
2244
2244
2245
2245
/*
2246
- * Parse the mark reference, demanding a trailing space. Return a
2247
- * pointer to the space.
2246
+ * Parse the mark reference, demanding a trailing space. Update *p to
2247
+ * point to the first character after the space.
2248
2248
*/
2249
2249
static uintmax_t parse_mark_ref_space (const char * * p )
2250
2250
{
@@ -2258,10 +2258,62 @@ static uintmax_t parse_mark_ref_space(const char **p)
2258
2258
return mark ;
2259
2259
}
2260
2260
2261
+ /*
2262
+ * Parse the path string into the strbuf. The path can either be quoted with
2263
+ * escape sequences or unquoted without escape sequences. Unquoted strings may
2264
+ * contain spaces only if `is_last_field` is nonzero; otherwise, it stops
2265
+ * parsing at the first space.
2266
+ */
2267
+ static void parse_path (struct strbuf * sb , const char * p , const char * * endp ,
2268
+ int is_last_field , const char * field )
2269
+ {
2270
+ if (* p == '"' ) {
2271
+ if (unquote_c_style (sb , p , endp ))
2272
+ die ("Invalid %s: %s" , field , command_buf .buf );
2273
+ if (strlen (sb -> buf ) != sb -> len )
2274
+ die ("NUL in %s: %s" , field , command_buf .buf );
2275
+ } else {
2276
+ /*
2277
+ * Unless we are parsing the last field of a line,
2278
+ * SP is the end of this field.
2279
+ */
2280
+ * endp = is_last_field
2281
+ ? p + strlen (p )
2282
+ : strchrnul (p , ' ' );
2283
+ strbuf_add (sb , p , * endp - p );
2284
+ }
2285
+ }
2286
+
2287
+ /*
2288
+ * Parse the path string into the strbuf, and complain if this is not the end of
2289
+ * the string. Unquoted strings may contain spaces.
2290
+ */
2291
+ static void parse_path_eol (struct strbuf * sb , const char * p , const char * field )
2292
+ {
2293
+ const char * end ;
2294
+
2295
+ parse_path (sb , p , & end , 1 , field );
2296
+ if (* end )
2297
+ die ("Garbage after %s: %s" , field , command_buf .buf );
2298
+ }
2299
+
2300
+ /*
2301
+ * Parse the path string into the strbuf, and ensure it is followed by a space.
2302
+ * Unquoted strings may not contain spaces. Update *endp to point to the first
2303
+ * character after the space.
2304
+ */
2305
+ static void parse_path_space (struct strbuf * sb , const char * p ,
2306
+ const char * * endp , const char * field )
2307
+ {
2308
+ parse_path (sb , p , endp , 0 , field );
2309
+ if (* * endp != ' ' )
2310
+ die ("Missing space after %s: %s" , field , command_buf .buf );
2311
+ (* endp )++ ;
2312
+ }
2313
+
2261
2314
static void file_change_m (const char * p , struct branch * b )
2262
2315
{
2263
- static struct strbuf uq = STRBUF_INIT ;
2264
- const char * endp ;
2316
+ static struct strbuf path = STRBUF_INIT ;
2265
2317
struct object_entry * oe ;
2266
2318
struct object_id oid ;
2267
2319
uint16_t mode , inline_data = 0 ;
@@ -2298,16 +2350,12 @@ static void file_change_m(const char *p, struct branch *b)
2298
2350
die ("Missing space after SHA1: %s" , command_buf .buf );
2299
2351
}
2300
2352
2301
- strbuf_reset (& uq );
2302
- if (!unquote_c_style (& uq , p , & endp )) {
2303
- if (* endp )
2304
- die ("Garbage after path in: %s" , command_buf .buf );
2305
- p = uq .buf ;
2306
- }
2353
+ strbuf_reset (& path );
2354
+ parse_path_eol (& path , p , "path" );
2307
2355
2308
2356
/* Git does not track empty, non-toplevel directories. */
2309
- if (S_ISDIR (mode ) && is_empty_tree_oid (& oid ) && * p ) {
2310
- tree_content_remove (& b -> branch_tree , p , NULL , 0 );
2357
+ if (S_ISDIR (mode ) && is_empty_tree_oid (& oid ) && * path . buf ) {
2358
+ tree_content_remove (& b -> branch_tree , path . buf , NULL , 0 );
2311
2359
return ;
2312
2360
}
2313
2361
@@ -2328,10 +2376,6 @@ static void file_change_m(const char *p, struct branch *b)
2328
2376
if (S_ISDIR (mode ))
2329
2377
die ("Directories cannot be specified 'inline': %s" ,
2330
2378
command_buf .buf );
2331
- if (p != uq .buf ) {
2332
- strbuf_addstr (& uq , p );
2333
- p = uq .buf ;
2334
- }
2335
2379
while (read_next_command () != EOF ) {
2336
2380
const char * v ;
2337
2381
if (skip_prefix (command_buf .buf , "cat-blob " , & v ))
@@ -2357,82 +2401,55 @@ static void file_change_m(const char *p, struct branch *b)
2357
2401
command_buf .buf );
2358
2402
}
2359
2403
2360
- if (!* p ) {
2404
+ if (!* path . buf ) {
2361
2405
tree_content_replace (& b -> branch_tree , & oid , mode , NULL );
2362
2406
return ;
2363
2407
}
2364
- tree_content_set (& b -> branch_tree , p , & oid , mode , NULL );
2408
+ tree_content_set (& b -> branch_tree , path . buf , & oid , mode , NULL );
2365
2409
}
2366
2410
2367
2411
static void file_change_d (const char * p , struct branch * b )
2368
2412
{
2369
- static struct strbuf uq = STRBUF_INIT ;
2370
- const char * endp ;
2413
+ static struct strbuf path = STRBUF_INIT ;
2371
2414
2372
- strbuf_reset (& uq );
2373
- if (!unquote_c_style (& uq , p , & endp )) {
2374
- if (* endp )
2375
- die ("Garbage after path in: %s" , command_buf .buf );
2376
- p = uq .buf ;
2377
- }
2378
- tree_content_remove (& b -> branch_tree , p , NULL , 1 );
2415
+ strbuf_reset (& path );
2416
+ parse_path_eol (& path , p , "path" );
2417
+ tree_content_remove (& b -> branch_tree , path .buf , NULL , 1 );
2379
2418
}
2380
2419
2381
- static void file_change_cr (const char * s , struct branch * b , int rename )
2420
+ static void file_change_cr (const char * p , struct branch * b , int rename )
2382
2421
{
2383
- const char * d ;
2384
- static struct strbuf s_uq = STRBUF_INIT ;
2385
- static struct strbuf d_uq = STRBUF_INIT ;
2386
- const char * endp ;
2422
+ static struct strbuf source = STRBUF_INIT ;
2423
+ static struct strbuf dest = STRBUF_INIT ;
2387
2424
struct tree_entry leaf ;
2388
2425
2389
- strbuf_reset (& s_uq );
2390
- if (!unquote_c_style (& s_uq , s , & endp )) {
2391
- if (* endp != ' ' )
2392
- die ("Missing space after source: %s" , command_buf .buf );
2393
- } else {
2394
- endp = strchr (s , ' ' );
2395
- if (!endp )
2396
- die ("Missing space after source: %s" , command_buf .buf );
2397
- strbuf_add (& s_uq , s , endp - s );
2398
- }
2399
- s = s_uq .buf ;
2400
-
2401
- endp ++ ;
2402
- if (!* endp )
2403
- die ("Missing dest: %s" , command_buf .buf );
2404
-
2405
- d = endp ;
2406
- strbuf_reset (& d_uq );
2407
- if (!unquote_c_style (& d_uq , d , & endp )) {
2408
- if (* endp )
2409
- die ("Garbage after dest in: %s" , command_buf .buf );
2410
- d = d_uq .buf ;
2411
- }
2426
+ strbuf_reset (& source );
2427
+ parse_path_space (& source , p , & p , "source" );
2428
+ strbuf_reset (& dest );
2429
+ parse_path_eol (& dest , p , "dest" );
2412
2430
2413
2431
memset (& leaf , 0 , sizeof (leaf ));
2414
2432
if (rename )
2415
- tree_content_remove (& b -> branch_tree , s , & leaf , 1 );
2433
+ tree_content_remove (& b -> branch_tree , source . buf , & leaf , 1 );
2416
2434
else
2417
- tree_content_get (& b -> branch_tree , s , & leaf , 1 );
2435
+ tree_content_get (& b -> branch_tree , source . buf , & leaf , 1 );
2418
2436
if (!leaf .versions [1 ].mode )
2419
- die ("Path %s not in branch" , s );
2420
- if (!* d ) { /* C "path/to/subdir" "" */
2437
+ die ("Path %s not in branch" , source . buf );
2438
+ if (!* dest . buf ) { /* C "path/to/subdir" "" */
2421
2439
tree_content_replace (& b -> branch_tree ,
2422
2440
& leaf .versions [1 ].oid ,
2423
2441
leaf .versions [1 ].mode ,
2424
2442
leaf .tree );
2425
2443
return ;
2426
2444
}
2427
- tree_content_set (& b -> branch_tree , d ,
2445
+ tree_content_set (& b -> branch_tree , dest . buf ,
2428
2446
& leaf .versions [1 ].oid ,
2429
2447
leaf .versions [1 ].mode ,
2430
2448
leaf .tree );
2431
2449
}
2432
2450
2433
2451
static void note_change_n (const char * p , struct branch * b , unsigned char * old_fanout )
2434
2452
{
2435
- static struct strbuf uq = STRBUF_INIT ;
2436
2453
struct object_entry * oe ;
2437
2454
struct branch * s ;
2438
2455
struct object_id oid , commit_oid ;
@@ -2497,10 +2514,6 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa
2497
2514
die ("Invalid ref name or SHA1 expression: %s" , p );
2498
2515
2499
2516
if (inline_data ) {
2500
- if (p != uq .buf ) {
2501
- strbuf_addstr (& uq , p );
2502
- p = uq .buf ;
2503
- }
2504
2517
read_next_command ();
2505
2518
parse_and_store_blob (& last_blob , & oid , 0 );
2506
2519
} else if (oe ) {
@@ -3152,6 +3165,7 @@ static void print_ls(int mode, const unsigned char *hash, const char *path)
3152
3165
3153
3166
static void parse_ls (const char * p , struct branch * b )
3154
3167
{
3168
+ static struct strbuf path = STRBUF_INIT ;
3155
3169
struct tree_entry * root = NULL ;
3156
3170
struct tree_entry leaf = {NULL };
3157
3171
@@ -3168,25 +3182,17 @@ static void parse_ls(const char *p, struct branch *b)
3168
3182
root -> versions [1 ].mode = S_IFDIR ;
3169
3183
load_tree (root );
3170
3184
}
3171
- if (* p == '"' ) {
3172
- static struct strbuf uq = STRBUF_INIT ;
3173
- const char * endp ;
3174
- strbuf_reset (& uq );
3175
- if (unquote_c_style (& uq , p , & endp ))
3176
- die ("Invalid path: %s" , command_buf .buf );
3177
- if (* endp )
3178
- die ("Garbage after path in: %s" , command_buf .buf );
3179
- p = uq .buf ;
3180
- }
3181
- tree_content_get (root , p , & leaf , 1 );
3185
+ strbuf_reset (& path );
3186
+ parse_path_eol (& path , p , "path" );
3187
+ tree_content_get (root , path .buf , & leaf , 1 );
3182
3188
/*
3183
3189
* A directory in preparation would have a sha1 of zero
3184
3190
* until it is saved. Save, for simplicity.
3185
3191
*/
3186
3192
if (S_ISDIR (leaf .versions [1 ].mode ))
3187
3193
store_tree (& leaf );
3188
3194
3189
- print_ls (leaf .versions [1 ].mode , leaf .versions [1 ].oid .hash , p );
3195
+ print_ls (leaf .versions [1 ].mode , leaf .versions [1 ].oid .hash , path . buf );
3190
3196
if (leaf .tree )
3191
3197
release_tree_content_recursive (leaf .tree );
3192
3198
if (!b || root != & b -> branch_tree )
0 commit comments