Commit a3e2cbea8743ac575f4afe7fa29ff08a3ff46135

Stefan Sperling 2017-12-01T22:09:59

make tree diffing work

diff --git a/lib/diff.c b/lib/diff.c
index 93179e1..0f5eb9b 100644
--- a/lib/diff.c
+++ b/lib/diff.c
@@ -144,11 +144,15 @@ done:
 	return err;
 }
 
-static const struct got_error *
-match_entry_by_name(struct got_tree_entry **te, struct got_tree_entry *te1,
-    struct got_tree_object *tree2)
+struct got_tree_entry *
+match_entry_by_name(struct got_tree_entry *te1, struct got_tree_object *tree2)
 {
-	*te = NULL;
+	struct got_tree_entry *te2;
+
+	SIMPLEQ_FOREACH(te2, &tree2->entries, entry) {
+		if (strcmp(te1->name, te2->name) == 0)
+			return te2;
+	}
 	return NULL;
 }
 
@@ -218,10 +222,14 @@ diff_modified_blob(struct got_object_id *id1, struct got_object_id *id2,
 	err = got_diff_blob(blob1, blob2, NULL, NULL, stdout);
 
 done:
-	got_object_close(obj1);
-	got_object_close(obj2);
-	got_object_blob_close(blob1);
-	got_object_blob_close(blob2);
+	if (obj1)
+		got_object_close(obj1);
+	if (obj2)
+		got_object_close(obj2);
+	if (blob1)
+		got_object_blob_close(blob1);
+	if (blob2)
+		got_object_blob_close(blob2);
 	return err;
 }
 
