bisect: refactor sha1_array into a generic sha1 list
This is a generally useful abstraction, so let's let others make use of it. The refactoring is more or less a straight copy; however, functions and struct members have had their names changed to match string_list, which is the most similar data structure. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									114a6a889f
								
							
						
					
					
						commit
						902bb36451
					
				
							
								
								
									
										2
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										2
									
								
								Makefile
								
								
								
								
							|  | @ -547,6 +547,7 @@ LIB_H += rerere.h | ||||||
| LIB_H += resolve-undo.h | LIB_H += resolve-undo.h | ||||||
| LIB_H += revision.h | LIB_H += revision.h | ||||||
| LIB_H += run-command.h | LIB_H += run-command.h | ||||||
|  | LIB_H += sha1-array.h | ||||||
| LIB_H += sha1-lookup.h | LIB_H += sha1-lookup.h | ||||||
| LIB_H += sideband.h | LIB_H += sideband.h | ||||||
| LIB_H += sigchain.h | LIB_H += sigchain.h | ||||||
|  | @ -649,6 +650,7 @@ LIB_OBJS += revision.o | ||||||
| LIB_OBJS += run-command.o | LIB_OBJS += run-command.o | ||||||
| LIB_OBJS += server-info.o | LIB_OBJS += server-info.o | ||||||
| LIB_OBJS += setup.o | LIB_OBJS += setup.o | ||||||
|  | LIB_OBJS += sha1-array.o | ||||||
| LIB_OBJS += sha1-lookup.o | LIB_OBJS += sha1-lookup.o | ||||||
| LIB_OBJS += sha1_file.o | LIB_OBJS += sha1_file.o | ||||||
| LIB_OBJS += sha1_name.o | LIB_OBJS += sha1_name.o | ||||||
|  |  | ||||||
							
								
								
									
										70
									
								
								bisect.c
								
								
								
								
							
							
						
						
									
										70
									
								
								bisect.c
								
								
								
								
							|  | @ -9,13 +9,7 @@ | ||||||
| #include "run-command.h" | #include "run-command.h" | ||||||
| #include "log-tree.h" | #include "log-tree.h" | ||||||
| #include "bisect.h" | #include "bisect.h" | ||||||
|  | #include "sha1-array.h" | ||||||
| struct sha1_array { |  | ||||||
| 	unsigned char (*sha1)[20]; |  | ||||||
| 	int sha1_nr; |  | ||||||
| 	int sha1_alloc; |  | ||||||
| 	int sorted; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static struct sha1_array good_revs; | static struct sha1_array good_revs; | ||||||
| static struct sha1_array skipped_revs; | static struct sha1_array skipped_revs; | ||||||
|  | @ -425,22 +419,15 @@ static void argv_array_push_sha1(struct argv_array *array, | ||||||
| 	argv_array_push(array, strbuf_detach(&buf, NULL)); | 	argv_array_push(array, strbuf_detach(&buf, NULL)); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void sha1_array_push(struct sha1_array *array, |  | ||||||
| 			    const unsigned char *sha1) |  | ||||||
| { |  | ||||||
| 	ALLOC_GROW(array->sha1, array->sha1_nr + 1, array->sha1_alloc); |  | ||||||
| 	hashcpy(array->sha1[array->sha1_nr++], sha1); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int register_ref(const char *refname, const unsigned char *sha1, | static int register_ref(const char *refname, const unsigned char *sha1, | ||||||
| 			int flags, void *cb_data) | 			int flags, void *cb_data) | ||||||
| { | { | ||||||
| 	if (!strcmp(refname, "bad")) { | 	if (!strcmp(refname, "bad")) { | ||||||
| 		current_bad_sha1 = sha1; | 		current_bad_sha1 = sha1; | ||||||
| 	} else if (!prefixcmp(refname, "good-")) { | 	} else if (!prefixcmp(refname, "good-")) { | ||||||
| 		sha1_array_push(&good_revs, sha1); | 		sha1_array_append(&good_revs, sha1); | ||||||
| 	} else if (!prefixcmp(refname, "skip-")) { | 	} else if (!prefixcmp(refname, "skip-")) { | ||||||
| 		sha1_array_push(&skipped_revs, sha1); | 		sha1_array_append(&skipped_revs, sha1); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -477,41 +464,14 @@ static void read_bisect_paths(struct argv_array *array) | ||||||
| 	fclose(fp); | 	fclose(fp); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int array_cmp(const void *a, const void *b) |  | ||||||
| { |  | ||||||
| 	return hashcmp(a, b); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void sort_sha1_array(struct sha1_array *array) |  | ||||||
| { |  | ||||||
| 	qsort(array->sha1, array->sha1_nr, sizeof(*array->sha1), array_cmp); |  | ||||||
|  |  | ||||||
| 	array->sorted = 1; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static const unsigned char *sha1_access(size_t index, void *table) |  | ||||||
| { |  | ||||||
| 	unsigned char (*array)[20] = table; |  | ||||||
| 	return array[index]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int lookup_sha1_array(struct sha1_array *array, |  | ||||||
| 			     const unsigned char *sha1) |  | ||||||
| { |  | ||||||
| 	if (!array->sorted) |  | ||||||
| 		sort_sha1_array(array); |  | ||||||
|  |  | ||||||
| 	return sha1_pos(sha1, array->sha1, array->sha1_nr, sha1_access); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static char *join_sha1_array_hex(struct sha1_array *array, char delim) | static char *join_sha1_array_hex(struct sha1_array *array, char delim) | ||||||
| { | { | ||||||
| 	struct strbuf joined_hexs = STRBUF_INIT; | 	struct strbuf joined_hexs = STRBUF_INIT; | ||||||
| 	int i; | 	int i; | ||||||
|  |  | ||||||
| 	for (i = 0; i < array->sha1_nr; i++) { | 	for (i = 0; i < array->nr; i++) { | ||||||
| 		strbuf_addstr(&joined_hexs, sha1_to_hex(array->sha1[i])); | 		strbuf_addstr(&joined_hexs, sha1_to_hex(array->sha1[i])); | ||||||
| 		if (i + 1 < array->sha1_nr) | 		if (i + 1 < array->nr) | ||||||
| 			strbuf_addch(&joined_hexs, delim); | 			strbuf_addch(&joined_hexs, delim); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -546,13 +506,13 @@ struct commit_list *filter_skipped(struct commit_list *list, | ||||||
| 	if (count) | 	if (count) | ||||||
| 		*count = 0; | 		*count = 0; | ||||||
|  |  | ||||||
| 	if (!skipped_revs.sha1_nr) | 	if (!skipped_revs.nr) | ||||||
| 		return list; | 		return list; | ||||||
|  |  | ||||||
| 	while (list) { | 	while (list) { | ||||||
| 		struct commit_list *next = list->next; | 		struct commit_list *next = list->next; | ||||||
| 		list->next = NULL; | 		list->next = NULL; | ||||||
| 		if (0 <= lookup_sha1_array(&skipped_revs, | 		if (0 <= sha1_array_lookup(&skipped_revs, | ||||||
| 					   list->item->object.sha1)) { | 					   list->item->object.sha1)) { | ||||||
| 			if (skipped_first && !*skipped_first) | 			if (skipped_first && !*skipped_first) | ||||||
| 				*skipped_first = 1; | 				*skipped_first = 1; | ||||||
|  | @ -647,7 +607,7 @@ static struct commit_list *managed_skipped(struct commit_list *list, | ||||||
|  |  | ||||||
| 	*tried = NULL; | 	*tried = NULL; | ||||||
|  |  | ||||||
| 	if (!skipped_revs.sha1_nr) | 	if (!skipped_revs.nr) | ||||||
| 		return list; | 		return list; | ||||||
|  |  | ||||||
| 	list = filter_skipped(list, tried, 0, &count, &skipped_first); | 	list = filter_skipped(list, tried, 0, &count, &skipped_first); | ||||||
|  | @ -672,7 +632,7 @@ static void bisect_rev_setup(struct rev_info *revs, const char *prefix, | ||||||
| 	/* rev_argv.argv[0] will be ignored by setup_revisions */ | 	/* rev_argv.argv[0] will be ignored by setup_revisions */ | ||||||
| 	argv_array_push(&rev_argv, xstrdup("bisect_rev_setup")); | 	argv_array_push(&rev_argv, xstrdup("bisect_rev_setup")); | ||||||
| 	argv_array_push_sha1(&rev_argv, current_bad_sha1, bad_format); | 	argv_array_push_sha1(&rev_argv, current_bad_sha1, bad_format); | ||||||
| 	for (i = 0; i < good_revs.sha1_nr; i++) | 	for (i = 0; i < good_revs.nr; i++) | ||||||
| 		argv_array_push_sha1(&rev_argv, good_revs.sha1[i], | 		argv_array_push_sha1(&rev_argv, good_revs.sha1[i], | ||||||
| 				     good_format); | 				     good_format); | ||||||
| 	argv_array_push(&rev_argv, xstrdup("--")); | 	argv_array_push(&rev_argv, xstrdup("--")); | ||||||
|  | @ -772,12 +732,12 @@ static struct commit *get_commit_reference(const unsigned char *sha1) | ||||||
|  |  | ||||||
| static struct commit **get_bad_and_good_commits(int *rev_nr) | static struct commit **get_bad_and_good_commits(int *rev_nr) | ||||||
| { | { | ||||||
| 	int len = 1 + good_revs.sha1_nr; | 	int len = 1 + good_revs.nr; | ||||||
| 	struct commit **rev = xmalloc(len * sizeof(*rev)); | 	struct commit **rev = xmalloc(len * sizeof(*rev)); | ||||||
| 	int i, n = 0; | 	int i, n = 0; | ||||||
|  |  | ||||||
| 	rev[n++] = get_commit_reference(current_bad_sha1); | 	rev[n++] = get_commit_reference(current_bad_sha1); | ||||||
| 	for (i = 0; i < good_revs.sha1_nr; i++) | 	for (i = 0; i < good_revs.nr; i++) | ||||||
| 		rev[n++] = get_commit_reference(good_revs.sha1[i]); | 		rev[n++] = get_commit_reference(good_revs.sha1[i]); | ||||||
| 	*rev_nr = n; | 	*rev_nr = n; | ||||||
|  |  | ||||||
|  | @ -840,9 +800,9 @@ static void check_merge_bases(void) | ||||||
| 		const unsigned char *mb = result->item->object.sha1; | 		const unsigned char *mb = result->item->object.sha1; | ||||||
| 		if (!hashcmp(mb, current_bad_sha1)) { | 		if (!hashcmp(mb, current_bad_sha1)) { | ||||||
| 			handle_bad_merge_base(); | 			handle_bad_merge_base(); | ||||||
| 		} else if (0 <= lookup_sha1_array(&good_revs, mb)) { | 		} else if (0 <= sha1_array_lookup(&good_revs, mb)) { | ||||||
| 			continue; | 			continue; | ||||||
| 		} else if (0 <= lookup_sha1_array(&skipped_revs, mb)) { | 		} else if (0 <= sha1_array_lookup(&skipped_revs, mb)) { | ||||||
| 			handle_skipped_merge_base(mb); | 			handle_skipped_merge_base(mb); | ||||||
| 		} else { | 		} else { | ||||||
| 			printf("Bisecting: a merge base must be tested\n"); | 			printf("Bisecting: a merge base must be tested\n"); | ||||||
|  | @ -903,7 +863,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	/* Bisecting with no good rev is ok. */ | 	/* Bisecting with no good rev is ok. */ | ||||||
| 	if (good_revs.sha1_nr == 0) | 	if (good_revs.nr == 0) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	/* Check if all good revs are ancestor of the bad rev. */ | 	/* Check if all good revs are ancestor of the bad rev. */ | ||||||
|  | @ -968,7 +928,7 @@ int bisect_next_all(const char *prefix) | ||||||
| 	bisect_common(&revs); | 	bisect_common(&revs); | ||||||
|  |  | ||||||
| 	revs.commits = find_bisection(revs.commits, &reaches, &all, | 	revs.commits = find_bisection(revs.commits, &reaches, &all, | ||||||
| 				       !!skipped_revs.sha1_nr); | 				       !!skipped_revs.nr); | ||||||
| 	revs.commits = managed_skipped(revs.commits, &tried); | 	revs.commits = managed_skipped(revs.commits, &tried); | ||||||
|  |  | ||||||
| 	if (!revs.commits) { | 	if (!revs.commits) { | ||||||
|  |  | ||||||
|  | @ -0,0 +1,43 @@ | ||||||
|  | #include "cache.h" | ||||||
|  | #include "sha1-array.h" | ||||||
|  | #include "sha1-lookup.h" | ||||||
|  |  | ||||||
|  | void sha1_array_append(struct sha1_array *array, const unsigned char *sha1) | ||||||
|  | { | ||||||
|  | 	ALLOC_GROW(array->sha1, array->nr + 1, array->alloc); | ||||||
|  | 	hashcpy(array->sha1[array->nr++], sha1); | ||||||
|  | 	array->sorted = 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int void_hashcmp(const void *a, const void *b) | ||||||
|  | { | ||||||
|  | 	return hashcmp(a, b); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void sha1_array_sort(struct sha1_array *array) | ||||||
|  | { | ||||||
|  | 	qsort(array->sha1, array->nr, sizeof(*array->sha1), void_hashcmp); | ||||||
|  | 	array->sorted = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static const unsigned char *sha1_access(size_t index, void *table) | ||||||
|  | { | ||||||
|  | 	unsigned char (*array)[20] = table; | ||||||
|  | 	return array[index]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int sha1_array_lookup(struct sha1_array *array, const unsigned char *sha1) | ||||||
|  | { | ||||||
|  | 	if (!array->sorted) | ||||||
|  | 		sha1_array_sort(array); | ||||||
|  | 	return sha1_pos(sha1, array->sha1, array->nr, sha1_access); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void sha1_array_clear(struct sha1_array *array) | ||||||
|  | { | ||||||
|  | 	free(array->sha1); | ||||||
|  | 	array->sha1 = NULL; | ||||||
|  | 	array->nr = 0; | ||||||
|  | 	array->alloc = 0; | ||||||
|  | 	array->sorted = 0; | ||||||
|  | } | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | #ifndef SHA1_ARRAY_H | ||||||
|  | #define SHA1_ARRAY_H | ||||||
|  |  | ||||||
|  | struct sha1_array { | ||||||
|  | 	unsigned char (*sha1)[20]; | ||||||
|  | 	int nr; | ||||||
|  | 	int alloc; | ||||||
|  | 	int sorted; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define SHA1_ARRAY_INIT { NULL, 0, 0, 0 } | ||||||
|  |  | ||||||
|  | void sha1_array_append(struct sha1_array *array, const unsigned char *sha1); | ||||||
|  | void sha1_array_sort(struct sha1_array *array); | ||||||
|  | int sha1_array_lookup(struct sha1_array *array, const unsigned char *sha1); | ||||||
|  | void sha1_array_clear(struct sha1_array *array); | ||||||
|  |  | ||||||
|  | #endif /* SHA1_ARRAY_H */ | ||||||
		Loading…
	
		Reference in New Issue
	
	 Jeff King
						Jeff King