A dirty move should move the <source> to the <destination>, both in the
working tree and the index, but should *not* remove the resulted path
from the working tree and should *not* turn on its CE_SKIP_WORKTREE bit.>
Helped-by: Derrick Stolee <derrickstolee@xxxxxxxxxx>
Helped-by: Victoria Dye <vdye@xxxxxxxxxx>
Signed-off-by: Shaoxuan Yuan <shaoxuan.yuan02@xxxxxxxxx>
---
builtin/mv.c | 55 +++++++++++++++++++++++++++++------
t/t7002-mv-sparse-checkout.sh | 8 ++---
2 files changed, 50 insertions(+), 13 deletions(-)
diff --git a/builtin/mv.c b/builtin/mv.c
index 1dc55153ed..e4a14aea2d 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -171,12 +171,13 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
};
const char **source, **destination, **dest_path, **submodule_gitfile;
const char *dst_w_slash;
- enum update_mode *modes;
+ enum update_mode *modes, dst_mode = 0;
struct stat st;
struct string_list src_for_dst = STRING_LIST_INIT_NODUP;
struct lock_file lock_file = LOCK_INIT;
struct cache_entry *ce;
struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP;
+ struct string_list dirty_paths = STRING_LIST_INIT_NODUP;
git_config(git_default_config, NULL);
@@ -214,6 +215,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
if (!path_in_sparse_checkout(dst_w_slash, &the_index) &&
empty_dir_has_sparse_contents(dst_w_slash)) {
destination = internal_prefix_pathspec(dst_w_slash, argv, argc, DUP_BASENAME);
+ dst_mode = SKIP_WORKTREE_DIR;
} else if (argc != 1) {
die(_("destination '%s' is not a directory"), dest_path[0]);
} else {
@@ -408,6 +410,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
const char *src = source[i], *dst = destination[i];
enum update_mode mode = modes[i];
int pos;
+ int sparse_and_dirty = 0;
struct checkout state = CHECKOUT_INIT;
state.istate = &the_index;
@@ -418,6 +421,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
if (show_only)
continue;
if (!(mode & (INDEX | SPARSE | SKIP_WORKTREE_DIR)) &&
+ !(dst_mode & SKIP_WORKTREE_DIR) &&
rename(src, dst) < 0) {
if (ignore_errors)
continue;
@@ -437,17 +441,49 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
pos = cache_name_pos(src, strlen(src));
assert(pos >= 0);
+ if (!(mode & SPARSE) && !lstat(src, &st))
+ sparse_and_dirty = ce_modified(active_cache[pos], &st, 0);
rename_cache_entry_at(pos, dst);
- if ((mode & SPARSE) &&
- (path_in_sparse_checkout(dst, &the_index))) {
- int dst_pos;
+ if (ignore_sparse &&
+ core_apply_sparse_checkout &&
+ core_sparse_checkout_cone) {
+ if ((mode & SPARSE) &&
+ path_in_sparse_checkout(dst, &the_index)) {
+ /* from out-of-cone to in-cone */
+ int dst_pos = cache_name_pos(dst, strlen(dst));
+ struct cache_entry *dst_ce = active_cache[dst_pos];
+
+ dst_ce->ce_flags &= ~CE_SKIP_WORKTREE;
+
+ if (checkout_entry(dst_ce, &state, NULL, NULL))
+ die(_("cannot checkout %s"), dst_ce->name);
+ } else if ((dst_mode & SKIP_WORKTREE_DIR) &&
+ !(mode & SPARSE) &&
+ !path_in_sparse_checkout(dst, &the_index)) {
+ /* from in-cone to out-of-cone */
+ int dst_pos = cache_name_pos(dst, strlen(dst));
+ struct cache_entry *dst_ce = active_cache[dst_pos];