Skip to content

Commit d56770f

Browse files
committed
sparse-index: mark mv as sparse-index compatible
In-cone moves already work without expanding the index, since index_name_pos() auto-expands sparse directory entries on demand. For out-of-cone moves (--sparse), call ensure_full_index() up front because the bulk iteration assumes individual file entries. Without --sparse, moving a sparse directory should produce the helpful "Use the --sparse option" hint. The old code relied on full index expansion to make the individual skip-worktree entries visible to the error path. Now that the index stays sparse, teach empty_dir_has_sparse_contents() to recognize sparse directory entries directly and short-circuit to the hint. As a side effect the error now names the directory the user typed rather than listing each file inside it. Add tests verifying that in-cone renames do not expand the index, that out-of-cone moves without --sparse produce the hint, and that --sparse triggers expansion. Signed-off-by: Kristofer Karlsson <krka@spotify.com>
1 parent 695dc7b commit d56770f

3 files changed

Lines changed: 33 additions & 3 deletions

File tree

builtin/mv.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "strvec.h"
2929
#include "submodule.h"
3030
#include "entry.h"
31+
#include "sparse-index.h"
3132

3233
static const char * const builtin_mv_usage[] = {
3334
N_("git mv [-v] [-f] [-n] [-k] <source> <destination>"),
@@ -153,7 +154,11 @@ static int empty_dir_has_sparse_contents(const char *name)
153154
int pos = index_name_pos(the_repository->index, with_slash, length);
154155
const struct cache_entry *ce;
155156

156-
if (pos < 0) {
157+
if (pos >= 0) {
158+
ce = the_repository->index->cache[pos];
159+
if (S_ISSPARSEDIR(ce->ce_mode))
160+
ret = 1;
161+
} else {
157162
pos = -pos - 1;
158163
if (pos >= the_repository->index->cache_nr)
159164
goto free_return;
@@ -249,12 +254,15 @@ int cmd_mv(int argc,
249254
usage_with_options(builtin_mv_usage, builtin_mv_options);
250255

251256
prepare_repo_settings(the_repository);
252-
the_repository->settings.command_requires_full_index = 1;
257+
the_repository->settings.command_requires_full_index = 0;
253258

254259
repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
255260
if (repo_read_index(the_repository) < 0)
256261
die(_("index file corrupt"));
257262

263+
if (ignore_sparse)
264+
ensure_full_index(the_repository->index);
265+
258266
internal_prefix_pathspec(&sources, prefix, argv, argc, 0);
259267
CALLOC_ARRAY(modes, argc);
260268

@@ -317,6 +325,10 @@ int cmd_mv(int argc,
317325
if (!path_in_sparse_checkout(src_w_slash, the_repository->index) &&
318326
empty_dir_has_sparse_contents(src)) {
319327
free(src_w_slash);
328+
if (!ignore_sparse) {
329+
string_list_append(&only_match_skip_worktree, src);
330+
goto act_on_entry;
331+
}
320332
modes[i] |= SKIP_WORKTREE_DIR;
321333
goto dir_check;
322334
}

t/t1092-sparse-checkout-compatibility.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,6 +1558,24 @@ test_expect_success 'sparse-index is not expanded' '
15581558
)
15591559
'
15601560

1561+
test_expect_success 'sparse-index is not expanded: git mv' '
1562+
init_repos &&
1563+
1564+
ensure_not_expanded mv deep/a deep/renamed-a &&
1565+
ensure_not_expanded mv deep/deeper2 deep/moved-deeper2 &&
1566+
1567+
ensure_not_expanded reset --hard &&
1568+
1569+
# mv of a sparse directory without --sparse should fail with
1570+
# a useful hint, without expanding the index.
1571+
run_sparse_index_trace2 ! mv folder1 deep &&
1572+
test_region ! index ensure_full_index trace2.txt &&
1573+
grep "Use the --sparse option" sparse-index-error &&
1574+
1575+
ensure_not_expanded reset --hard &&
1576+
ensure_expanded mv --sparse folder1 deep
1577+
'
1578+
15611579
test_expect_success 'sparse-index is not expanded: merge conflict in cone' '
15621580
init_repos &&
15631581

t/t7002-mv-sparse-checkout.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ test_expect_success 'refuse to move out-of-cone directory without --sparse' '
238238
239239
test_must_fail git mv folder1 sub 2>stderr &&
240240
cat sparse_error_header >expect &&
241-
echo folder1/file1 >>expect &&
241+
echo folder1 >>expect &&
242242
cat sparse_hint >>expect &&
243243
test_cmp expect stderr
244244
'

0 commit comments

Comments
 (0)