revision traversal: --children option
This adds a new --children option to the revision machinery. In addition to the list of parents, child commits of each commit are computed and stored as a decoration to each commit. Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									f43e2fd43b
								
							
						
					
					
						commit
						f35f5603f4
					
				
							
								
								
									
										40
									
								
								revision.c
								
								
								
								
							
							
						
						
									
										40
									
								
								revision.c
								
								
								
								
							|  | @ -9,6 +9,7 @@ | ||||||
| #include "grep.h" | #include "grep.h" | ||||||
| #include "reflog-walk.h" | #include "reflog-walk.h" | ||||||
| #include "patch-ids.h" | #include "patch-ids.h" | ||||||
|  | #include "decorate.h" | ||||||
|  |  | ||||||
| volatile show_early_output_fn_t show_early_output; | volatile show_early_output_fn_t show_early_output; | ||||||
|  |  | ||||||
|  | @ -1310,6 +1311,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch | ||||||
| 				revs->no_walk = 0; | 				revs->no_walk = 0; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (!strcmp(arg, "--children")) { | ||||||
|  | 				revs->children.name = "children"; | ||||||
|  | 				revs->limited = 1; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i); | 			opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i); | ||||||
| 			if (opts > 0) { | 			if (opts > 0) { | ||||||
|  | @ -1395,10 +1401,31 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch | ||||||
|  |  | ||||||
| 	if (revs->reverse && revs->reflog_info) | 	if (revs->reverse && revs->reflog_info) | ||||||
| 		die("cannot combine --reverse with --walk-reflogs"); | 		die("cannot combine --reverse with --walk-reflogs"); | ||||||
|  | 	if (revs->parents && revs->children.name) | ||||||
|  | 		die("cannot combine --parents and --children"); | ||||||
| 	return left; | 	return left; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void add_child(struct rev_info *revs, struct commit *parent, struct commit *child) | ||||||
|  | { | ||||||
|  | 	struct commit_list *l = xcalloc(1, sizeof(*l)); | ||||||
|  |  | ||||||
|  | 	l->item = child; | ||||||
|  | 	l->next = add_decoration(&revs->children, &parent->object, l); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void set_children(struct rev_info *revs) | ||||||
|  | { | ||||||
|  | 	struct commit_list *l; | ||||||
|  | 	for (l = revs->commits; l; l = l->next) { | ||||||
|  | 		struct commit *commit = l->item; | ||||||
|  | 		struct commit_list *p; | ||||||
|  |  | ||||||
|  | 		for (p = commit->parents; p; p = p->next) | ||||||
|  | 			add_child(revs, p->item, commit); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| int prepare_revision_walk(struct rev_info *revs) | int prepare_revision_walk(struct rev_info *revs) | ||||||
| { | { | ||||||
| 	int nr = revs->pending.nr; | 	int nr = revs->pending.nr; | ||||||
|  | @ -1427,6 +1454,8 @@ int prepare_revision_walk(struct rev_info *revs) | ||||||
| 			return -1; | 			return -1; | ||||||
| 	if (revs->topo_order) | 	if (revs->topo_order) | ||||||
| 		sort_in_topological_order(&revs->commits, revs->lifo); | 		sort_in_topological_order(&revs->commits, revs->lifo); | ||||||
|  | 	if (revs->children.name) | ||||||
|  | 		set_children(revs); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1504,6 +1533,11 @@ static int commit_match(struct commit *commit, struct rev_info *opt) | ||||||
| 			   commit->buffer, strlen(commit->buffer)); | 			   commit->buffer, strlen(commit->buffer)); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static inline int want_ancestry(struct rev_info *revs) | ||||||
|  | { | ||||||
|  | 	return (revs->parents || revs->children.name); | ||||||
|  | } | ||||||
|  |  | ||||||
| enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit) | enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit) | ||||||
| { | { | ||||||
| 	if (commit->object.flags & SHOWN) | 	if (commit->object.flags & SHOWN) | ||||||
|  | @ -1524,13 +1558,13 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit) | ||||||
| 		/* Commit without changes? */ | 		/* Commit without changes? */ | ||||||
| 		if (commit->object.flags & TREESAME) { | 		if (commit->object.flags & TREESAME) { | ||||||
| 			/* drop merges unless we want parenthood */ | 			/* drop merges unless we want parenthood */ | ||||||
| 			if (!revs->parents) | 			if (!want_ancestry(revs)) | ||||||
| 				return commit_ignore; | 				return commit_ignore; | ||||||
| 			/* non-merge - always ignore it */ | 			/* non-merge - always ignore it */ | ||||||
| 			if (!commit->parents || !commit->parents->next) | 			if (!commit->parents || !commit->parents->next) | ||||||
| 				return commit_ignore; | 				return commit_ignore; | ||||||
| 		} | 		} | ||||||
| 		if (revs->parents && rewrite_parents(revs, commit) < 0) | 		if (want_ancestry(revs) && rewrite_parents(revs, commit) < 0) | ||||||
| 			return commit_error; | 			return commit_error; | ||||||
| 	} | 	} | ||||||
| 	return commit_show; | 	return commit_show; | ||||||
|  |  | ||||||
|  | @ -98,6 +98,7 @@ struct rev_info { | ||||||
| 	struct diff_options pruning; | 	struct diff_options pruning; | ||||||
|  |  | ||||||
| 	struct reflog_walk_info *reflog_info; | 	struct reflog_walk_info *reflog_info; | ||||||
|  | 	struct decoration children; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define REV_TREE_SAME		0 | #define REV_TREE_SAME		0 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano