Skip to content

Commit 2e31da5

Browse files
derrickstoleedscho
authored andcommitted
path-walk: add new 'edge_aggressive' option
In preparation for allowing both the --shallow and --path-walk options in the 'git pack-objects' builtin, create a new 'edge_aggressive' option in the path-walk API. This option will help walk the boundary more thoroughly and help avoid sending extra objects during fetches and pushes. The only use of the 'edge_hint_aggressive' option in the revision API is within mark_edges_uninteresting(), which is usually called before between prepare_revision_walk() and before visiting commits with get_revision(). In prepare_revision_walk(), the UNINTERESTING commits are walked until a boundary is found. We didn't use this in the past because we would mark objects UNINTERESTING after doing the initial commit walk to the boundary. While we should be marking these objects as UNINTERESTING, we shouldn't _emit_ them all via the path-walk algorithm or else our delta calculations will get really slow. Based on these observations, the way we were handling the UNINTERESTING flag in walk_objects_by_path() was overly complicated and buggy. A lot of it can be removed and simplified to work with this new approach. It also means that we will see the UNINTERESTING boundaries of paths when doing a default path-walk call, changing some existing test cases. Signed-off-by: Derrick Stolee <stolee@gmail.com>
1 parent 501634b commit 2e31da5

File tree

4 files changed

+58
-33
lines changed

4 files changed

+58
-33
lines changed

Diff for: Documentation/technical/api-path-walk.txt

+8
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ better off using the revision walk API instead.
6565
the revision walk so that the walk emits commits marked with the
6666
`UNINTERESTING` flag.
6767

68+
`edge_aggressive`::
69+
For performance reasons, usually only the boundary commits are
70+
explored to find UNINTERESTING objects. However, in the case of
71+
shallow clones it can be helpful to mark all trees and blobs
72+
reachable from UNINTERESTING tip commits as UNINTERESTING. This
73+
matches the behavior of `--objects-edge-aggressive` in the
74+
revision API.
75+
6876
`pl`::
6977
This pattern list pointer allows focusing the path-walk search to
7078
a set of patterns, only emitting paths that match the given

Diff for: path-walk.c

+35-25
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "trace2.h"
1919
#include "tree.h"
2020
#include "tree-walk.h"
21+
#include "list-objects.h"
2122

2223
struct type_and_oid_list
2324
{
@@ -233,6 +234,26 @@ static void clear_strmap(struct strmap *map)
233234
strmap_init(map);
234235
}
235236

237+
static struct repository *edge_repo;
238+
static struct type_and_oid_list *edge_tree_list;
239+
240+
static void show_edge(struct commit *commit)
241+
{
242+
struct tree *t = repo_get_commit_tree(edge_repo, commit);
243+
244+
if (!t)
245+
return;
246+
247+
if (commit->object.flags & UNINTERESTING)
248+
t->object.flags |= UNINTERESTING;
249+
250+
if (t->object.flags & SEEN)
251+
return;
252+
t->object.flags |= SEEN;
253+
254+
oid_array_append(&edge_tree_list->oids, &t->object.oid);
255+
}
256+
236257
/**
237258
* Given the configuration of 'info', walk the commits based on 'info->revs' and
238259
* call 'info->path_fn' on each discovered path.
@@ -242,7 +263,7 @@ static void clear_strmap(struct strmap *map)
242263
int walk_objects_by_path(struct path_walk_info *info)
243264
{
244265
const char *root_path = "";
245-
int ret = 0, has_uninteresting = 0;
266+
int ret = 0;
246267
size_t commits_nr = 0, paths_nr = 0;
247268
struct commit *c;
248269
struct type_and_oid_list *root_tree_list;
@@ -254,7 +275,6 @@ int walk_objects_by_path(struct path_walk_info *info)
254275
.path_stack = STRING_LIST_INIT_DUP,
255276
.paths_to_lists = STRMAP_INIT
256277
};
257-
struct oidset root_tree_set = OIDSET_INIT;
258278

259279
trace2_region_enter("path-walk", "commit-walk", info->revs->repo);
260280

@@ -280,6 +300,18 @@ int walk_objects_by_path(struct path_walk_info *info)
280300
if (prepare_revision_walk(info->revs))
281301
die(_("failed to setup revision walk"));
282302

303+
/*
304+
* Do an initial walk of tip commits in info->revs->commits and
305+
* info->revs->cmdline.rev to match the standard edge-walk behavior.
306+
*
307+
* This is particularly important when 'edge_aggressive' is set.
308+
*/
309+
info->revs->edge_hint_aggressive = info->edge_aggressive;
310+
311+
edge_repo = info->revs->repo;
312+
edge_tree_list = root_tree_list;
313+
mark_edges_uninteresting(info->revs, show_edge, info->prune_all_uninteresting);
314+
283315
info->revs->blob_objects = info->revs->tree_objects = 0;
284316

285317
if (info->tags) {
@@ -366,17 +398,10 @@ int walk_objects_by_path(struct path_walk_info *info)
366398
if (t->object.flags & SEEN)
367399
continue;
368400
t->object.flags |= SEEN;
369-
370-
if (!oidset_insert(&root_tree_set, oid))
371-
oid_array_append(&root_tree_list->oids, oid);
401+
oid_array_append(&root_tree_list->oids, oid);
372402
} else {
373403
warning("could not find tree %s", oid_to_hex(oid));
374404
}
375-
376-
if (t && (c->object.flags & UNINTERESTING)) {
377-
t->object.flags |= UNINTERESTING;
378-
has_uninteresting = 1;
379-
}
380405
}
381406

382407
trace2_data_intmax("path-walk", ctx.repo, "commits", commits_nr);
@@ -389,21 +414,6 @@ int walk_objects_by_path(struct path_walk_info *info)
389414
oid_array_clear(&commit_list->oids);
390415
free(commit_list);
391416

392-
/*
393-
* Before performing a DFS of our paths and emitting them as interesting,
394-
* do a full walk of the trees to distribute the UNINTERESTING bit. Use
395-
* the sparse algorithm if prune_all_uninteresting was set.
396-
*/
397-
if (has_uninteresting) {
398-
trace2_region_enter("path-walk", "uninteresting-walk", info->revs->repo);
399-
if (info->prune_all_uninteresting)
400-
mark_trees_uninteresting_sparse(ctx.repo, &root_tree_set);
401-
else
402-
mark_trees_uninteresting_dense(ctx.repo, &root_tree_set);
403-
trace2_region_leave("path-walk", "uninteresting-walk", info->revs->repo);
404-
}
405-
oidset_clear(&root_tree_set);
406-
407417
string_list_append(&ctx.path_stack, root_path);
408418

409419
trace2_region_enter("path-walk", "path-walk", info->revs->repo);

Diff for: path-walk.h

+7
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ struct path_walk_info {
4848
*/
4949
int prune_all_uninteresting;
5050

51+
/**
52+
* When 'edge_aggressive' is set, then the revision walk will use
53+
* the '--object-edge-aggressive' option to mark even more objects
54+
* as uninteresting.
55+
*/
56+
int edge_aggressive;
57+
5158
/**
5259
* Specify a sparse-checkout definition to match our paths to. Do not
5360
* walk outside of this sparse definition. If the patterns are in

Diff for: t/t6601-path-walk.sh

+8-8
Original file line numberDiff line numberDiff line change
@@ -181,13 +181,13 @@ test_expect_success 'topic, not base' '
181181
COMMIT::$(git rev-parse topic)
182182
commits:1
183183
TREE::$(git rev-parse topic^{tree})
184-
TREE:left/:$(git rev-parse topic:left)
184+
TREE:left/:$(git rev-parse base~1:left):UNINTERESTING
185185
TREE:right/:$(git rev-parse topic:right)
186186
trees:3
187-
BLOB:a:$(git rev-parse topic:a)
188-
BLOB:left/b:$(git rev-parse topic:left/b)
187+
BLOB:a:$(git rev-parse base~1:a):UNINTERESTING
188+
BLOB:left/b:$(git rev-parse base~1:left/b):UNINTERESTING
189189
BLOB:right/c:$(git rev-parse topic:right/c)
190-
BLOB:right/d:$(git rev-parse topic:right/d)
190+
BLOB:right/d:$(git rev-parse base~1:right/d):UNINTERESTING
191191
blobs:4
192192
tags:0
193193
EOF
@@ -205,10 +205,10 @@ test_expect_success 'topic, not base, only blobs' '
205205
cat >expect <<-EOF &&
206206
commits:0
207207
trees:0
208-
BLOB:a:$(git rev-parse topic:a)
209-
BLOB:left/b:$(git rev-parse topic:left/b)
208+
BLOB:a:$(git rev-parse base~1:a):UNINTERESTING
209+
BLOB:left/b:$(git rev-parse base~1:left/b):UNINTERESTING
210210
BLOB:right/c:$(git rev-parse topic:right/c)
211-
BLOB:right/d:$(git rev-parse topic:right/d)
211+
BLOB:right/d:$(git rev-parse base~1:right/d):UNINTERESTING
212212
blobs:4
213213
tags:0
214214
EOF
@@ -246,7 +246,7 @@ test_expect_success 'topic, not base, only trees' '
246246
cat >expect <<-EOF &&
247247
commits:0
248248
TREE::$(git rev-parse topic^{tree})
249-
TREE:left/:$(git rev-parse topic:left)
249+
TREE:left/:$(git rev-parse base~1:left):UNINTERESTING
250250
TREE:right/:$(git rev-parse topic:right)
251251
trees:3
252252
blobs:0

0 commit comments

Comments
 (0)