Skip to content

Commit 3d231f7

Browse files
pks-tgitster
authored andcommitted
builtin/mv: refactor add_slash() to always return allocated strings
The `add_slash()` function will only conditionally return an allocated string when the passed-in string did not yet have a trailing slash. This makes the memory ownership harder to track than really necessary. It's dubious whether this optimization really buys us all that much. The number of times we execute this function is bounded by the number of arguments to git-mv(1), so in the typical case we may end up saving an allocation or two. Simplify the code to unconditionally return allocated strings. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 11ce77b commit 3d231f7

File tree

1 file changed

+20
-18
lines changed

1 file changed

+20
-18
lines changed

builtin/mv.c

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ static const char **internal_prefix_pathspec(const char *prefix,
7676
return result;
7777
}
7878

79-
static const char *add_slash(const char *path)
79+
static char *add_slash(const char *path)
8080
{
8181
size_t len = strlen(path);
8282
if (len && path[len - 1] != '/') {
@@ -86,7 +86,7 @@ static const char *add_slash(const char *path)
8686
with_slash[len] = 0;
8787
return with_slash;
8888
}
89-
return path;
89+
return xstrdup(path);
9090
}
9191

9292
#define SUBMODULE_WITH_GITDIR ((const char *)1)
@@ -111,7 +111,7 @@ static void prepare_move_submodule(const char *src, int first,
111111
static int index_range_of_same_dir(const char *src, int length,
112112
int *first_p, int *last_p)
113113
{
114-
const char *src_w_slash = add_slash(src);
114+
char *src_w_slash = add_slash(src);
115115
int first, last, len_w_slash = length + 1;
116116

117117
first = index_name_pos(the_repository->index, src_w_slash, len_w_slash);
@@ -124,8 +124,8 @@ static int index_range_of_same_dir(const char *src, int length,
124124
if (strncmp(path, src_w_slash, len_w_slash))
125125
break;
126126
}
127-
if (src_w_slash != src)
128-
free((char *)src_w_slash);
127+
128+
free(src_w_slash);
129129
*first_p = first;
130130
*last_p = last;
131131
return last - first;
@@ -141,7 +141,7 @@ static int index_range_of_same_dir(const char *src, int length,
141141
static int empty_dir_has_sparse_contents(const char *name)
142142
{
143143
int ret = 0;
144-
const char *with_slash = add_slash(name);
144+
char *with_slash = add_slash(name);
145145
int length = strlen(with_slash);
146146

147147
int pos = index_name_pos(the_repository->index, with_slash, length);
@@ -159,8 +159,7 @@ static int empty_dir_has_sparse_contents(const char *name)
159159
}
160160

161161
free_return:
162-
if (with_slash != name)
163-
free((char *)with_slash);
162+
free(with_slash);
164163
return ret;
165164
}
166165

@@ -178,7 +177,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
178177
OPT_END(),
179178
};
180179
const char **source, **destination, **dest_path, **submodule_gitfile;
181-
const char *dst_w_slash;
180+
char *dst_w_slash = NULL;
182181
const char **src_dir = NULL;
183182
int src_dir_nr = 0, src_dir_alloc = 0;
184183
struct strbuf a_src_dir = STRBUF_INIT;
@@ -243,10 +242,6 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
243242
dst_mode = SPARSE;
244243
}
245244
}
246-
if (dst_w_slash != dest_path[0]) {
247-
free((char *)dst_w_slash);
248-
dst_w_slash = NULL;
249-
}
250245

251246
/* Checking */
252247
for (i = 0; i < argc; i++) {
@@ -265,12 +260,14 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
265260

266261
pos = index_name_pos(the_repository->index, src, length);
267262
if (pos < 0) {
268-
const char *src_w_slash = add_slash(src);
263+
char *src_w_slash = add_slash(src);
269264
if (!path_in_sparse_checkout(src_w_slash, the_repository->index) &&
270265
empty_dir_has_sparse_contents(src)) {
266+
free(src_w_slash);
271267
modes[i] |= SKIP_WORKTREE_DIR;
272268
goto dir_check;
273269
}
270+
free(src_w_slash);
274271
/* only error if existence is expected. */
275272
if (!(modes[i] & SPARSE))
276273
bad = _("bad source");
@@ -310,7 +307,9 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
310307

311308
dir_check:
312309
if (S_ISDIR(st.st_mode)) {
313-
int j, dst_len, n;
310+
char *dst_with_slash;
311+
size_t dst_with_slash_len;
312+
int j, n;
314313
int first = index_name_pos(the_repository->index, src, length), last;
315314

316315
if (first >= 0) {
@@ -335,19 +334,21 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
335334
REALLOC_ARRAY(modes, n);
336335
REALLOC_ARRAY(submodule_gitfile, n);
337336

338-
dst = add_slash(dst);
339-
dst_len = strlen(dst);
337+
dst_with_slash = add_slash(dst);
338+
dst_with_slash_len = strlen(dst_with_slash);
340339

341340
for (j = 0; j < last - first; j++) {
342341
const struct cache_entry *ce = the_repository->index->cache[first + j];
343342
const char *path = ce->name;
344343
source[argc + j] = path;
345344
destination[argc + j] =
346-
prefix_path(dst, dst_len, path + length + 1);
345+
prefix_path(dst_with_slash, dst_with_slash_len, path + length + 1);
347346
memset(modes + argc + j, 0, sizeof(enum update_mode));
348347
modes[argc + j] |= ce_skip_worktree(ce) ? SPARSE : INDEX;
349348
submodule_gitfile[argc + j] = NULL;
350349
}
350+
351+
free(dst_with_slash);
351352
argc += last - first;
352353
goto act_on_entry;
353354
}
@@ -565,6 +566,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
565566
COMMIT_LOCK | SKIP_IF_UNCHANGED))
566567
die(_("Unable to write new index file"));
567568

569+
free(dst_w_slash);
568570
string_list_clear(&src_for_dst, 0);
569571
string_list_clear(&dirty_paths, 0);
570572
UNLEAK(source);

0 commit comments

Comments
 (0)