Skip to content

Commit bcf38e7

Browse files
committed
Merge branch 'ds/path-walk-repack-fix' into jch
"git repack --path-walk" lost objects in some corner cases, which has been corrected. Comments? * ds/path-walk-repack-fix: path-walk: create initializer for path lists path-walk: fix setup of pending objects t7700: add failing --path-walk test
2 parents 7b53f42 + a8b7745 commit bcf38e7

File tree

2 files changed

+68
-30
lines changed

2 files changed

+68
-30
lines changed

path-walk.c

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,24 @@ static void push_to_stack(struct path_walk_context *ctx,
105105
prio_queue_put(&ctx->path_stack, xstrdup(path));
106106
}
107107

108+
static void add_path_to_list(struct path_walk_context *ctx,
109+
const char *path,
110+
enum object_type type,
111+
struct object_id *oid,
112+
int interesting)
113+
{
114+
struct type_and_oid_list *list = strmap_get(&ctx->paths_to_lists, path);
115+
116+
if (!list) {
117+
CALLOC_ARRAY(list, 1);
118+
list->type = type;
119+
strmap_put(&ctx->paths_to_lists, path, list);
120+
}
121+
122+
list->maybe_interesting |= interesting;
123+
oid_array_append(&list->oids, oid);
124+
}
125+
108126
static int add_tree_entries(struct path_walk_context *ctx,
109127
const char *base_path,
110128
struct object_id *oid)
@@ -129,7 +147,6 @@ static int add_tree_entries(struct path_walk_context *ctx,
129147

130148
init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
131149
while (tree_entry(&desc, &entry)) {
132-
struct type_and_oid_list *list;
133150
struct object *o;
134151
/* Not actually true, but we will ignore submodules later. */
135152
enum object_type type = S_ISDIR(entry.mode) ? OBJ_TREE : OBJ_BLOB;
@@ -190,17 +207,10 @@ static int add_tree_entries(struct path_walk_context *ctx,
190207
continue;
191208
}
192209

193-
if (!(list = strmap_get(&ctx->paths_to_lists, path.buf))) {
194-
CALLOC_ARRAY(list, 1);
195-
list->type = type;
196-
strmap_put(&ctx->paths_to_lists, path.buf, list);
197-
}
198-
push_to_stack(ctx, path.buf);
199-
200-
if (!(o->flags & UNINTERESTING))
201-
list->maybe_interesting = 1;
210+
add_path_to_list(ctx, path.buf, type, &entry.oid,
211+
!(o->flags & UNINTERESTING));
202212

203-
oid_array_append(&list->oids, &entry.oid);
213+
push_to_stack(ctx, path.buf);
204214
}
205215

206216
free_tree_buffer(tree);
@@ -377,15 +387,9 @@ static int setup_pending_objects(struct path_walk_info *info,
377387
if (!info->trees)
378388
continue;
379389
if (pending->path) {
380-
struct type_and_oid_list *list;
381390
char *path = *pending->path ? xstrfmt("%s/", pending->path)
382391
: xstrdup("");
383-
if (!(list = strmap_get(&ctx->paths_to_lists, path))) {
384-
CALLOC_ARRAY(list, 1);
385-
list->type = OBJ_TREE;
386-
strmap_put(&ctx->paths_to_lists, path, list);
387-
}
388-
oid_array_append(&list->oids, &obj->oid);
392+
add_path_to_list(ctx, path, OBJ_TREE, &obj->oid, 1);
389393
free(path);
390394
} else {
391395
/* assume a root tree, such as a lightweight tag. */
@@ -396,19 +400,10 @@ static int setup_pending_objects(struct path_walk_info *info,
396400
case OBJ_BLOB:
397401
if (!info->blobs)
398402
continue;
399-
if (pending->path) {
400-
struct type_and_oid_list *list;
401-
char *path = pending->path;
402-
if (!(list = strmap_get(&ctx->paths_to_lists, path))) {
403-
CALLOC_ARRAY(list, 1);
404-
list->type = OBJ_BLOB;
405-
strmap_put(&ctx->paths_to_lists, path, list);
406-
}
407-
oid_array_append(&list->oids, &obj->oid);
408-
} else {
409-
/* assume a root tree, such as a lightweight tag. */
403+
if (pending->path)
404+
add_path_to_list(ctx, pending->path, OBJ_BLOB, &obj->oid, 1);
405+
else
410406
oid_array_append(&tagged_blobs->oids, &obj->oid);
411-
}
412407
break;
413408

414409
case OBJ_COMMIT:

t/t7700-repack.sh

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,4 +838,47 @@ test_expect_success '-n overrides repack.updateServerInfo=true' '
838838
test_server_info_missing
839839
'
840840

841+
test_expect_success 'pending objects are repacked appropriately' '
842+
git init pending &&
843+
844+
(
845+
cd pending &&
846+
847+
mkdir -p a/b &&
848+
echo singleton >file &&
849+
echo stuff >a/b/c &&
850+
echo more >a/d &&
851+
git add file a &&
852+
git commit -m "single blobs" &&
853+
854+
echo d >a/d &&
855+
echo e >a/e &&
856+
git add a &&
857+
git commit -m "more blobs" &&
858+
859+
# This use of a sparse index helps to force
860+
# test that the cache-tree is walked, too.
861+
git sparse-checkout set --sparse-index a x &&
862+
863+
# Just _stage_ the changes.
864+
echo f >a/d &&
865+
echo h >a/e &&
866+
echo i >a/i &&
867+
mkdir x &&
868+
echo y >x/y &&
869+
git add a x &&
870+
871+
# Bring the loose objects into a packfile to avoid
872+
# leftovers in next test. Without this, the loose
873+
# objects persist and the test succeeds for other
874+
# reasons.
875+
git repack -adf &&
876+
git fsck &&
877+
878+
# Test path walk version with pack.useSparse.
879+
git -c pack.useSparse=true repack -adf --path-walk &&
880+
git fsck
881+
)
882+
'
883+
841884
test_done

0 commit comments

Comments
 (0)