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
					
				
							
								
								
									
										45
									
								
								refs.c
								
								
								
								
							
							
						
						
									
										45
									
								
								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); | ||||
|  | ||||
| 			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 { | ||||
| 			if (*bp == '\n') { | ||||
| 				/* | ||||
| 				 * (bp + 1) thru endp is the beginning of the | ||||
| 				 * current line we have in sb | ||||
| 				 * The newline is the end of the previous line, | ||||
| 				 * 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)); | ||||
| 				scanp = bp; | ||||
| 				endp = bp + 1; | ||||
| 			} | ||||
| 				ret = show_one_reflog_ent(&sb, fn, cb_data); | ||||
| 				strbuf_reset(&sb); | ||||
| 				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; | ||||
| 			} | ||||
|  | ||||
| 			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) | ||||
| 		ret = show_one_reflog_ent(&sb, fn, cb_data); | ||||
| 		die("BUG: reverse reflog parser had leftover data"); | ||||
|  | ||||
| 	fclose(logfp); | ||||
| 	strbuf_release(&sb); | ||||
|  |  | |||
|  | @ -287,4 +287,34 @@ test_expect_success 'stale dirs do not cause d/f conflicts (reflogs off)' ' | |||
| 	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 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano