Commit b02560eced1f0b170085e9c5aa73e835beea3dac

Stefan Sperling 2019-08-19T09:54:52

fix number of lines accounted for during blame

diff --git a/got/got.c b/got/got.c
index eb5fcb7..81e94d2 100644
--- a/got/got.c
+++ b/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");
diff --git a/lib/blame.c b/lib/blame.c
index a1b4bd5..df12bfb 100644
--- a/lib/blame.c
+++ b/lib/blame.c
@@ -344,9 +344,13 @@ 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) {
 		err = got_error_from_errno("calloc");
diff --git a/lib/object.c b/lib/object.c
index 14011f6..a47efb0 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -1164,6 +1164,7 @@ got_object_blob_dump_to_file(size_t *filesize, int *nlines,
 		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 *nlines,
 				*line_offsets = calloc(1, sizeof(**line_offsets));
 				if (*line_offsets == NULL)
 					return got_error_from_errno("malloc");
+
+				/* Skip forward over end of first line. */
+				while (i < len) {
+					if (buf[i] == '\n')
+						break;
+					i++;
+				}
 			}
-			/* Scan '\n' offsets in this chunk of data. */
-			for (i = hdrlen; i < len; i++) {
-				if (buf[i] != '\n')
+			/* 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 *nlines,
 				}
 				off = total_len + i - hdrlen + 1;
 				(*line_offsets)[*nlines - 1] = off;
+				i++;
 			}
 		}
 		/* Skip blob object header first time around. */
diff --git a/tog/tog.c b/tog/tog.c
index a4136fe..8019b23 100644
--- a/tog/tog.c
+++ b/tog/tog.c
@@ -3248,9 +3248,13 @@ run_blame(struct tog_blame *blame, struct tog_view *view, int *blame_complete,
 	}
 	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) {
 		err = got_error_from_errno("calloc");