Skip to content

Commit 86ab490

Browse files
author
Junio C Hamano
committed
revision walker: Fix --boundary when limited
This cleans up the boundary processing in the commit walker. It - rips out the boundary logic from the commit walker. Placing "negative" commits in the revs->commits list was Ok if all we cared about "boundary" was the UNINTERESTING limiting case, but conceptually it was wrong. - makes get_revision_1() function to walk the commits and return the results as if there is no funny postprocessing flags such as --reverse, --skip nor --max-count. - makes get_revision() function the postprocessing phase: If reverse is given, wait for get_revision_1() to give everything that it would normally give, and then reverse it before consuming. If skip is given, skip that many before going further. If max is given, stop when we gave out that many. Now that we are about to return one positive commit, mark the parents of that commit to be potential boundaries before returning, iff we are doing the boundary processing. Return the commit. - After get_revision() finishes giving out all the positive commits, if we are doing the boundary processing, we look at the parents that we marked as potential boundaries earlier, see if they are really boundaries, and give them out. It loses more code than it adds, even when the new gc_boundary() function, which is purely for early optimization, is counted. Note that this patch is purely for eyeballing and discussion only. It breaks git-bundle's verify logic because the logic does not use BOUNDARY_SHOW flag for its internal computation anymore. After we correct it not to attempt to affect the boundary processing by setting the BOUNDARY_SHOW flag, we can remove BOUNDARY_SHOW from revision.h and use that bit assignment for the new CHILD_SHOWN flag. Signed-off-by: Junio C Hamano <[email protected]>
1 parent ba66c58 commit 86ab490

File tree

2 files changed

+100
-116
lines changed

2 files changed

+100
-116
lines changed

revision.c

Lines changed: 94 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -437,36 +437,6 @@ static void limit_list(struct rev_info *revs)
437437
continue;
438438
p = &commit_list_insert(commit, p)->next;
439439
}
440-
if (revs->boundary) {
441-
/* mark the ones that are on the result list first */
442-
for (list = newlist; list; list = list->next) {
443-
struct commit *commit = list->item;
444-
commit->object.flags |= TMP_MARK;
445-
}
446-
for (list = newlist; list; list = list->next) {
447-
struct commit *commit = list->item;
448-
struct object *obj = &commit->object;
449-
struct commit_list *parent;
450-
if (obj->flags & UNINTERESTING)
451-
continue;
452-
for (parent = commit->parents;
453-
parent;
454-
parent = parent->next) {
455-
struct commit *pcommit = parent->item;
456-
if (!(pcommit->object.flags & UNINTERESTING))
457-
continue;
458-
pcommit->object.flags |= BOUNDARY;
459-
if (pcommit->object.flags & TMP_MARK)
460-
continue;
461-
pcommit->object.flags |= TMP_MARK;
462-
p = &commit_list_insert(pcommit, p)->next;
463-
}
464-
}
465-
for (list = newlist; list; list = list->next) {
466-
struct commit *commit = list->item;
467-
commit->object.flags &= ~TMP_MARK;
468-
}
469-
}
470440
revs->commits = newlist;
471441
}
472442

@@ -1193,17 +1163,6 @@ static void rewrite_parents(struct rev_info *revs, struct commit *commit)
11931163
}
11941164
}
11951165

1196-
static void mark_boundary_to_show(struct commit *commit)
1197-
{
1198-
struct commit_list *p = commit->parents;
1199-
while (p) {
1200-
commit = p->item;
1201-
p = p->next;
1202-
if (commit->object.flags & BOUNDARY)
1203-
commit->object.flags |= BOUNDARY_SHOW;
1204-
}
1205-
}
1206-
12071166
static int commit_match(struct commit *commit, struct rev_info *opt)
12081167
{
12091168
if (!opt->grep_filter)
@@ -1235,15 +1194,9 @@ static struct commit *get_revision_1(struct rev_info *revs)
12351194
*/
12361195
if (!revs->limited) {
12371196
if (revs->max_age != -1 &&
1238-
(commit->date < revs->max_age)) {
1239-
if (revs->boundary)
1240-
commit->object.flags |=
1241-
BOUNDARY_SHOW | BOUNDARY;
1242-
else
1243-
continue;
1244-
} else
1245-
add_parents_to_list(revs, commit,
1246-
&revs->commits);
1197+
(commit->date < revs->max_age))
1198+
continue;
1199+
add_parents_to_list(revs, commit, &revs->commits);
12471200
}
12481201
if (commit->object.flags & SHOWN)
12491202
continue;
@@ -1252,18 +1205,6 @@ static struct commit *get_revision_1(struct rev_info *revs)
12521205
revs->ignore_packed))
12531206
continue;
12541207

1255-
/* We want to show boundary commits only when their
1256-
* children are shown. When path-limiter is in effect,
1257-
* rewrite_parents() drops some commits from getting shown,
1258-
* and there is no point showing boundary parents that
1259-
* are not shown. After rewrite_parents() rewrites the
1260-
* parents of a commit that is shown, we mark the boundary
1261-
* parents with BOUNDARY_SHOW.
1262-
*/
1263-
if (commit->object.flags & BOUNDARY_SHOW) {
1264-
commit->object.flags |= SHOWN;
1265-
return commit;
1266-
}
12671208
if (commit->object.flags & UNINTERESTING)
12681209
continue;
12691210
if (revs->min_age != -1 && (commit->date > revs->min_age))
@@ -1286,80 +1227,119 @@ static struct commit *get_revision_1(struct rev_info *revs)
12861227
if (revs->parents)
12871228
rewrite_parents(revs, commit);
12881229
}
1289-
if (revs->boundary)
1290-
mark_boundary_to_show(commit);
12911230
commit->object.flags |= SHOWN;
12921231
return commit;
12931232
} while (revs->commits);
12941233
return NULL;
12951234
}
12961235

1236+
static void gc_boundary(struct object_array *array)
1237+
{
1238+
unsigned nr = array->nr;
1239+
unsigned alloc = array->alloc;
1240+
struct object_array_entry *objects = array->objects;
1241+
1242+
if (alloc <= nr) {
1243+
unsigned i, j;
1244+
for (i = j = 0; i < nr; i++) {
1245+
if (objects[i].item->flags & SHOWN)
1246+
continue;
1247+
if (i != j)
1248+
objects[j] = objects[i];
1249+
j++;
1250+
}
1251+
for (i = j; j < nr; j++)
1252+
objects[i].item = NULL;
1253+
array->nr = j;
1254+
}
1255+
}
1256+
12971257
struct commit *get_revision(struct rev_info *revs)
12981258
{
12991259
struct commit *c = NULL;
1300-
1301-
if (revs->reverse) {
1302-
struct commit_list *list;
1303-
1304-
/*
1305-
* rev_info.reverse is used to note the fact that we
1306-
* want to output the list of revisions in reverse
1307-
* order. To accomplish this goal, reverse can have
1308-
* different values:
1309-
*
1310-
* 0 do nothing
1311-
* 1 reverse the list
1312-
* 2 internal use: we have already obtained and
1313-
* reversed the list, now we only need to yield
1314-
* its items.
1315-
*/
1316-
1317-
if (revs->reverse == 1) {
1318-
revs->reverse = 0;
1319-
list = NULL;
1320-
while ((c = get_revision(revs)))
1321-
commit_list_insert(c, &list);
1322-
revs->commits = list;
1323-
revs->reverse = 2;
1260+
struct commit_list *l;
1261+
1262+
if (revs->boundary == 2) {
1263+
unsigned i;
1264+
struct object_array *array = &revs->boundary_commits;
1265+
struct object_array_entry *objects = array->objects;
1266+
for (i = 0; i < array->nr; i++) {
1267+
c = (struct commit *)(objects[i].item);
1268+
if (!c)
1269+
continue;
1270+
if (!(c->object.flags & CHILD_SHOWN))
1271+
continue;
1272+
if (!(c->object.flags & SHOWN))
1273+
break;
13241274
}
1325-
1326-
if (!revs->commits)
1275+
if (array->nr <= i)
13271276
return NULL;
1328-
c = revs->commits->item;
1329-
list = revs->commits->next;
1330-
free(revs->commits);
1331-
revs->commits = list;
1277+
1278+
c->object.flags |= SHOWN | BOUNDARY;
13321279
return c;
13331280
}
13341281

1335-
if (0 < revs->skip_count) {
1336-
while ((c = get_revision_1(revs)) != NULL) {
1337-
if (revs->skip_count-- <= 0)
1338-
break;
1339-
}
1282+
if (revs->reverse) {
1283+
l = NULL;
1284+
while ((c = get_revision_1(revs)))
1285+
commit_list_insert(c, &l);
1286+
revs->commits = l;
1287+
revs->reverse = 0;
13401288
}
13411289

1342-
/* Check the max_count ... */
1290+
/*
1291+
* Now pick up what they want to give us
1292+
*/
1293+
c = get_revision_1(revs);
1294+
while (0 < revs->skip_count) {
1295+
revs->skip_count--;
1296+
c = get_revision_1(revs);
1297+
if (!c)
1298+
break;
1299+
}
1300+
1301+
/*
1302+
* Check the max_count.
1303+
*/
13431304
switch (revs->max_count) {
13441305
case -1:
13451306
break;
13461307
case 0:
1347-
if (revs->boundary) {
1348-
struct commit_list *list = revs->commits;
1349-
while (list) {
1350-
list->item->object.flags |=
1351-
BOUNDARY_SHOW | BOUNDARY;
1352-
list = list->next;
1353-
}
1354-
/* all remaining commits are boundary commits */
1355-
revs->max_count = -1;
1356-
revs->limited = 1;
1357-
} else
1358-
return NULL;
1308+
c = NULL;
1309+
break;
13591310
default:
13601311
revs->max_count--;
13611312
}
1362-
if (c)
1313+
1314+
if (!revs->boundary)
13631315
return c;
1364-
return get_revision_1(revs);
1316+
1317+
if (!c) {
1318+
/*
1319+
* get_revision_1() runs out the commits, and
1320+
* we are done computing the boundaries.
1321+
* switch to boundary commits output mode.
1322+
*/
1323+
revs->boundary = 2;
1324+
return get_revision(revs);
1325+
}
1326+
1327+
/*
1328+
* boundary commits are the commits that are parents of the
1329+
* ones we got from get_revision_1() but they themselves are
1330+
* not returned from get_revision_1(). Before returning
1331+
* 'c', we need to mark its parents that they could be boundaries.
1332+
*/
1333+
1334+
for (l = c->parents; l; l = l->next) {
1335+
struct object *p;
1336+
p = &(l->item->object);
1337+
if (p->flags & CHILD_SHOWN)
1338+
continue;
1339+
p->flags |= CHILD_SHOWN;
1340+
gc_boundary(&revs->boundary_commits);
1341+
add_object_array(p, NULL, &revs->boundary_commits);
1342+
}
1343+
1344+
return c;
13651345
}

revision.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define BOUNDARY_SHOW (1u<<6)
1111
#define ADDED (1u<<7) /* Parents already parsed and added? */
1212
#define SYMMETRIC_LEFT (1u<<8)
13+
#define CHILD_SHOWN (1u<<9)
1314

1415
struct rev_info;
1516
struct log_info;
@@ -21,6 +22,9 @@ struct rev_info {
2122
struct commit_list *commits;
2223
struct object_array pending;
2324

25+
/* Parents of shown commits */
26+
struct object_array boundary_commits;
27+
2428
/* Basic information */
2529
const char *prefix;
2630
void *prune_data;
@@ -40,10 +44,10 @@ struct rev_info {
4044
edge_hint:1,
4145
limited:1,
4246
unpacked:1, /* see also ignore_packed below */
43-
boundary:1,
47+
boundary:2,
4448
left_right:1,
4549
parents:1,
46-
reverse:2;
50+
reverse:1;
4751

4852
/* Diff flags */
4953
unsigned int diff:1,

0 commit comments

Comments
 (0)