20
20
#include "read-cache-ll.h"
21
21
#include "repository.h"
22
22
#include "setup.h"
23
+ #include "strvec.h"
23
24
#include "submodule.h"
24
25
#include "entry.h"
25
26
@@ -38,42 +39,32 @@ enum update_mode {
38
39
#define DUP_BASENAME 1
39
40
#define KEEP_TRAILING_SLASH 2
40
41
41
- static const char * * internal_prefix_pathspec (const char * prefix ,
42
- const char * * pathspec ,
43
- int count , unsigned flags )
42
+ static void internal_prefix_pathspec (struct strvec * out ,
43
+ const char * prefix ,
44
+ const char * * pathspec ,
45
+ int count , unsigned flags )
44
46
{
45
- int i ;
46
- const char * * result ;
47
47
int prefixlen = prefix ? strlen (prefix ) : 0 ;
48
- ALLOC_ARRAY (result , count + 1 );
49
48
50
49
/* Create an intermediate copy of the pathspec based on the flags */
51
- for (i = 0 ; i < count ; i ++ ) {
52
- int length = strlen (pathspec [i ]);
53
- int to_copy = length ;
54
- char * it ;
50
+ for (int i = 0 ; i < count ; i ++ ) {
51
+ size_t length = strlen (pathspec [i ]);
52
+ size_t to_copy = length ;
53
+ const char * maybe_basename ;
54
+ char * trimmed , * prefixed_path ;
55
+
55
56
while (!(flags & KEEP_TRAILING_SLASH ) &&
56
57
to_copy > 0 && is_dir_sep (pathspec [i ][to_copy - 1 ]))
57
58
to_copy -- ;
58
59
59
- it = xmemdupz (pathspec [i ], to_copy );
60
- if (flags & DUP_BASENAME ) {
61
- result [i ] = xstrdup (basename (it ));
62
- free (it );
63
- } else {
64
- result [i ] = it ;
65
- }
66
- }
67
- result [count ] = NULL ;
60
+ trimmed = xmemdupz (pathspec [i ], to_copy );
61
+ maybe_basename = (flags & DUP_BASENAME ) ? basename (trimmed ) : trimmed ;
62
+ prefixed_path = prefix_path (prefix , prefixlen , maybe_basename );
63
+ strvec_push (out , prefixed_path );
68
64
69
- /* Prefix the pathspec and free the old intermediate strings */
70
- for (i = 0 ; i < count ; i ++ ) {
71
- const char * match = prefix_path (prefix , prefixlen , result [i ]);
72
- free ((char * ) result [i ]);
73
- result [i ] = match ;
65
+ free (prefixed_path );
66
+ free (trimmed );
74
67
}
75
-
76
- return result ;
77
68
}
78
69
79
70
static char * add_slash (const char * path )
@@ -176,7 +167,10 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
176
167
OPT_BOOL (0 , "sparse" , & ignore_sparse , N_ ("allow updating entries outside of the sparse-checkout cone" )),
177
168
OPT_END (),
178
169
};
179
- const char * * source , * * destination , * * dest_path , * * submodule_gitfile ;
170
+ struct strvec sources = STRVEC_INIT ;
171
+ struct strvec dest_paths = STRVEC_INIT ;
172
+ struct strvec destinations = STRVEC_INIT ;
173
+ const char * * submodule_gitfile ;
180
174
char * dst_w_slash = NULL ;
181
175
const char * * src_dir = NULL ;
182
176
int src_dir_nr = 0 , src_dir_alloc = 0 ;
@@ -201,7 +195,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
201
195
if (repo_read_index (the_repository ) < 0 )
202
196
die (_ ("index file corrupt" ));
203
197
204
- source = internal_prefix_pathspec (prefix , argv , argc , 0 );
198
+ internal_prefix_pathspec (& sources , prefix , argv , argc , 0 );
205
199
CALLOC_ARRAY (modes , argc );
206
200
207
201
/*
@@ -212,41 +206,39 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
212
206
flags = KEEP_TRAILING_SLASH ;
213
207
if (argc == 1 && is_directory (argv [0 ]) && !is_directory (argv [1 ]))
214
208
flags = 0 ;
215
- dest_path = internal_prefix_pathspec (prefix , argv + argc , 1 , flags );
216
- dst_w_slash = add_slash (dest_path [0 ]);
209
+ internal_prefix_pathspec (& dest_paths , prefix , argv + argc , 1 , flags );
210
+ dst_w_slash = add_slash (dest_paths . v [0 ]);
217
211
submodule_gitfile = xcalloc (argc , sizeof (char * ));
218
212
219
- if (dest_path [0 ][0 ] == '\0' )
213
+ if (dest_paths . v [0 ][0 ] == '\0' )
220
214
/* special case: "." was normalized to "" */
221
- destination = internal_prefix_pathspec (dest_path [0 ], argv , argc , DUP_BASENAME );
222
- else if (!lstat (dest_path [0 ], & st ) &&
223
- S_ISDIR (st .st_mode )) {
224
- destination = internal_prefix_pathspec (dst_w_slash , argv , argc , DUP_BASENAME );
215
+ internal_prefix_pathspec (& destinations , dest_paths .v [0 ], argv , argc , DUP_BASENAME );
216
+ else if (!lstat (dest_paths .v [0 ], & st ) && S_ISDIR (st .st_mode )) {
217
+ internal_prefix_pathspec (& destinations , dst_w_slash , argv , argc , DUP_BASENAME );
218
+ } else if (!path_in_sparse_checkout (dst_w_slash , the_repository -> index ) &&
219
+ empty_dir_has_sparse_contents (dst_w_slash )) {
220
+ internal_prefix_pathspec (& destinations , dst_w_slash , argv , argc , DUP_BASENAME );
221
+ dst_mode = SKIP_WORKTREE_DIR ;
222
+ } else if (argc != 1 ) {
223
+ die (_ ("destination '%s' is not a directory" ), dest_paths .v [0 ]);
225
224
} else {
226
- if (!path_in_sparse_checkout (dst_w_slash , the_repository -> index ) &&
227
- empty_dir_has_sparse_contents (dst_w_slash )) {
228
- destination = internal_prefix_pathspec (dst_w_slash , argv , argc , DUP_BASENAME );
229
- dst_mode = SKIP_WORKTREE_DIR ;
230
- } else if (argc != 1 ) {
231
- die (_ ("destination '%s' is not a directory" ), dest_path [0 ]);
232
- } else {
233
- destination = dest_path ;
234
- /*
235
- * <destination> is a file outside of sparse-checkout
236
- * cone. Insist on cone mode here for backward
237
- * compatibility. We don't want dst_mode to be assigned
238
- * for a file when the repo is using no-cone mode (which
239
- * is deprecated at this point) sparse-checkout. As
240
- * SPARSE here is only considering cone-mode situation.
241
- */
242
- if (!path_in_cone_mode_sparse_checkout (destination [0 ], the_repository -> index ))
243
- dst_mode = SPARSE ;
244
- }
225
+ strvec_pushv (& destinations , dest_paths .v );
226
+
227
+ /*
228
+ * <destination> is a file outside of sparse-checkout
229
+ * cone. Insist on cone mode here for backward
230
+ * compatibility. We don't want dst_mode to be assigned
231
+ * for a file when the repo is using no-cone mode (which
232
+ * is deprecated at this point) sparse-checkout. As
233
+ * SPARSE here is only considering cone-mode situation.
234
+ */
235
+ if (!path_in_cone_mode_sparse_checkout (destinations .v [0 ], the_repository -> index ))
236
+ dst_mode = SPARSE ;
245
237
}
246
238
247
239
/* Checking */
248
240
for (i = 0 ; i < argc ; i ++ ) {
249
- const char * src = source [i ], * dst = destination [i ];
241
+ const char * src = sources . v [i ], * dst = destinations . v [i ];
250
242
int length ;
251
243
const char * bad = NULL ;
252
244
int skip_sparse = 0 ;
@@ -330,8 +322,6 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
330
322
src_dir [src_dir_nr ++ ] = src ;
331
323
332
324
n = argc + last - first ;
333
- REALLOC_ARRAY (source , n );
334
- REALLOC_ARRAY (destination , n );
335
325
REALLOC_ARRAY (modes , n );
336
326
REALLOC_ARRAY (submodule_gitfile , n );
337
327
@@ -341,12 +331,16 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
341
331
for (j = 0 ; j < last - first ; j ++ ) {
342
332
const struct cache_entry * ce = the_repository -> index -> cache [first + j ];
343
333
const char * path = ce -> name ;
344
- source [argc + j ] = path ;
345
- destination [argc + j ] =
346
- prefix_path (dst_with_slash , dst_with_slash_len , path + length + 1 );
334
+ char * prefixed_path = prefix_path (dst_with_slash , dst_with_slash_len , path + length + 1 );
335
+
336
+ strvec_push (& sources , path );
337
+ strvec_push (& destinations , prefixed_path );
338
+
347
339
memset (modes + argc + j , 0 , sizeof (enum update_mode ));
348
340
modes [argc + j ] |= ce_skip_worktree (ce ) ? SPARSE : INDEX ;
349
341
submodule_gitfile [argc + j ] = NULL ;
342
+
343
+ free (prefixed_path );
350
344
}
351
345
352
346
free (dst_with_slash );
@@ -430,8 +424,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
430
424
remove_entry :
431
425
if (-- argc > 0 ) {
432
426
int n = argc - i ;
433
- MOVE_ARRAY ( source + i , source + i + 1 , n );
434
- MOVE_ARRAY ( destination + i , destination + i + 1 , n );
427
+ strvec_remove ( & sources , i );
428
+ strvec_remove ( & destinations , i );
435
429
MOVE_ARRAY (modes + i , modes + i + 1 , n );
436
430
MOVE_ARRAY (submodule_gitfile + i ,
437
431
submodule_gitfile + i + 1 , n );
@@ -448,7 +442,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
448
442
}
449
443
450
444
for (i = 0 ; i < argc ; i ++ ) {
451
- const char * src = source [i ], * dst = destination [i ];
445
+ const char * src = sources . v [i ], * dst = destinations . v [i ];
452
446
enum update_mode mode = modes [i ];
453
447
int pos ;
454
448
int sparse_and_dirty = 0 ;
@@ -576,8 +570,9 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
576
570
string_list_clear (& src_for_dst , 0 );
577
571
string_list_clear (& dirty_paths , 0 );
578
572
string_list_clear (& only_match_skip_worktree , 0 );
579
- UNLEAK (source );
580
- UNLEAK (dest_path );
573
+ strvec_clear (& sources );
574
+ strvec_clear (& dest_paths );
575
+ strvec_clear (& destinations );
581
576
free (submodule_gitfile );
582
577
free (modes );
583
578
return ret ;
0 commit comments