Commit Diff


commit - 3c1f04f18c0c08476bd685984b0fb6801017b11d
commit + f6861a8122f025e3ba8dd3c13215c27b6bf184cb
blob - be58cf339b920db7909cf38049c0b61c5d291788
blob + 54674805bc2ad0b54c4592914c85b28726a3073c
--- got/got.c
+++ got/got.c
@@ -290,7 +290,7 @@ print_patch(struct got_commit_object *commit, struct g
 			return err;
 	}
 
-	err = got_diff_tree(tree1, tree2, repo, stdout);
+	err = got_diff_tree(tree1, tree2, "", "", repo, stdout);
 	if (tree1)
 		got_object_tree_close(tree1);
 	got_object_tree_close(tree2);
@@ -717,10 +717,12 @@ cmd_diff(int argc, char *argv[])
 
 	switch (got_object_get_type(obj1)) {
 	case GOT_OBJ_TYPE_BLOB:
-		error = got_diff_objects_as_blobs(obj1, obj2, repo, stdout);
+		error = got_diff_objects_as_blobs(obj1, obj2, NULL, NULL,
+		    repo, stdout);
 		break;
 	case GOT_OBJ_TYPE_TREE:
-		error = got_diff_objects_as_trees(obj1, obj2, repo, stdout);
+		error = got_diff_objects_as_trees(obj1, obj2, "", "", repo,
+		    stdout);
 		break;
 	case GOT_OBJ_TYPE_COMMIT:
 		error = got_diff_objects_as_commits(obj1, obj2, repo, stdout);
blob - 0f04bd8dc24610ab8b6aa4a71934829503df5230
blob + c92aa2f05fa3e54c44c247060cc5cfb9aa5690cb
--- include/got_diff.h
+++ include/got_diff.h
@@ -25,24 +25,32 @@ const struct got_error *got_diff_blob(struct got_blob_
 
 /*
  * Compute the differences between two trees and write unified diff text
- * to the provided output FILE.
+ * to the provided output FILE. Two const char * diff header labels may
+ * be provided which will be used to identify each blob in the diff output.
+ * If a label is NULL, use the blob's SHA1 checksum instead.
  */
 const struct got_error *got_diff_tree(struct got_tree_object *,
-    struct got_tree_object *, struct got_repository *, FILE *);
+    struct got_tree_object *, const char *label1, const char *label2,
+    struct got_repository *, FILE *);
 
 /*
- * Diff two objects, assuming both objects are blobs.
+ * Diff two objects, assuming both objects are blobs. Two const char * diff
+ * header labels may be provided which will be used to identify each blob in
+ * the diff output. If a label is NULL, use the blob's SHA1 checksum instead.
  * Write unified diff text to the provided output FILE.
  */
 const struct got_error *got_diff_objects_as_blobs(struct got_object *,
-    struct got_object *, struct got_repository *, FILE *);
+    struct got_object *, const char *, const char *, struct got_repository *,
+    FILE *);
 
 /*
- * Diff two objects, assuming both objects are trees.
+ * Diff two objects, assuming both objects are trees. Two const char * diff
+ * header labels may be provided which will be used to identify each blob in
+ * the trees. If a label is NULL, use the blob's SHA1 checksum instead.
  * Write unified diff text to the provided output FILE.
  */
 const struct got_error *got_diff_objects_as_trees(struct got_object *,
-    struct got_object *, struct got_repository *, FILE *);
+    struct got_object *, char *, char *, struct got_repository *, FILE *);
 
 /*
  * Diff two objects, assuming both objects are commits.
blob - 2beea41cdbdaa48a259447b266ae99b811b68764
blob + 58ae938182c6e017b5c50f1ae0d48099de6c9801
--- lib/diff.c
+++ lib/diff.c
@@ -163,8 +163,8 @@ match_entry_by_name(struct got_tree_entry *te1, struct
 }
 
 static const struct got_error *
-diff_added_blob(struct got_object_id *id, struct got_repository *repo,
-    FILE *outfile)
+diff_added_blob(struct got_object_id *id, const char *label,
+    struct got_repository *repo, FILE *outfile)
 {
 	const struct got_error *err;
 	struct got_blob_object  *blob = NULL;
@@ -177,7 +177,7 @@ diff_added_blob(struct got_object_id *id, struct got_r
 	err = got_object_blob_open(&blob, repo, obj, 8192);
 	if (err)
 		goto done;
-	err = got_diff_blob(NULL, blob, NULL, NULL, outfile);
+	err = got_diff_blob(NULL, blob, NULL, label, outfile);
 done:
 	got_object_close(obj);
 	if (blob)
@@ -187,7 +187,8 @@ done:
 
 static const struct got_error *
 diff_modified_blob(struct got_object_id *id1, struct got_object_id *id2,
-    struct got_repository *repo, FILE *outfile)
+    const char *label1, const char *label2, struct got_repository *repo,
+    FILE *outfile)
 {
 	const struct got_error *err;
 	struct got_object *obj1 = NULL;
@@ -219,7 +220,7 @@ diff_modified_blob(struct got_object_id *id1, struct g
 	if (err)
 		goto done;
 
-	err = got_diff_blob(blob1, blob2, NULL, NULL, outfile);
+	err = got_diff_blob(blob1, blob2, label1, label2, outfile);
 
 done:
 	if (obj1)
@@ -234,8 +235,8 @@ done:
 }
 
 static const struct got_error *
-diff_deleted_blob(struct got_object_id *id, struct got_repository *repo,
-    FILE *outfile)
+diff_deleted_blob(struct got_object_id *id, const char *label,
+    struct got_repository *repo, FILE *outfile)
 {
 	const struct got_error *err;
 	struct got_blob_object  *blob = NULL;
@@ -248,7 +249,7 @@ diff_deleted_blob(struct got_object_id *id, struct got
 	err = got_object_blob_open(&blob, repo, obj, 8192);
 	if (err)
 		goto done;
-	err = got_diff_blob(blob, NULL, NULL, NULL, outfile);
+	err = got_diff_blob(blob, NULL, label, NULL, outfile);
 done:
 	got_object_close(obj);
 	if (blob)
@@ -257,8 +258,8 @@ done:
 }
 
 static const struct got_error *
-diff_added_tree(struct got_object_id *id, struct got_repository *repo,
-    FILE *outfile)
+diff_added_tree(struct got_object_id *id, const char *label,
+    struct got_repository *repo, FILE *outfile)
 {
 	const struct got_error *err = NULL;
 	struct got_object *treeobj = NULL;
@@ -277,7 +278,7 @@ diff_added_tree(struct got_object_id *id, struct got_r
 	if (err)
 		goto done;
 
-	err = got_diff_tree(NULL, tree, repo, outfile);
+	err = got_diff_tree(NULL, tree, NULL, label, repo, outfile);
 
 done:
 	if (tree)
@@ -289,9 +290,10 @@ done:
 
 static const struct got_error *
 diff_modified_tree(struct got_object_id *id1, struct got_object_id *id2,
-    struct got_repository *repo, FILE *outfile)
+    const char *label1, const char *label2, struct got_repository *repo,
+    FILE *outfile)
 {
-	const struct got_error *err = NULL;
+	const struct got_error *err;
 	struct got_object *treeobj1 = NULL;
 	struct got_object *treeobj2 = NULL;
 	struct got_tree_object *tree1 = NULL;
@@ -323,7 +325,7 @@ diff_modified_tree(struct got_object_id *id1, struct g
 	if (err)
 		goto done;
 
-	err = got_diff_tree(tree1, tree2, repo, outfile);
+	err = got_diff_tree(tree1, tree2, label1, label2, repo, outfile);
 
 done:
 	if (tree1)
@@ -338,9 +340,10 @@ done:
 }
 
 static const struct got_error *
-diff_deleted_tree(struct got_object_id *id, struct got_repository *repo, FILE *outfile)
+diff_deleted_tree(struct got_object_id *id, const char *label,
+    struct got_repository *repo, FILE *outfile)
 {
-	const struct got_error *err = NULL;
+	const struct got_error *err;
 	struct got_object *treeobj = NULL;
 	struct got_tree_object *tree = NULL;
 
@@ -357,8 +360,7 @@ diff_deleted_tree(struct got_object_id *id, struct got
 	if (err)
 		goto done;
 
-	err = got_diff_tree(tree, NULL, repo, outfile);
-
+	err = got_diff_tree(tree, NULL, label, NULL, repo, outfile);
 done:
 	if (tree)
 		got_object_tree_close(tree);
@@ -369,90 +371,128 @@ done:
 
 static const struct got_error *
 diff_kind_mismatch(struct got_object_id *id1, struct got_object_id *id2,
-    FILE *outfile)
+    const char *label1, const char *label2, FILE *outfile)
 {
 	/* XXX TODO */
 	return NULL;
 }
 
 static const struct got_error *
