Commit Diff


commit - 84f17c46f2598468c88e7a8d02b10e314162f647
commit + b02560eced1f0b170085e9c5aa73e835beea3dac
blob - eb5fcb7a53932972a7d3230e79c09ecc1e5f0dab
blob + 81e94d2a06cec2500840550ba922519e89c869c8
--- got/got.c
+++ got/got.c
@@ -2285,6 +2285,7 @@ cmd_blame(int argc, char *argv[])
 	char *commit_id_str = NULL;
 	struct blame_cb_args bca;
 	int ch, obj_type, i;
+	size_t filesize;
 
 #ifndef PROFILE
 	if (pledge("stdio rpath wpath cpath flock proc exec sendfd unveil",
@@ -2411,11 +2412,15 @@ cmd_blame(int argc, char *argv[])
 		error = got_error_from_errno("got_opentemp");
 		goto done;
 	}
-	error = got_object_blob_dump_to_file(NULL, &bca.nlines,
+	error = got_object_blob_dump_to_file(&filesize, &bca.nlines,
 	    &bca.line_offsets, bca.f, blob);
 	if (error || bca.nlines == 0)
 		goto done;
 
+	/* Don't include \n at EOF in the blame line count. */
+	if (bca.line_offsets[bca.nlines - 1] == filesize)
+		bca.nlines--;
+
 	bca.lines = calloc(bca.nlines, sizeof(*bca.lines));
 	if (bca.lines == NULL) {
 		error = got_error_from_errno("calloc");
blob - a1b4bd57e86473bd5bd845a4ee2c6601b8df3430
blob + df12bfb1268e9700fcdafe8129ce1e07f5248a33
--- lib/blame.c
+++ lib/blame.c
@@ -344,8 +344,12 @@ blame_open(struct got_blame **blamep, const char *path
 	}
 	err = got_object_blob_dump_to_file(&blame->filesize, &blame->nlines,
 	   &blame->line_offsets, blame->f, blob);
-	if (err)
+	if (err || blame->nlines == 0)
 		goto done;
+
+	/* Don't include \n at EOF in the blame line count. */
+	if (blame->line_offsets[blame->nlines - 1] == blame->filesize)
+		blame->nlines--;
 
 	blame->lines = calloc(blame->nlines, sizeof(*blame->lines));
 	if (blame->lines == NULL) {
blob - 14011f6a3b2ed86c5a236597eb7384119033b4c4
blob + a47efb07e8c0310f225ecd2a079dafb706f795fb
--- lib/object.c
+++ lib/object.c
@@ -1164,6 +1164,7 @@ got_object_blob_dump_to_file(size_t *filesize, int *nl
 		if (len == 0)
 			break;
 		buf = got_object_blob_get_read_buf(blob);
+		i = hdrlen;
 		if (line_offsets && nlines) {
 			if (*line_offsets == NULL) {
 				/* Have some data but perhaps no '\n'. */
@@ -1172,11 +1173,20 @@ got_object_blob_dump_to_file(size_t *filesize, int *nl
 				*line_offsets = calloc(1, sizeof(**line_offsets));
 				if (*line_offsets == NULL)
 					return got_error_from_errno("malloc");
-			}
-			/* Scan '\n' offsets in this chunk of data. */
-			for (i = hdrlen; i < len; i++) {
-				if (buf[i] != '\n')
+
+				/* Skip forward over end of first line. */
+				while (i < len) {
+					if (buf[i] == '\n')
+						break;
+					i++;
+				}
+			}
+			/* Scan '\n' offsets in remaining chunk of data. */
+			while (i < len) {
+				if (buf[i] != '\n') {
+					i++;
 					continue;
+				}
 				(*nlines)++;
 				if (noffsets < *nlines) {
 					off_t *o = recallocarray(*line_offsets,
@@ -1193,6 +1203,7 @@ got_object_blob_dump_to_file(size_t *filesize, int *nl
 				}
 				off = total_len + i - hdrlen + 1;
 				(*line_offsets)[*nlines - 1] = off;
+				i++;
 			}
 		}
 		/* Skip blob object header first time around. */
blob - a4136fea5133d35c4c4b1acc1e44ae5886cf894f
blob + 8019b23a5036ede951002c3d0bc629636a152963
--- tog/tog.c
+++ tog/tog.c
@@ -3248,8 +3248,12 @@ run_blame(struct tog_blame *blame, struct tog_view *vi
 	}
 	err = got_object_blob_dump_to_file(&blame->filesize, &blame->nlines,
 	    &blame->line_offsets, blame->f, blob);
-	if (err)
+	if (err || blame->nlines == 0)
 		goto done;
+
+	/* Don't include \n at EOF in the blame line count. */
+	if (blame->line_offsets[blame->nlines - 1] == blame->filesize)
+		blame->nlines--;
 
 	blame->lines = calloc(blame->nlines, sizeof(*blame->lines));
 	if (blame->lines == NULL) {