mirror of
				https://git.proxmox.com/git/libgit2
				synced 2025-10-31 09:24:17 +00:00 
			
		
		
		
	Fix mark_parents() to account for bad luck traversals
If commit timestamps are off, we're more likely to hit a traversal where the first path ends up traversing past the root commit of the tree. If that happens, it's possible that the loop will complete before the second path marks some of those final parents. This fix keeps track of the root nodes that are encountered in the traversal, and verify that they are properly marked. In the best case, with accurate timestamps, the traversal will continue to terminate when all the commits are STALE (parents of a merge-base), as it did before. In the worst case, where one path makes a complete traversal past a root commit, we will continue the loop until the root commit itself is marked.
This commit is contained in:
		
							parent
							
								
									b337814e70
								
							
						
					
					
						commit
						e51c8b99be
					
				
							
								
								
									
										20
									
								
								src/graph.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/graph.c
									
									
									
									
									
								
							| @ -10,7 +10,7 @@ | ||||
| #include "merge.h" | ||||
| #include "git2/graph.h" | ||||
| 
 | ||||
| static int interesting(git_pqueue *list) | ||||
| static int interesting(git_pqueue *list, git_commit_list *roots) | ||||
| { | ||||
| 	unsigned int i; | ||||
| 	/* element 0 isn't used - we need to start at 1 */ | ||||
| @ -20,6 +20,12 @@ static int interesting(git_pqueue *list) | ||||
| 			return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	while(roots) { | ||||
| 		if ((roots->item->flags & STALE) == 0) | ||||
| 			return 1; | ||||
| 		roots = roots->next; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| @ -28,6 +34,7 @@ static int mark_parents(git_revwalk *walk, git_commit_list_node *one, | ||||
| { | ||||
| 	int error; | ||||
| 	unsigned int i; | ||||
| 	git_commit_list *roots = NULL; | ||||
| 	git_pqueue list; | ||||
| 
 | ||||
| 	/* if the commit is repeated, we have a our merge base already */ | ||||
| @ -52,11 +59,13 @@ static int mark_parents(git_revwalk *walk, git_commit_list_node *one, | ||||
| 		return -1; | ||||
| 
 | ||||
| 	/* as long as there are non-STALE commits */ | ||||
| 	while (interesting(&list)) { | ||||
| 	while (interesting(&list, roots)) { | ||||
| 		git_commit_list_node *commit; | ||||
| 		int flags; | ||||
| 
 | ||||
| 		commit = git_pqueue_pop(&list); | ||||
| 		if (commit == NULL) | ||||
| 			break; | ||||
| 
 | ||||
| 		flags = commit->flags & (PARENT1 | PARENT2 | STALE); | ||||
| 		if (flags == (PARENT1 | PARENT2)) { | ||||
| @ -78,8 +87,15 @@ static int mark_parents(git_revwalk *walk, git_commit_list_node *one, | ||||
| 			if (git_pqueue_insert(&list, p) < 0) | ||||
| 				return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		if (commit->out_degree == 0) { | ||||
| 			if (git_commit_list_insert(commit, &roots) == NULL) | ||||
| 				return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (roots) | ||||
| 		git_commit_list_free(&roots); | ||||
| 	git_pqueue_free(&list); | ||||
| 
 | ||||
| 	return 0; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Scott J. Goldman
						Scott J. Goldman