Skip to content

Commit a4a88b2

Browse files
Linus TorvaldsJunio C Hamano
authored andcommitted
git-rev-list libification: rev-list walking
This actually moves the "meat" of the revision walking from rev-list.c to the new library code in revision.h. It introduces the new functions void prepare_revision_walk(struct rev_info *revs); struct commit *get_revision(struct rev_info *revs); to prepare and then walk the revisions that we have. Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d9a8368 commit a4a88b2

File tree

3 files changed

+266
-251
lines changed

3 files changed

+266
-251
lines changed

rev-list.c

Lines changed: 16 additions & 248 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@
88
#include "diff.h"
99
#include "revision.h"
1010

11-
/* bits #0 and #1 in revision.h */
11+
/* bits #0-2 in revision.h */
1212

13-
#define COUNTED (1u << 2)
14-
#define SHOWN (1u << 3)
15-
#define TREECHANGE (1u << 4)
13+
#define COUNTED (1u << 3)
14+
#define SHOWN (1u << 4)
1615
#define TMP_MARK (1u << 5) /* for isolated cases; clean after use */
1716

1817
static const char rev_list_usage[] =
@@ -213,17 +212,17 @@ static struct object_list **process_tree(struct tree *tree,
213212
return p;
214213
}
215214

216-
static void show_commit_list(struct commit_list *list)
215+
static void show_commit_list(struct rev_info *revs)
217216
{
217+
struct commit *commit;
218218
struct object_list *objects = NULL, **p = &objects, *pending;
219-
while (list) {
220-
struct commit *commit = pop_most_recent_commit(&list, SEEN);
221219

220+
while ((commit = get_revision(revs)) != NULL) {
222221
p = process_tree(commit->tree, p, NULL, "");
223222
if (process_commit(commit) == STOP)
224223
break;
225224
}
226-
for (pending = revs.pending_objects; pending; pending = pending->next) {
225+
for (pending = revs->pending_objects; pending; pending = pending->next) {
227226
struct object *obj = pending->item;
228227
const char *name = pending->name;
229228
if (obj->flags & (UNINTERESTING | SEEN))
@@ -259,19 +258,6 @@ static void show_commit_list(struct commit_list *list)
259258
}
260259
}
261260

262-
static int everybody_uninteresting(struct commit_list *orig)
263-
{
264-
struct commit_list *list = orig;
265-
while (list) {
266-
struct commit *commit = list->item;
267-
list = list->next;
268-
if (commit->object.flags & UNINTERESTING)
269-
continue;
270-
return 0;
271-
}
272-
return 1;
273-
}
274-
275261
/*
276262
* This is a truly stupid algorithm, but it's only
277263
* used for bisection, and we just don't care enough.
@@ -379,224 +365,12 @@ static void mark_edges_uninteresting(struct commit_list *list)
379365
}
380366
}
381367

382-
#define TREE_SAME 0
383-
#define TREE_NEW 1
384-
#define TREE_DIFFERENT 2
385-
static int tree_difference = TREE_SAME;
386-
387-
static void file_add_remove(struct diff_options *options,
388-
int addremove, unsigned mode,
389-
const unsigned char *sha1,
390-
const char *base, const char *path)
391-
{
392-
int diff = TREE_DIFFERENT;
393-
394-
/*
395-
* Is it an add of a new file? It means that
396-
* the old tree didn't have it at all, so we
397-
* will turn "TREE_SAME" -> "TREE_NEW", but
398-
* leave any "TREE_DIFFERENT" alone (and if
399-
* it already was "TREE_NEW", we'll keep it
400-
* "TREE_NEW" of course).
401-
*/
402-
if (addremove == '+') {
403-
diff = tree_difference;
404-
if (diff != TREE_SAME)
405-
return;
406-
diff = TREE_NEW;
407-
}
408-
tree_difference = diff;
409-
}
410-
411-
static void file_change(struct diff_options *options,
412-
unsigned old_mode, unsigned new_mode,
413-
const unsigned char *old_sha1,
414-
const unsigned char *new_sha1,
415-
const char *base, const char *path)
416-
{
417-
tree_difference = TREE_DIFFERENT;
418-
}
419-
420-
static struct diff_options diff_opt = {
421-
.recursive = 1,
422-
.add_remove = file_add_remove,
423-
.change = file_change,
424-
};
425-
426-
static int compare_tree(struct tree *t1, struct tree *t2)
427-
{
428-
if (!t1)
429-
return TREE_NEW;
430-
if (!t2)
431-
return TREE_DIFFERENT;
432-
tree_difference = TREE_SAME;
433-
if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "", &diff_opt) < 0)
434-
return TREE_DIFFERENT;
435-
return tree_difference;
436-
}
437-
438-
static int same_tree_as_empty(struct tree *t1)
439-
{
440-
int retval;
441-
void *tree;
442-
struct tree_desc empty, real;
443-
444-
if (!t1)
445-
return 0;
446-
447-
tree = read_object_with_reference(t1->object.sha1, "tree", &real.size, NULL);
448-
if (!tree)
449-
return 0;
450-
real.buf = tree;
451-
452-
empty.buf = "";
453-
empty.size = 0;
454-
455-
tree_difference = 0;
456-
retval = diff_tree(&empty, &real, "", &diff_opt);
457-
free(tree);
458-
459-
return retval >= 0 && !tree_difference;
460-
}
461-
462-
static void try_to_simplify_commit(struct commit *commit)
463-
{
464-
struct commit_list **pp, *parent;
465-
466-
if (!commit->tree)
467-
return;
468-
469-
if (!commit->parents) {
470-
if (!same_tree_as_empty(commit->tree))
471-
commit->object.flags |= TREECHANGE;
472-
return;
473-
}
474-
475-
pp = &commit->parents;
476-
while ((parent = *pp) != NULL) {
477-
struct commit *p = parent->item;
478-
479-
if (p->object.flags & UNINTERESTING) {
480-
pp = &parent->next;
481-
continue;
482-
}
483-
484-
parse_commit(p);
485-
switch (compare_tree(p->tree, commit->tree)) {
486-
case TREE_SAME:
487-
parent->next = NULL;
488-
commit->parents = parent;
489-
return;
490-
491-
case TREE_NEW:
492-
if (revs.remove_empty_trees && same_tree_as_empty(p->tree)) {
493-
*pp = parent->next;
494-
continue;
495-
}
496-
/* fallthrough */
497-
case TREE_DIFFERENT:
498-
pp = &parent->next;
499-
continue;
500-
}
501-
die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
502-
}
503-
commit->object.flags |= TREECHANGE;
504-
}
505-
506-
static void add_parents_to_list(struct commit *commit, struct commit_list **list)
507-
{
508-
struct commit_list *parent = commit->parents;
509-
510-
/*
511-
* If the commit is uninteresting, don't try to
512-
* prune parents - we want the maximal uninteresting
513-
* set.
514-
*
515-
* Normally we haven't parsed the parent
516-
* yet, so we won't have a parent of a parent
517-
* here. However, it may turn out that we've
518-
* reached this commit some other way (where it
519-
* wasn't uninteresting), in which case we need
520-
* to mark its parents recursively too..
521-
*/
522-
if (commit->object.flags & UNINTERESTING) {
523-
while (parent) {
524-
struct commit *p = parent->item;
525-
parent = parent->next;
526-
parse_commit(p);
527-
p->object.flags |= UNINTERESTING;
528-
if (p->parents)
529-
mark_parents_uninteresting(p);
530-
if (p->object.flags & SEEN)
531-
continue;
532-
p->object.flags |= SEEN;
533-
insert_by_date(p, list);
534-
}
535-
return;
536-
}
537-
538-
/*
539-
* Ok, the commit wasn't uninteresting. Try to
540-
* simplify the commit history and find the parent
541-
* that has no differences in the path set if one exists.
542-
*/
543-
if (revs.paths)
544-
try_to_simplify_commit(commit);
545-
546-
parent = commit->parents;
547-
while (parent) {
548-
struct commit *p = parent->item;
549-
550-
parent = parent->next;
551-
552-
parse_commit(p);
553-
if (p->object.flags & SEEN)
554-
continue;
555-
p->object.flags |= SEEN;
556-
insert_by_date(p, list);
557-
}
558-
}
559-
560-
static struct commit_list *limit_list(struct commit_list *list)
561-
{
562-
struct commit_list *newlist = NULL;
563-
struct commit_list **p = &newlist;
564-
while (list) {
565-
struct commit_list *entry = list;
566-
struct commit *commit = list->item;
567-
struct object *obj = &commit->object;
568-
569-
list = list->next;
570-
free(entry);
571-
572-
if (revs.max_age != -1 && (commit->date < revs.max_age))
573-
obj->flags |= UNINTERESTING;
574-
if (revs.unpacked && has_sha1_pack(obj->sha1))
575-
obj->flags |= UNINTERESTING;
576-
add_parents_to_list(commit, &list);
577-
if (obj->flags & UNINTERESTING) {
578-
mark_parents_uninteresting(commit);
579-
if (everybody_uninteresting(list))
580-
break;
581-
continue;
582-
}
583-
if (revs.min_age != -1 && (commit->date > revs.min_age))
584-
continue;
585-
p = &commit_list_insert(commit, p)->next;
586-
}
587-
if (revs.tree_objects)
588-
mark_edges_uninteresting(newlist);
589-
if (bisect_list)
590-
newlist = find_bisection(newlist);
591-
return newlist;
592-
}
593-
594368
int main(int argc, const char **argv)
595369
{
596370
struct commit_list *list;
597371
int i;
598372

599-
argc = setup_revisions(argc, argv, &revs);
373+
argc = setup_revisions(argc, argv, &revs, NULL);
600374

601375
for (i = 1 ; i < argc; i++) {
602376
const char *arg = argv[i];
@@ -672,24 +446,18 @@ int main(int argc, const char **argv)
672446
(!(revs.tag_objects||revs.tree_objects||revs.blob_objects) && !revs.pending_objects))
673447
usage(rev_list_usage);
674448

675-
if (revs.paths)
676-
diff_tree_setup_paths(revs.paths);
449+
prepare_revision_walk(&revs);
450+
if (revs.tree_objects)
451+
mark_edges_uninteresting(revs.commits);
452+
453+
if (bisect_list)
454+
revs.commits = find_bisection(revs.commits);
677455

678456
save_commit_buffer = verbose_header;
679457
track_object_refs = 0;
680458

681-
if (!merge_order) {
682-
sort_by_date(&list);
683-
if (list && !revs.limited && revs.max_count == 1 &&
684-
!revs.tag_objects && !revs.tree_objects && !revs.blob_objects) {
685-
show_commit(list->item);
686-
return 0;
687-
}
688-
if (revs.limited)
689-
list = limit_list(list);
690-
if (revs.topo_order)
691-
sort_in_topological_order(&list, revs.lifo);
692-
show_commit_list(list);
459+
if (!merge_order) {
460+
show_commit_list(&revs);
693461
} else {
694462
#ifndef NO_OPENSSL
695463
if (sort_list_in_merge_order(list, &process_commit)) {

0 commit comments

Comments
 (0)