@@ -365,10 +373,9 @@ diff_entry_old_new(struct got_tree_entry *te1, struct got_tree_object *tree2,
 {
 	const struct got_error *err;
 	struct got_tree_entry *te2;
+	char hex[SHA1_DIGEST_STRING_LENGTH];
 
-	err = match_entry_by_name(&te2, te1, tree2);
-	if (err)
-		return err;
+	te2 = match_entry_by_name(te1, tree2);
 	if (te2 == NULL) {
 		if (S_ISDIR(te1->mode))
 			return diff_deleted_tree(&te1->id, repo);
@@ -381,6 +388,7 @@ diff_entry_old_new(struct got_tree_entry *te1, struct got_tree_object *tree2,
 	} else if (S_ISREG(te1->mode) && S_ISREG(te2->mode)) {
 		if (!same_id(&te1->id, &te2->id))
 			return diff_modified_blob(&te1->id, &te2->id, repo);
+
 	}
 
 	return diff_kind_mismatch(&te1->id, &te2->id);
@@ -393,9 +401,7 @@ diff_entry_new_old(struct got_tree_entry *te2, struct got_tree_object *tree1,
 	const struct got_error *err;
 	struct got_tree_entry *te1;
 
-	err = match_entry_by_name(&te1, te2, tree1);
-	if (err)
-		return err;
+	te1 = match_entry_by_name(te2, tree1);
 	if (te1 != NULL) /* handled by diff_entry_old_new() */
 		return NULL;
 
diff --git a/lib/diffreg.c b/lib/diffreg.c
index 79eb0a8..c39cd8c 100644
--- a/lib/diffreg.c
+++ b/lib/diffreg.c
@@ -918,7 +918,7 @@ change(FILE *outfile, struct got_diff_state *ds, struct got_diff_args *args,
     const char *file1, FILE *f1, const char *file2, FILE *f2,
     int a, int b, int c, int d, int *pflags)
 {
-	static size_t max_context = 64;
+	size_t max_context = 64;
 	int i;
 
 restart:
diff --git a/lib/object.c b/lib/object.c
index cccf552..779aab7 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -120,27 +120,27 @@ inflate_read(struct got_zstream_buf *zb, FILE *f, size_t *outlenp)
 	z->next_out = zb->outbuf;
 	z->avail_out = zb->outlen;
 
-	if (z->avail_in == 0 && (zb->flags & GOT_ZSTREAM_F_HAVE_MORE) == 0) {
-		int i;
-		n = fread(zb->inbuf, 1, zb->inlen, f);
-		if (n == 0) {
-			if (ferror(f))
-				return got_error(GOT_ERR_IO);
-			*outlenp = 0;
-			return NULL;
+	do {
+		if (z->avail_in == 0) {
+			int i;
+			n = fread(zb->inbuf, 1, zb->inlen, f);
+			if (n == 0) {
+				if (ferror(f))
+					return got_error(GOT_ERR_IO);
+				*outlenp = 0;
+				return NULL;
+			}
+			z->next_in = zb->inbuf;
+			z->avail_in = n;
 		}
-		z->next_in = zb->inbuf;
-		z->avail_in = n;
-	}
+		ret = inflate(z, Z_SYNC_FLUSH);
+	} while (ret == Z_OK && z->avail_out > 0);
 
-	ret = inflate(z, Z_SYNC_FLUSH);
-	if (ret == Z_OK) {
-		if (z->avail_out == 0)
-			zb->flags |= GOT_ZSTREAM_F_HAVE_MORE;
-		else
-			zb->flags &= ~GOT_ZSTREAM_F_HAVE_MORE;
-	} else if (ret != Z_STREAM_END)
-		return got_error(GOT_ERR_DECOMPRESSION);
+	if (ret != Z_OK) {
+		if (ret != Z_STREAM_END)
+			return got_error(GOT_ERR_DECOMPRESSION);
+		zb->flags |= GOT_ZSTREAM_F_HAVE_MORE;
+	}
 
 	*outlenp = z->total_out - last_total_out;
 	return NULL;
@@ -203,6 +203,9 @@ read_object_header(struct got_object **obj, struct got_repository *repo,
 	const struct got_error *err;
 	FILE *f;
 	struct got_zstream_buf zb;
+	char *buf;
+	size_t totalsz;
+	const size_t zbsize = 64;
 	size_t outlen;
 	int i, ret;
 
@@ -210,17 +213,31 @@ read_object_header(struct got_object **obj, struct got_repository *repo,
 	if (f == NULL)
 		return got_error(GOT_ERR_BAD_PATH);
 
-	err = inflate_init(&zb, 64);
+	totalsz = zbsize;
+	buf = calloc(totalsz, sizeof(char));
+	if (buf == NULL)
+		return got_error(GOT_ERR_NO_MEM);
+
+	err = inflate_init(&zb, zbsize);
 	if (err) {
 		fclose(f);
 		return err;
 	}
 
-	err = inflate_read(&zb, f, &outlen);
-	if (err)
-		goto done;
+	i = 0;
+	do {
+		err = inflate_read(&zb, f, &outlen);
+		if (err)
+			goto done;
+		if (strchr(zb.outbuf, '\0') == NULL) {
+			buf = recallocarray(buf, 1 + i, 2 + i, zbsize);
+			totalsz += zbsize;
+		}
+		memcpy(buf, zb.outbuf, zbsize);
+		i++;
+	} while (strchr(zb.outbuf, '\0') == NULL);
 
-	err = parse_object_header(obj, zb.outbuf, outlen);
+	err = parse_object_header(obj, buf, totalsz);
 done:
 	inflate_end(&zb);
 	fclose(f);
diff --git a/regress/repository/repository_test.c b/regress/repository/repository_test.c
index 9e73397..6abb0c9 100644
--- a/regress/repository/repository_test.c
+++ b/regress/repository/repository_test.c
@@ -293,7 +293,7 @@ static int
 repo_diff_tree(const char *repo_path)
 {
 	const char *tree1_sha1 = "1efc41caf761a0a1f119d0c5121eedcb2e7a88c3";
-	const char *tree2_sha1 = "cb4ba67a335b2b7ecac88867063596bd9e1ab485";
+	const char *tree2_sha1 = "4aa8f2933839ff8a8fb3f905a4c232d22c6ff5f3";
 	const struct got_error *err;
 	struct got_repository *repo;
 	struct got_object_id id1;