@@ -16,9 +16,12 @@ static const char * const builtin_mv_usage[] = {
1616 NULL
1717};
1818
19+ #define DUP_BASENAME 1
20+ #define KEEP_TRAILING_SLASH 2
21+
1922static const char * * internal_copy_pathspec (const char * prefix ,
2023 const char * * pathspec ,
21- int count , int base_name )
24+ int count , unsigned flags )
2225{
2326 int i ;
2427 const char * * result = xmalloc ((count + 1 ) * sizeof (const char * ));
@@ -27,11 +30,12 @@ static const char **internal_copy_pathspec(const char *prefix,
2730 for (i = 0 ; i < count ; i ++ ) {
2831 int length = strlen (result [i ]);
2932 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 ]))
3135 to_copy -- ;
32- if (to_copy != length || base_name ) {
36+ if (to_copy != length || flags & DUP_BASENAME ) {
3337 char * it = xmemdupz (result [i ], to_copy );
34- if (base_name ) {
38+ if (flags & DUP_BASENAME ) {
3539 result [i ] = xstrdup (basename (it ));
3640 free (it );
3741 } else
@@ -87,16 +91,21 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
8791
8892 source = internal_copy_pathspec (prefix , argv , argc , 0 );
8993 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 );
91100 submodule_gitfile = xcalloc (argc , sizeof (char * ));
92101
93102 if (dest_path [0 ][0 ] == '\0' )
94103 /* 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 );
96105 else if (!lstat (dest_path [0 ], & st ) &&
97106 S_ISDIR (st .st_mode )) {
98107 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 );
100109 } else {
101110 if (argc != 1 )
102111 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)
205214 }
206215 } else if (string_list_has_string (& src_for_dst , dst ))
207216 bad = _ ("multiple sources for the same target" );
217+ else if (is_dir_sep (dst [strlen (dst ) - 1 ]))
218+ bad = _ ("destination directory does not exist" );
208219 else
209220 string_list_insert (& src_for_dst , dst );
210221
0 commit comments