-diff_entry_old_new(struct got_tree_entry *te1, struct got_tree_object *tree2,
-    struct got_repository *repo, FILE *outfile)
+diff_entry_old_new(struct got_tree_entry *te1, struct got_tree_entry *te2,
+    const char *label1, const char *label2, struct got_repository *repo,
+    FILE *outfile)
 {
-	struct got_tree_entry *te2 = NULL;
+	const struct got_error *err = NULL;
 
-	if (tree2)
-		te2 = match_entry_by_name(te1, tree2);
 	if (te2 == NULL) {
 		if (S_ISDIR(te1->mode))
-			return diff_deleted_tree(te1->id, repo, outfile);
-		return diff_deleted_blob(te1->id, repo, outfile);
+			err = diff_deleted_tree(te1->id, label1, repo, outfile);
+		else
+			err = diff_deleted_blob(te1->id, label1, repo, outfile);
+		return err;
 	}
 
 	if (S_ISDIR(te1->mode) && S_ISDIR(te2->mode)) {
 		if (got_object_id_cmp(te1->id, te2->id) != 0)
-			return diff_modified_tree(te1->id, te2->id, repo,
-			    outfile);
+			return diff_modified_tree(te1->id, te2->id,
+			    label1, label2, repo, outfile);
 	} else if (S_ISREG(te1->mode) && S_ISREG(te2->mode)) {
 		if (got_object_id_cmp(te1->id, te2->id) != 0)
-			return diff_modified_blob(te1->id, te2->id, repo,
-			    outfile);
+			return diff_modified_blob(te1->id, te2->id,
+			    label1, label2, repo, outfile);
 	}
 
-	return diff_kind_mismatch(te1->id, te2->id, outfile);
+	if (got_object_id_cmp(te1->id, te2->id) == 0)
+		return NULL;
+
+	return diff_kind_mismatch(te1->id, te2->id, label1, label2, outfile);
 }
 
 static const struct got_error *
