summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/mv.c99
-rwxr-xr-xt/t7001-mv.sh34
2 files changed, 86 insertions, 47 deletions
diff --git a/builtin/mv.c b/builtin/mv.c
index 16ce99b..1d3ef63 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -118,55 +118,60 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
&& lstat(dst, &st) == 0)
bad = _("cannot move directory over file");
else if (src_is_dir) {
- const char *src_w_slash = add_slash(src);
- int len_w_slash = length + 1;
- int first, last;
-
- modes[i] = WORKING_DIRECTORY;
-
- first = cache_name_pos(src_w_slash, len_w_slash);
- if (first >= 0)
- die (_("Huh? %.*s is in index?"),
- len_w_slash, src_w_slash);
-
- first = -1 - first;
- for (last = first; last < active_nr; last++) {
- const char *path = active_cache[last]->name;
- if (strncmp(path, src_w_slash, len_w_slash))
- break;
- }
- free((char *)src_w_slash);
-
- if (last - first < 1)
- bad = _("source directory is empty");
- else {
- int j, dst_len;
-
- if (last - first > 0) {
- source = xrealloc(source,
- (argc + last - first)
- * sizeof(char *));
- destination = xrealloc(destination,
- (argc + last - first)
- * sizeof(char *));
- modes = xrealloc(modes,
- (argc + last - first)
- * sizeof(enum update_mode));
+ int first = cache_name_pos(src, length);
+ if (first >= 0) {
+ if (!S_ISGITLINK(active_cache[first]->ce_mode))
+ die (_("Huh? Directory %s is in index and no submodule?"), src);
+ } else {
+ const char *src_w_slash = add_slash(src);
+ int last, len_w_slash = length + 1;
+
+ modes[i] = WORKING_DIRECTORY;
+
+ first = cache_name_pos(src_w_slash, len_w_slash);
+ if (first >= 0)
+ die (_("Huh? %.*s is in index?"),
+ len_w_slash, src_w_slash);
+
+ first = -1 - first;
+ for (last = first; last < active_nr; last++) {
+ const char *path = active_cache[last]->name;
+ if (strncmp(path, src_w_slash, len_w_slash))
+ break;
}
-
- dst = add_slash(dst);
- dst_len = strlen(dst);
-
- for (j = 0; j < last - first; j++) {
- const char *path =
- active_cache[first + j]->name;
- source[argc + j] = path;
- destination[argc + j] =
- prefix_path(dst, dst_len,
- path + length + 1);
- modes[argc + j] = INDEX;
+ free((char *)src_w_slash);
+
+ if (last - first < 1)
+ bad = _("source directory is empty");
+ else {
+ int j, dst_len;
+
+ if (last - first > 0) {
+ source = xrealloc(source,
+ (argc + last - first)
+ * sizeof(char *));
+ destination = xrealloc(destination,
+ (argc + last - first)
+ * sizeof(char *));
+ modes = xrealloc(modes,
+ (argc + last - first)
+ * sizeof(enum update_mode));
+ }
+
+ dst = add_slash(dst);
+ dst_len = strlen(dst);
+
+ for (j = 0; j < last - first; j++) {
+ const char *path =
+ active_cache[first + j]->name;
+ source[argc + j] = path;
+ destination[argc + j] =
+ prefix_path(dst, dst_len,
+ path + length + 1);
+ modes[argc + j] = INDEX;
+ }
+ argc += last - first;
}
- argc += last - first;
}
} else if (cache_name_pos(src, length) < 0)
bad = _("not under version control");
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index 101816e..15c18b6 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -259,4 +259,38 @@ test_expect_success SYMLINKS 'check moved symlink' '
rm -f moved symlink
+test_expect_success 'setup submodule' '
+ git commit -m initial &&
+ git reset --hard &&
+ git submodule add ./. sub &&
+ echo content >file &&
+ git add file &&
+ git commit -m "added sub and file"
+'
+
+test_expect_success 'git mv cannot move a submodule in a file' '
+ test_must_fail git mv sub file
+'
+
+test_expect_success 'git mv moves a submodule with a .git directory and no .gitmodules' '
+ entry="$(git ls-files --stage sub | cut -f 1)" &&
+ git rm .gitmodules &&
+ (
+ cd sub &&
+ rm -f .git &&
+ cp -a ../.git/modules/sub .git &&
+ GIT_WORK_TREE=. git config --unset core.worktree
+ ) &&
+ mkdir mod &&
+ git mv sub mod/sub &&
+ ! test -e sub &&
+ [ "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" ] &&
+ (
+ cd mod/sub &&
+ git status
+ ) &&
+ git update-index --refresh &&
+ git diff-files --quiet
+'
+
test_done