Skip to content

Commit 39dc89b

Browse files
committed
list-objects: consume sparse tree walk
When creating a pack-file using 'git pack-objects --revs' we provide a list of interesting and uninteresting commits. For example, a push operation would make the local topic branch be interesting and the known remote refs as uninteresting. We want to discover the set of new objects to send to the server as a thin pack. We walk these commits until we discover a frontier of commits such that every commit walk starting at interesting commits ends in a root commit or unintersting commit. We then need to discover which non-commit objects are reachable from uninteresting commits. This commit walk is not changing during this series. The mark_edges_uninteresting() method in list-objects.c iterates on the commit list and does the following: * If the commit is UNINTERSTING, then mark its root tree and every object it can reach as UNINTERESTING. * If the commit is interesting, then mark the root tree of every UNINTERSTING parent (and all objects that tree can reach) as UNINTERSTING. At the very end, we repeat the process on every commit directly given to the revision walk from stdin. This helps ensure we properly cover shallow commits that otherwise were not included in the frontier. The logic to recursively follow trees is in the mark_tree_uninteresting() method in revision.c. The algorithm avoids duplicate work by not recursing into trees that are already marked UNINTERSTING. Add a new 'sparse' option to the mark_edges_uninteresting() method that performs this logic in a slightly new way. As we iterate over the commits, we add all of the root trees to an oidset. Then, call mark_trees_uninteresting_sparse() on that oidset. Note that we include interesting trees in this process. The current implementation of mark_trees_unintersting_sparse() will walk the same trees as the old logic, but this will be replaced in a later change. The sparse option is not used by any callers at the moment, but will be wired to 'git pack-objects' in the next change. Signed-off-by: Derrick Stolee <[email protected]>
1 parent 817e30a commit 39dc89b

File tree

6 files changed

+66
-16
lines changed

6 files changed

+66
-16
lines changed

bisect.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ static void bisect_common(struct rev_info *revs)
656656
if (prepare_revision_walk(revs))
657657
die("revision walk setup failed");
658658
if (revs->tree_objects)
659-
mark_edges_uninteresting(revs, NULL);
659+
mark_edges_uninteresting(revs, NULL, 0);
660660
}
661661

662662
static void exit_if_skipped_commits(struct commit_list *tried,

builtin/pack-objects.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3135,7 +3135,7 @@ static void get_object_list(int ac, const char **av)
31353135

31363136
if (prepare_revision_walk(&revs))
31373137
die(_("revision walk setup failed"));
3138-
mark_edges_uninteresting(&revs, show_edge);
3138+
mark_edges_uninteresting(&revs, show_edge, 0);
31393139

31403140
if (!fn_show_object)
31413141
fn_show_object = show_object;

builtin/rev-list.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
543543
if (prepare_revision_walk(&revs))
544544
die("revision walk setup failed");
545545
if (revs.tree_objects)
546-
mark_edges_uninteresting(&revs, show_edge);
546+
mark_edges_uninteresting(&revs, show_edge, 0);
547547

548548
if (bisect_list) {
549549
int reaches, all;

http-push.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1933,7 +1933,7 @@ int cmd_main(int argc, const char **argv)
19331933
pushing = 0;
19341934
if (prepare_revision_walk(&revs))
19351935
die("revision walk setup failed");
1936-
mark_edges_uninteresting(&revs, NULL);
1936+
mark_edges_uninteresting(&revs, NULL, 0);
19371937
objects_to_send = get_delta(&revs, ref_lock);
19381938
finish_all_active_slots();
19391939

list-objects.c

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -222,25 +222,73 @@ static void mark_edge_parents_uninteresting(struct commit *commit,
222222
}
223223
}
224224

225-
void mark_edges_uninteresting(struct rev_info *revs, show_edge_fn show_edge)
225+
static void add_edge_parents(struct commit *commit,
226+
struct rev_info *revs,
227+
show_edge_fn show_edge,
228+
struct oidset *set)
229+
{
230+
struct commit_list *parents;
231+
232+
for (parents = commit->parents; parents; parents = parents->next) {
233+
struct commit *parent = parents->item;
234+
struct tree *tree = get_commit_tree(parent);
235+
236+
if (!tree)
237+
continue;
238+
239+
oidset_insert(set, &tree->object.oid);
240+
241+
if (!(parent->object.flags & UNINTERESTING))
242+
continue;
243+
tree->object.flags |= UNINTERESTING;
244+
245+
if (revs->edge_hint && !(parent->object.flags & SHOWN)) {
246+
parent->object.flags |= SHOWN;
247+
show_edge(parent);
248+
}
249+
}
250+
}
251+
252+
void mark_edges_uninteresting(struct rev_info *revs,
253+
show_edge_fn show_edge,
254+
int sparse)
226255
{
227256
struct commit_list *list;
228257
int i;
229258

230-
for (list = revs->commits; list; list = list->next) {
231-
struct commit *commit = list->item;
259+
if (sparse) {
260+
struct oidset set;
261+
oidset_init(&set, 16);
232262

233-
if (commit->object.flags & UNINTERESTING) {
234-
mark_tree_uninteresting(revs->repo,
235-
get_commit_tree(commit));
236-
if (revs->edge_hint_aggressive && !(commit->object.flags & SHOWN)) {
237-
commit->object.flags |= SHOWN;
238-
show_edge(commit);
263+
for (list = revs->commits; list; list = list->next) {
264+
struct commit *commit = list->item;
265+
struct tree *tree = get_commit_tree(commit);
266+
267+
if (commit->object.flags & UNINTERESTING)
268+
tree->object.flags |= UNINTERESTING;
269+
270+
oidset_insert(&set, &tree->object.oid);
271+
add_edge_parents(commit, revs, show_edge, &set);
272+
}
273+
274+
mark_trees_uninteresting_sparse(revs->repo, &set);
275+
oidset_clear(&set);
276+
} else {
277+
for (list = revs->commits; list; list = list->next) {
278+
struct commit *commit = list->item;
279+
if (commit->object.flags & UNINTERESTING) {
280+
mark_tree_uninteresting(revs->repo,
281+
get_commit_tree(commit));
282+
if (revs->edge_hint_aggressive && !(commit->object.flags & SHOWN)) {
283+
commit->object.flags |= SHOWN;
284+
show_edge(commit);
285+
}
286+
continue;
239287
}
240-
continue;
288+
mark_edge_parents_uninteresting(commit, revs, show_edge);
241289
}
242-
mark_edge_parents_uninteresting(commit, revs, show_edge);
243290
}
291+
244292
if (revs->edge_hint_aggressive) {
245293
for (i = 0; i < revs->cmdline.nr; i++) {
246294
struct object *obj = revs->cmdline.rev[i].item;

list-objects.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ typedef void (*show_object_fn)(struct object *, const char *, void *);
1010
void traverse_commit_list(struct rev_info *, show_commit_fn, show_object_fn, void *);
1111

1212
typedef void (*show_edge_fn)(struct commit *);
13-
void mark_edges_uninteresting(struct rev_info *, show_edge_fn);
13+
void mark_edges_uninteresting(struct rev_info *revs,
14+
show_edge_fn show_edge,
15+
int sparse);
1416

1517
struct oidset;
1618
struct list_objects_filter_options;

0 commit comments

Comments
 (0)