mv: remove use of deprecated 'get_pathspec()'

Convert the 'internal_copy_pathspec()' function to 'prefix_path()' instead of using the deprecated 'get_pathspec()' interface. Also, rename 'internal_copy_pathspec()' to 'internal_prefix_pathspec()' to be more descriptive of what the funciton is actually doing. In addition to this, fix a memory leak caused by only duplicating some of the pathspec elements. Instead always duplicate all of the the pathspec elements as an intermediate step (with modificationed based on the passed in flags). This way the intermediate strings can then be freed after getting the result from 'prefix_path()'. Signed-off-by: Brandon Williams <bmwill@google.com> Reviewed-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Brandon Williams committed Jan 4, 2017 at 10:03 UTC 2ec87741b2d2935542b13d407fbeedbe0a7af094
1 file changed +31 -19
builtin/mv.c
+31 -19
@@ -4,6 +4,7 @@
4 * Copyright (C) 2006 Johannes Schindelin
5 */
6 #include "builtin.h"
7 +#include "pathspec.h"
8 #include "lockfile.h"
9 #include "dir.h"
10 #include "cache-tree.h"
@@ -19,31 +20,42 @@ static const char * const builtin_mv_usage[] = {
20 #define DUP_BASENAME 1
21 #define KEEP_TRAILING_SLASH 2
22
22 -static const char **internal_copy_pathspec(const char *prefix,
23 - const char **pathspec,
24 - int count, unsigned flags)
23 +static const char **internal_prefix_pathspec(const char *prefix,
24 + const char **pathspec,
25 + int count, unsigned flags)
26 {
27 int i;
28 const char **result;
29 + int prefixlen = prefix ? strlen(prefix) : 0;
30 ALLOC_ARRAY(result, count + 1);
29 - COPY_ARRAY(result, pathspec, count);
30 - result[count] = NULL;
31 +
32 + /* Create an intermediate copy of the pathspec based on the flags */
33 for (i = 0; i < count; i++) {
32 - int length = strlen(result[i]);
34 + int length = strlen(pathspec[i]);
35 int to_copy = length;
36 + char *it;
37 while (!(flags & KEEP_TRAILING_SLASH) &&
35 - to_copy > 0 && is_dir_sep(result[i][to_copy - 1]))
38 + to_copy > 0 && is_dir_sep(pathspec[i][to_copy - 1]))
39 to_copy--;
37 - if (to_copy != length || flags & DUP_BASENAME) {
38 - char *it = xmemdupz(result[i], to_copy);
39 - if (flags & DUP_BASENAME) {
40 - result[i] = xstrdup(basename(it));
41 - free(it);
42 - } else
43 - result[i] = it;
40 +
41 + it = xmemdupz(pathspec[i], to_copy);
42 + if (flags & DUP_BASENAME) {
43 + result[i] = xstrdup(basename(it));
44 + free(it);
45 + } else {
46 + result[i] = it;
47 }
48 }
46 - return get_pathspec(prefix, result);
49 + result[count] = NULL;
50 +
51 + /* Prefix the pathspec and free the old intermediate strings */
52 + for (i = 0; i < count; i++) {
53 + const char *match = prefix_path(prefix, prefixlen, result[i]);
54 + free((char *) result[i]);
55 + result[i] = match;
56 + }
57 +
58 + return result;
59 }
60
61 static const char *add_slash(const char *path)
@@ -130,7 +142,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
142 if (read_cache() < 0)
143 die(_("index file corrupt"));
144
133 - source = internal_copy_pathspec(prefix, argv, argc, 0);
145 + source = internal_prefix_pathspec(prefix, argv, argc, 0);
146 modes = xcalloc(argc, sizeof(enum update_mode));
147 /*
148 * Keep trailing slash, needed to let
@@ -140,16 +152,16 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
152 flags = KEEP_TRAILING_SLASH;
153 if (argc == 1 && is_directory(argv[0]) && !is_directory(argv[1]))
154 flags = 0;
143 - dest_path = internal_copy_pathspec(prefix, argv + argc, 1, flags);
155 + dest_path = internal_prefix_pathspec(prefix, argv + argc, 1, flags);
156 submodule_gitfile = xcalloc(argc, sizeof(char *));
157
158 if (dest_path[0][0] == '\0')
159 /* special case: "." was normalized to "" */
148 - destination = internal_copy_pathspec(dest_path[0], argv, argc, DUP_BASENAME);
160 + destination = internal_prefix_pathspec(dest_path[0], argv, argc, DUP_BASENAME);
161 else if (!lstat(dest_path[0], &st) &&
162 S_ISDIR(st.st_mode)) {
163 dest_path[0] = add_slash(dest_path[0]);
152 - destination = internal_copy_pathspec(dest_path[0], argv, argc, DUP_BASENAME);
164 + destination = internal_prefix_pathspec(dest_path[0], argv, argc, DUP_BASENAME);
165 } else {
166 if (argc != 1)
167 die(_("destination '%s' is not a directory"), dest_path[0]);