-diff_entry_new_old(struct got_tree_entry *te2, struct got_tree_object *tree1,
-    struct got_repository *repo, FILE *outfile)
+diff_entry_new_old(struct got_tree_entry *te2, struct got_tree_entry *te1,
+    const char *label2, struct got_repository *repo, FILE *outfile)
 {
-	if (tree1) {
-		struct got_tree_entry *te1 = match_entry_by_name(te2, tree1);
-		if (te1 != NULL) /* handled by diff_entry_old_new() */
-			return NULL;
-	}
+	if (te1 != NULL) /* handled by diff_entry_old_new() */
+		return NULL;
 
 	if (S_ISDIR(te2->mode))
-		return diff_added_tree(te2->id, repo, outfile);
-	return diff_added_blob(te2->id, repo, outfile);
+		return diff_added_tree(te2->id, label2, repo, outfile);
+
+	return diff_added_blob(te2->id, label2, repo, outfile);
 }
 
 const struct got_error *
 got_diff_tree(struct got_tree_object *tree1, struct got_tree_object *tree2,
-    struct got_repository *repo, FILE *outfile)
+    const char *label1, const char *label2, struct got_repository *repo,
+    FILE *outfile)
 {
 	const struct got_error *err = NULL;
 	struct got_tree_entry *te1 = NULL;
 	struct got_tree_entry *te2 = NULL;
+	char *l1 = NULL, *l2 = NULL;
 
 	if (tree1) {
 		const struct got_tree_entries *entries;
 		entries = got_object_tree_get_entries(tree1);
 		te1 = SIMPLEQ_FIRST(&entries->head);
+		if (asprintf(&l1, "%s%s%s", label1, label1[0] ? "/" : "",
+		    te1->name) == -1)
+			return got_error_from_errno();
 	}
 	if (tree2) {
 		const struct got_tree_entries *entries;
 		entries = got_object_tree_get_entries(tree2);
 		te2 = SIMPLEQ_FIRST(&entries->head);
+		if (asprintf(&l2, "%s%s%s", label2, label2[0] ? "/" : "",
+		    te2->name) == -1)
+			return got_error_from_errno();
 	}
 
 	do {
 		if (te1) {
-			err = diff_entry_old_new(te1, tree2, repo, outfile);
+			struct got_tree_entry *te = NULL;
+			if (tree2)
+				te = match_entry_by_name(te1, tree2);
+			if (te) {
+				free(l2);
+				l2 = NULL;
+				if (te && asprintf(&l2, "%s%s%s", label2,
+				    label2[0] ? "/" : "", te->name) == -1)
+					return got_error_from_errno();
+			}
+			err = diff_entry_old_new(te1, te, l1, l2, repo,
+			    outfile);
 			if (err)
 				break;
 		}
 
 		if (te2) {
-			err = diff_entry_new_old(te2, tree1, repo, outfile);
+			struct got_tree_entry *te = NULL;
+			if (tree1)
+				te = match_entry_by_name(te2, tree1);
+			err = diff_entry_new_old(te2, te, l2, repo, outfile);
 			if (err)
 				break;
 		}
 
-		if (te1)
+		free(l1);
+		l1 = NULL;
+		if (te1) {
 			te1 = SIMPLEQ_NEXT(te1, entry);
-		if (te2)
+			if (te1 &&
+			    asprintf(&l1, "%s%s%s", label1,
+			    label1[0] ? "/" : "", te1->name) == -1)
+				return got_error_from_errno();
+		}
+		free(l2);
+		l2 = NULL;
+		if (te2) {
 			te2 = SIMPLEQ_NEXT(te2, entry);
+			if (te2 &&
+			    asprintf(&l2, "%s%s%s", label2,
+			        label2[0] ? "/" : "", te2->name) == -1)
+				return got_error_from_errno();
+		}
 	} while (te1 || te2);
 
 	return err;
@@ -460,7 +500,8 @@ got_diff_tree(struct got_tree_object *tree1, struct go
 
 const struct got_error *
 got_diff_objects_as_blobs(struct got_object *obj1, struct got_object *obj2,
-    struct got_repository *repo, FILE *outfile)
+    const char *label1, const char *label2, struct got_repository *repo,
+    FILE *outfile)
 {
 	const struct got_error *err;
 	struct got_blob_object *blob1 = NULL, *blob2 = NULL;
@@ -478,7 +519,7 @@ got_diff_objects_as_blobs(struct got_object *obj1, str
 		if (err)
 			goto done;
 	}
-	err = got_diff_blob(blob1, blob2, NULL, NULL, outfile);
+	err = got_diff_blob(blob1, blob2, label1, label2, outfile);
 done:
 	if (blob1)
 		got_object_blob_close(blob1);
@@ -489,7 +530,7 @@ done:
 
 const struct got_error *
 got_diff_objects_as_trees(struct got_object *obj1, struct got_object *obj2,
-    struct got_repository *repo, FILE *outfile)
+    char *label1, char *label2, struct got_repository *repo, FILE *outfile)
 {
 	const struct got_error *err;
 	struct got_tree_object *tree1 = NULL, *tree2 = NULL;
@@ -507,7 +548,7 @@ got_diff_objects_as_trees(struct got_object *obj1, str
 		if (err)
 			goto done;
 	}
-	err = got_diff_tree(tree1, tree2, repo, outfile);
+	err = got_diff_tree(tree1, tree2, label1, label2, repo, outfile);
 done:
 	if (tree1)
 		got_object_tree_close(tree1);
@@ -582,7 +623,8 @@ got_diff_objects_as_commits(struct got_object *obj1, s
 		goto done;
 	}
 
-	err = got_diff_objects_as_trees(tree_obj1, tree_obj2, repo, outfile);
+	err = got_diff_objects_as_trees(tree_obj1, tree_obj2, "", "", repo,
+	    outfile);
 done:
 	if (tree_obj1)
 		got_object_close(tree_obj1);
blob - d5fe6d3ef1904416bca7e896855adc989a99b553
blob + ed18000f24cef20a98c96ca53a1bfe44692860ed
--- regress/repository/repository_test.c
+++ regress/repository/repository_test.c
@@ -427,7 +427,7 @@ repo_diff_tree(const char *repo_path)
 	} else
 		outfile = stdout;
 	test_printf("\n");
-	got_diff_tree(tree1, tree2, repo, outfile);
+	got_diff_tree(tree1, tree2, "", "", repo, outfile);
 	test_printf("\n");
 
 	got_object_tree_close(tree1);
blob - b06d551f87a1ef879bfdf855b30647b1fe26e1ba
blob + d7c5c6828911b898e727a0cf6de3c87c8dd9c406
--- tog/tog.c
+++ tog/tog.c
@@ -1590,10 +1590,11 @@ open_diff_view(struct tog_view *view, struct got_objec
 
 	switch (got_object_get_type(obj1 ? obj1 : obj2)) {
 	case GOT_OBJ_TYPE_BLOB:
-		err = got_diff_objects_as_blobs(obj1, obj2, repo, f);
+		err = got_diff_objects_as_blobs(obj1, obj2, NULL, NULL,
+		    repo, f);
 		break;
 	case GOT_OBJ_TYPE_TREE:
-		err = got_diff_objects_as_trees(obj1, obj2, repo, f);
+		err = got_diff_objects_as_trees(obj1, obj2, "", "", repo, f);
 		break;
 	case GOT_OBJ_TYPE_COMMIT:
 		err = got_diff_objects_as_commits(obj1, obj2, repo, f);