@@ -16,9 +16,12 @@ static const char * const builtin_mv_usage[] = {
16
16
NULL
17
17
};
18
18
19
+ #define DUP_BASENAME 1
20
+ #define KEEP_TRAILING_SLASH 2
21
+
19
22
static const char * * internal_copy_pathspec (const char * prefix ,
20
23
const char * * pathspec ,
21
- int count , int base_name )
24
+ int count , unsigned flags )
22
25
{
23
26
int i ;
24
27
const char * * result = xmalloc ((count + 1 ) * sizeof (const char * ));
@@ -27,11 +30,12 @@ static const char **internal_copy_pathspec(const char *prefix,
27
30
for (i = 0 ; i < count ; i ++ ) {
28
31
int length = strlen (result [i ]);
29
32
int to_copy = length ;
30
- while (to_copy > 0 && is_dir_sep (result [i ][to_copy - 1 ]))
33
+ while (!(flags & KEEP_TRAILING_SLASH ) &&
34
+ to_copy > 0 && is_dir_sep (result [i ][to_copy - 1 ]))
31
35
to_copy -- ;
32
- if (to_copy != length || base_name ) {
36
+ if (to_copy != length || flags & DUP_BASENAME ) {
33
37
char * it = xmemdupz (result [i ], to_copy );
34
- if (base_name ) {
38
+ if (flags & DUP_BASENAME ) {
35
39
result [i ] = xstrdup (basename (it ));
36
40
free (it );
37
41
} else
@@ -87,16 +91,21 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
87
91
88
92
source = internal_copy_pathspec (prefix , argv , argc , 0 );
89
93
modes = xcalloc (argc , sizeof (enum update_mode ));
90
- dest_path = internal_copy_pathspec (prefix , argv + argc , 1 , 0 );
94
+ /*
95
+ * Keep trailing slash, needed to let
96
+ * "git mv file no-such-dir/" error out.
97
+ */
98
+ dest_path = internal_copy_pathspec (prefix , argv + argc , 1 ,
99
+ KEEP_TRAILING_SLASH );
91
100
submodule_gitfile = xcalloc (argc , sizeof (char * ));
92
101
93
102
if (dest_path [0 ][0 ] == '\0' )
94
103
/* special case: "." was normalized to "" */
95
- destination = internal_copy_pathspec (dest_path [0 ], argv , argc , 1 );
104
+ destination = internal_copy_pathspec (dest_path [0 ], argv , argc , DUP_BASENAME );
96
105
else if (!lstat (dest_path [0 ], & st ) &&
97
106
S_ISDIR (st .st_mode )) {
98
107
dest_path [0 ] = add_slash (dest_path [0 ]);
99
- destination = internal_copy_pathspec (dest_path [0 ], argv , argc , 1 );
108
+ destination = internal_copy_pathspec (dest_path [0 ], argv , argc , DUP_BASENAME );
100
109
} else {
101
110
if (argc != 1 )
102
111
die ("destination '%s' is not a directory" , dest_path [0 ]);
@@ -205,6 +214,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
205
214
}
206
215
} else if (string_list_has_string (& src_for_dst , dst ))
207
216
bad = _ ("multiple sources for the same target" );
217
+ else if (is_dir_sep (dst [strlen (dst ) - 1 ]))
218
+ bad = _ ("destination directory does not exist" );
208
219
else
209
220
string_list_insert (& src_for_dst , dst );
210
221
0 commit comments