Commit Diff


commit - 013404a990deb32cbdbb7b721480633ba67ffdb3
commit + 98abbc8404f0fa4e8d10cea8ec22c4b2d2cb0f64
blob - 8fed0efda697f89b5d9ea163a1dc5d9a5a406a02
blob + 93179e12ca821cce26e7df9bf46b4fad6c2b6839
--- lib/diff.c
+++ lib/diff.c
@@ -65,6 +65,7 @@ got_diff_blob(struct got_blob_object *blob1, struct go
 	FILE *f1 = NULL, *f2 = NULL;
 	char hex1[SHA1_DIGEST_STRING_LENGTH];
 	char hex2[SHA1_DIGEST_STRING_LENGTH];
+	char *idstr1 = NULL, *idstr2 = NULL;
 	size_t len, hdrlen;
 	int res, flags = 0;
 
@@ -84,9 +85,8 @@ got_diff_blob(struct got_blob_object *blob1, struct go
 	} else
 		flags |= D_EMPTY2;
 
-	if (blob1 == NULL) {
-		f1 = NULL;
-	} else {
+	if (blob1) {
+		idstr1 = got_object_id_str(&blob1->id, hex1, sizeof(hex1));
 		hdrlen = blob1->hdrlen;
 		do {
 			err = got_object_blob_read_block(blob1, &len);
@@ -96,44 +96,51 @@ got_diff_blob(struct got_blob_object *blob1, struct go
 			fwrite(blob1->zb.outbuf + hdrlen, len - hdrlen, 1, f1);
 			hdrlen = 0;
 		} while (len != 0);
-	}
+	} else
+		idstr1 = "/dev/null";
 
-	hdrlen = blob2->hdrlen;
-	do {
-		err = got_object_blob_read_block(blob2, &len);
-		if (err)
-			goto done;
-		/* Skip blob object header first time around. */
-		fwrite(blob2->zb.outbuf + hdrlen, len - hdrlen, 1, f2);
-		hdrlen = 0;
-	} while (len != 0);
+	if (blob2) {
+		idstr2 = got_object_id_str(&blob2->id, hex2, sizeof(hex2));
+		hdrlen = blob2->hdrlen;
+		do {
+			err = got_object_blob_read_block(blob2, &len);
+			if (err)
+				goto done;
+			/* Skip blob object header first time around. */
+			fwrite(blob2->zb.outbuf + hdrlen, len - hdrlen, 1, f2);
+			hdrlen = 0;
+		} while (len != 0);
+	} else
+		idstr2 = "/dev/null";
 
-	fflush(f1);
-	fflush(f2);
-	/* rewind(f1); */
-	/* rewind(f2);*/
+	if (f1)
+		fflush(f1);
+	if (f2)
+		fflush(f2);
 
 	memset(&ds, 0, sizeof(ds));
 	/* XXX should stat buffers be passed in args instead of ds? */
 	ds.stb1.st_mode = S_IFREG;
-	ds.stb1.st_size = blob1->zb.z.total_out;
+	if (blob1)
+		ds.stb1.st_size = blob1->zb.z.total_out;
 	ds.stb1.st_mtime = 0; /* XXX */
 
 	ds.stb2.st_mode = S_IFREG;
-	ds.stb2.st_size = blob2->zb.z.total_out;
+	if (blob2)
+		ds.stb2.st_size = blob2->zb.z.total_out;
 	ds.stb2.st_mtime = 0; /* XXX */
 
 	memset(&args, 0, sizeof(args));
 	args.diff_format = D_UNIFIED;
-	args.label[0] = label1 ?
-	    label1 : got_object_id_str(&blob1->id, hex1, sizeof(hex1));
-	args.label[1] = label2 ?
-	    label2 : got_object_id_str(&blob2->id, hex2, sizeof(hex2));
+	args.label[0] = label1 ? label1 : idstr1;
+	args.label[1] = label2 ? label2 : idstr2;
 
 	err = got_diffreg(&res, f1, f2, flags, &args, &ds, outfile);
 done:
-	fclose(f1);
-	fclose(f2);
+	if (f1)
+		fclose(f1);
+	if (f2)
+		fclose(f2);
 	return err;
 }
 
blob - c589fb48ea301eb26dbf1f700b9d3de89a88338f
blob + 134e586b5f43b5ae6841c882e192c91afb3b7009
--- regress/repository/repository_test.c
+++ regress/repository/repository_test.c
@@ -283,6 +283,63 @@ repo_diff_blob(const char *repo_path)
 
 	got_object_blob_close(blob1);
 	got_object_blob_close(blob2);
+	got_object_close(obj1);
+	got_object_close(obj2);
+	got_repo_close(repo);
+	return (err == NULL);
+}
+
+static int
+repo_diff_tree(const char *repo_path)
+{
+	const char *blob1_sha1 = "1efc41caf761a0a1f119d0c5121eedcb2e7a88c3";
+	const char *blob2_sha1 = "cb4ba67a335b2b7ecac88867063596bd9e1ab485";
+	const struct got_error *err;
+	struct got_repository *repo;
+	struct got_object_id id1;
+	struct got_object_id id2;
+	struct got_object *obj1;
+	struct got_object *obj2;
+	struct got_tree_object *tree1;
+	struct got_tree_object *tree2;
+	char hex[SHA1_DIGEST_STRING_LENGTH];
+	int i;
+	size_t len;
+
+	if (!got_parse_sha1_digest(id1.sha1, blob1_sha1))
+		return 0;
+	if (!got_parse_sha1_digest(id2.sha1, blob2_sha1))
+		return 0;
+
+	err = got_repo_open(&repo, repo_path);
+	if (err != NULL || repo == NULL)
+		return 0;
+
+	err = got_object_open(&obj1, repo, &id1);
+	if (err != NULL || obj1 == NULL)
+		return 0;
+	if (obj1->type != GOT_OBJ_TYPE_TREE)
+		return 0;
+	err = got_object_open(&obj2, repo, &id2);
+	if (err != NULL || obj2 == NULL)
+		return 0;
+	if (obj2->type != GOT_OBJ_TYPE_TREE)
+		return 0;
+
+	err = got_object_tree_open(&tree1, repo, obj1);
+	if (err != NULL)
+		return 0;
+
+	err = got_object_tree_open(&tree2, repo, obj2);
+	if (err != NULL)
+		return 0;
+
+	putchar('\n');
+	got_diff_tree(tree1, tree2, repo);
+	putchar('\n');
+
+	got_object_tree_close(tree1);
+	got_object_tree_close(tree2);
 	got_object_close(obj1);
 	got_object_close(obj2);
 	got_repo_close(repo);
@@ -307,6 +364,7 @@ main(int argc, const char *argv[])
 	RUN_TEST(repo_read_log(repo_path), "read_log");
 	RUN_TEST(repo_read_blob(repo_path), "read_blob");
 	RUN_TEST(repo_diff_blob(repo_path), "diff_blob");
+	RUN_TEST(repo_diff_tree(repo_path), "diff_tree");
 
 	return failure ? 1 : 0;
 }