Merge branch 'jk/for-each-reflog-ent-reverse' into maint
* jk/for-each-reflog-ent-reverse: for_each_reflog_ent_reverse: turn leftover check into assertion for_each_reflog_ent_reverse: fix newlines on block boundariesmaint
						commit
						417a5b226c
					
				
							
								
								
									
										51
									
								
								refs.c
								
								
								
								
							
							
						
						
									
										51
									
								
								refs.c
								
								
								
								
							|  | @ -3404,29 +3404,54 @@ int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void | ||||||
|  |  | ||||||
| 			bp = find_beginning_of_line(buf, scanp); | 			bp = find_beginning_of_line(buf, scanp); | ||||||
|  |  | ||||||
| 			if (*bp != '\n') { | 			if (*bp == '\n') { | ||||||
| 				strbuf_splice(&sb, 0, 0, buf, endp - buf); |  | ||||||
| 				if (pos) |  | ||||||
| 					break; /* need to fill another block */ |  | ||||||
| 				scanp = buf - 1; /* leave loop */ |  | ||||||
| 			} else { |  | ||||||
| 				/* | 				/* | ||||||
| 				 * (bp + 1) thru endp is the beginning of the | 				 * The newline is the end of the previous line, | ||||||
| 				 * current line we have in sb | 				 * so we know we have complete line starting | ||||||
|  | 				 * at (bp + 1). Prefix it onto any prior data | ||||||
|  | 				 * we collected for the line and process it. | ||||||
| 				 */ | 				 */ | ||||||
| 				strbuf_splice(&sb, 0, 0, bp + 1, endp - (bp + 1)); | 				strbuf_splice(&sb, 0, 0, bp + 1, endp - (bp + 1)); | ||||||
| 				scanp = bp; | 				scanp = bp; | ||||||
| 				endp = bp + 1; | 				endp = bp + 1; | ||||||
| 			} | 				ret = show_one_reflog_ent(&sb, fn, cb_data); | ||||||
| 			ret = show_one_reflog_ent(&sb, fn, cb_data); | 				strbuf_reset(&sb); | ||||||
| 			strbuf_reset(&sb); | 				if (ret) | ||||||
| 			if (ret) | 					break; | ||||||
|  | 			} else if (!pos) { | ||||||
|  | 				/* | ||||||
|  | 				 * We are at the start of the buffer, and the | ||||||
|  | 				 * start of the file; there is no previous | ||||||
|  | 				 * line, and we have everything for this one. | ||||||
|  | 				 * Process it, and we can end the loop. | ||||||
|  | 				 */ | ||||||
|  | 				strbuf_splice(&sb, 0, 0, buf, endp - buf); | ||||||
|  | 				ret = show_one_reflog_ent(&sb, fn, cb_data); | ||||||
|  | 				strbuf_reset(&sb); | ||||||
| 				break; | 				break; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (bp == buf) { | ||||||
|  | 				/* | ||||||
|  | 				 * We are at the start of the buffer, and there | ||||||
|  | 				 * is more file to read backwards. Which means | ||||||
|  | 				 * we are in the middle of a line. Note that we | ||||||
|  | 				 * may get here even if *bp was a newline; that | ||||||
|  | 				 * just means we are at the exact end of the | ||||||
|  | 				 * previous line, rather than some spot in the | ||||||
|  | 				 * middle. | ||||||
|  | 				 * | ||||||
|  | 				 * Save away what we have to be combined with | ||||||
|  | 				 * the data from the next read. | ||||||
|  | 				 */ | ||||||
|  | 				strbuf_splice(&sb, 0, 0, buf, endp - buf); | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
| 	if (!ret && sb.len) | 	if (!ret && sb.len) | ||||||
| 		ret = show_one_reflog_ent(&sb, fn, cb_data); | 		die("BUG: reverse reflog parser had leftover data"); | ||||||
|  |  | ||||||
| 	fclose(logfp); | 	fclose(logfp); | ||||||
| 	strbuf_release(&sb); | 	strbuf_release(&sb); | ||||||
|  |  | ||||||
|  | @ -287,4 +287,34 @@ test_expect_success 'stale dirs do not cause d/f conflicts (reflogs off)' ' | ||||||
| 	test_cmp expect actual | 	test_cmp expect actual | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | # Triggering the bug detected by this test requires a newline to fall | ||||||
|  | # exactly BUFSIZ-1 bytes from the end of the file. We don't know | ||||||
|  | # what that value is, since it's platform dependent. However, if | ||||||
|  | # we choose some value N, we also catch any D which divides N evenly | ||||||
|  | # (since we will read backwards in chunks of D). So we choose 8K, | ||||||
|  | # which catches glibc (with an 8K BUFSIZ) and *BSD (1K). | ||||||
|  | # | ||||||
|  | # Each line is 114 characters, so we need 75 to still have a few before the | ||||||
|  | # last 8K. The 89-character padding on the final entry lines up our | ||||||
|  | # newline exactly. | ||||||
|  | test_expect_success 'parsing reverse reflogs at BUFSIZ boundaries' ' | ||||||
|  | 	git checkout -b reflogskip && | ||||||
|  | 	z38=00000000000000000000000000000000000000 && | ||||||
|  | 	ident="abc <xyz> 0000000001 +0000" && | ||||||
|  | 	for i in $(test_seq 1 75); do | ||||||
|  | 		printf "$z38%02d $z38%02d %s\t" $i $(($i+1)) "$ident" && | ||||||
|  | 		if test $i = 75; then | ||||||
|  | 			for j in $(test_seq 1 89); do | ||||||
|  | 				printf X | ||||||
|  | 			done | ||||||
|  | 		else | ||||||
|  | 			printf X | ||||||
|  | 		fi && | ||||||
|  | 		printf "\n" | ||||||
|  | 	done >.git/logs/refs/heads/reflogskip && | ||||||
|  | 	git rev-parse reflogskip@{73} >actual && | ||||||
|  | 	echo ${z38}03 >expect && | ||||||
|  | 	test_cmp expect actual | ||||||
|  | ' | ||||||
|  |  | ||||||
| test_done | test_done | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano