commit - 1de5e06571b18a9888f0e659ef6f91b82d5c0c42
commit + aaa1358905e35eaa19a177bd11797d1a38d6cc03
blob - d428a7862a0c726d3db541dbe0a1559ac1fbc04a
blob + 0cb4b58a9016b7bc0462275d8ddff416e5848b05
--- got/got.c
+++ got/got.c
struct got_tree_object *tree1 = NULL, *tree2;
struct got_object_qid *qid;
char *id_str1 = NULL, *id_str2;
+ struct got_diff_blob_output_unidiff_arg arg;
err = got_object_open_as_tree(&tree2, repo,
got_object_commit_get_tree_id(commit));
goto done;
printf("diff %s %s\n", id_str1 ? id_str1 : "/dev/null", id_str2);
- err = got_diff_tree(tree1, tree2, "", "", diff_context, repo, stdout);
+ arg.diff_context = diff_context;
+ arg.outfile = stdout;
+ err = got_diff_tree(tree1, tree2, "", "", repo,
+ got_diff_blob_output_unidiff, &arg);
done:
if (tree1)
got_object_tree_close(tree1);
blob - 79cfc0f733a6c5652963c916118617590ffa1389
blob + 8ab2399438d290b97f821e2df3f6782205433eda
--- include/got_diff.h
+++ include/got_diff.h
size_t, const char *, int, FILE *);
/*
- * Compute the differences between two trees and write unified diff text
- * 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.
- * The number of context lines to show in the diff must be specified as well.
+ * A callback function invoked to handle the differences between two blobs
+ * when diffing trees with got_diff_tree(). This callback receives two blobs,
+ * their respective IDs, and two corresponding paths within the diffed trees.
+ * The first blob contains content from the old side of the diff, and
+ * the second blob contains content on the new side of the diff.
+ * The set of arguments relating to either blob may be NULL to indicate
+ * that no content is present on its respective side of the diff.
*/
+typedef const struct got_error *(*got_diff_blob_cb)(void *,
+ struct got_blob_object *, struct got_blob_object *,
+ struct got_object_id *, struct got_object_id *,
+ const char *, const char *, struct got_repository *);
+
+/*
+ * A pre-defined implementation of got_diff_blob_cb() which appends unidiff
+ * output to a file. The caller must allocate and fill in the argument
+ * structure.
+ */
+struct got_diff_blob_output_unidiff_arg {
+ FILE *outfile; /* Unidiff text will be written here. */
+ int diff_context; /* Sets the number of context lines. */
+};
+const struct got_error *got_diff_blob_output_unidiff(void *,
+ struct got_blob_object *, struct got_blob_object *,
+ struct got_object_id *, struct got_object_id *,
+ const char *, const char *, struct got_repository *);
+
+/*
+ * Compute the differences between two trees and invoke the provided
+ * got_diff_blob_cb() callback when content differs.
+ */
const struct got_error *got_diff_tree(struct got_tree_object *,
- struct got_tree_object *, const char *label1, const char *label2,
- int, struct got_repository *, FILE *);
+ struct got_tree_object *, const char *, const char *,
+ struct got_repository *, got_diff_blob_cb cb, void *cb_arg);
/*
* Diff two objects, assuming both objects are blobs. Two const char * diff
blob - 1c51bb9a08762148d3c8c698a7b64c5e7101546c
blob + 4da542a630e60a18a9b1066bc987ff7453340987
--- lib/diff.c
+++ lib/diff.c
if (f2 && fclose(f2) != 0 && err == NULL)
err = got_error_from_errno("fclose");
return err;
+}
+
+const struct got_error *
+got_diff_blob_output_unidiff(void *arg, struct got_blob_object *blob1,
+ struct got_blob_object *blob2, struct got_object_id *id1,
+ struct got_object_id *id2, const char *label1, const char *label2,
+ struct got_repository *repo)
+{
+ struct got_diff_blob_output_unidiff_arg *a = arg;
+
+ return diff_blobs(blob1, blob2, label1, label2, a->diff_context,
+ a->outfile, NULL);
}
const struct got_error *
static const struct got_error *
diff_added_blob(struct got_object_id *id, const char *label,
- int diff_context, struct got_repository *repo, FILE *outfile)
+ struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg)
{
const struct got_error *err;
struct got_blob_object *blob = NULL;
err = got_object_blob_open(&blob, repo, obj, 8192);
if (err)
goto done;
- err = got_diff_blob(NULL, blob, NULL, label, diff_context, outfile);
+ err = cb(cb_arg, NULL, blob, NULL, id, NULL, label, repo);
done:
got_object_close(obj);
if (blob)
static const struct got_error *
diff_modified_blob(struct got_object_id *id1, struct got_object_id *id2,
- const char *label1, const char *label2, int diff_context,
- struct got_repository *repo, FILE *outfile)
+ const char *label1, const char *label2, struct got_repository *repo,
+ got_diff_blob_cb cb, void *cb_arg)
{
const struct got_error *err;
struct got_object *obj1 = NULL;
if (err)
goto done;
- err = got_diff_blob(blob1, blob2, label1, label2, diff_context,
- outfile);
-
+ err = cb(cb_arg, blob1, blob2, id1, id2, label1, label2, repo);
done:
if (obj1)
got_object_close(obj1);
static const struct got_error *
diff_deleted_blob(struct got_object_id *id, const char *label,
- int diff_context, struct got_repository *repo, FILE *outfile)
+ struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg)
{
const struct got_error *err;
struct got_blob_object *blob = NULL;
err = got_object_blob_open(&blob, repo, obj, 8192);
if (err)
goto done;
- err = got_diff_blob(blob, NULL, label, NULL, diff_context, outfile);
+ err = cb(cb_arg, blob, NULL, id, NULL, label, NULL, repo);
done:
got_object_close(obj);
if (blob)
static const struct got_error *
diff_added_tree(struct got_object_id *id, const char *label,
- int diff_context, struct got_repository *repo, FILE *outfile)
+ struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg)
{
const struct got_error *err = NULL;
struct got_object *treeobj = NULL;
if (err)
goto done;
- err = got_diff_tree(NULL, tree, NULL, label, diff_context, repo,
- outfile);
-
+ err = got_diff_tree(NULL, tree, NULL, label, repo, cb, cb_arg);
done:
if (tree)
got_object_tree_close(tree);
static const struct got_error *
diff_modified_tree(struct got_object_id *id1, struct got_object_id *id2,
- const char *label1, const char *label2, int diff_context,
- struct got_repository *repo, FILE *outfile)
+ const char *label1, const char *label2, struct got_repository *repo,
+ got_diff_blob_cb cb, void *cb_arg)
{
const struct got_error *err;
struct got_object *treeobj1 = NULL;
if (err)
goto done;
- err = got_diff_tree(tree1, tree2, label1, label2, diff_context, repo,
- outfile);
+ err = got_diff_tree(tree1, tree2, label1, label2, repo, cb, cb_arg);
done:
if (tree1)
static const struct got_error *
diff_deleted_tree(struct got_object_id *id, const char *label,
- int diff_context, struct got_repository *repo, FILE *outfile)
+ struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg)
{
const struct got_error *err;
struct got_object *treeobj = NULL;
if (err)
goto done;
- err = got_diff_tree(tree, NULL, label, NULL, diff_context, repo,
- outfile);
+ err = got_diff_tree(tree, NULL, label, NULL, repo, cb, cb_arg);
done:
if (tree)
got_object_tree_close(tree);
static const struct got_error *
diff_kind_mismatch(struct got_object_id *id1, struct got_object_id *id2,
- const char *label1, const char *label2, FILE *outfile)
+ const char *label1, const char *label2, struct got_repository *repo,
+ got_diff_blob_cb cb, void *cb_arg)
{
/* XXX TODO */
return NULL;
static const struct got_error *
diff_entry_old_new(const struct got_tree_entry *te1,
const struct got_tree_entry *te2, const char *label1, const char *label2,
- int diff_context, struct got_repository *repo, FILE *outfile)
+ struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg)
{
const struct got_error *err = NULL;
int id_match;
if (te2 == NULL) {
if (S_ISDIR(te1->mode))
- err = diff_deleted_tree(te1->id, label1, diff_context,
- repo, outfile);
+ err = diff_deleted_tree(te1->id, label1, repo,
+ cb, cb_arg);
else
- err = diff_deleted_blob(te1->id, label1, diff_context,
- repo, outfile);
+ err = diff_deleted_blob(te1->id, label1, repo,
+ cb, cb_arg);
return err;
}
if (S_ISDIR(te1->mode) && S_ISDIR(te2->mode)) {
if (!id_match)
return diff_modified_tree(te1->id, te2->id,
- label1, label2, diff_context, repo, outfile);
+ label1, label2, repo, cb, cb_arg);
} else if (S_ISREG(te1->mode) && S_ISREG(te2->mode)) {
if (!id_match)
return diff_modified_blob(te1->id, te2->id,
- label1, label2, diff_context, repo, outfile);
+ label1, label2, repo, cb, cb_arg);
}
if (id_match)
return NULL;
- return diff_kind_mismatch(te1->id, te2->id, label1, label2, outfile);
+ return diff_kind_mismatch(te1->id, te2->id, label1, label2, repo,
+ cb, cb_arg);
}
static const struct got_error *
diff_entry_new_old(const struct got_tree_entry *te2,
- const struct got_tree_entry *te1, const char *label2, int diff_context,
- struct got_repository *repo, FILE *outfile)
+ const struct got_tree_entry *te1, const char *label2,
+ struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg)
{
if (te1 != NULL) /* handled by diff_entry_old_new() */
return NULL;
if (S_ISDIR(te2->mode))
- return diff_added_tree(te2->id, label2, diff_context, repo,
- outfile);
+ return diff_added_tree(te2->id, label2, repo, cb, cb_arg);
- return diff_added_blob(te2->id, label2, diff_context, repo, outfile);
+ return diff_added_blob(te2->id, label2, repo, cb, cb_arg);
}
const struct got_error *
got_diff_tree(struct got_tree_object *tree1, struct got_tree_object *tree2,
- const char *label1, const char *label2, int diff_context,
- struct got_repository *repo, FILE *outfile)
+ const char *label1, const char *label2, struct got_repository *repo,
+ got_diff_blob_cb cb, void *cb_arg)
{
const struct got_error *err = NULL;
struct got_tree_entry *te1 = NULL;
return
got_error_from_errno("asprintf");
}
- err = diff_entry_old_new(te1, te, l1, l2, diff_context,
- repo, outfile);
+ err = diff_entry_old_new(te1, te, l1, l2, repo, cb,
+ cb_arg);
if (err)
break;
}
return
got_error_from_errno("asprintf");
}
- err = diff_entry_new_old(te2, te, l2, diff_context,
- repo, outfile);
+ err = diff_entry_new_old(te2, te, l2, repo, cb, cb_arg);
if (err)
break;
}
{
const struct got_error *err;
struct got_tree_object *tree1 = NULL, *tree2 = NULL;
+ struct got_diff_blob_output_unidiff_arg arg;
if (id1 == NULL && id2 == NULL)
return got_error(GOT_ERR_NO_OBJ);
if (err)
goto done;
}
- err = got_diff_tree(tree1, tree2, label1, label2, diff_context,
- repo, outfile);
+ arg.diff_context = diff_context;
+ arg.outfile = outfile;
+ err = got_diff_tree(tree1, tree2, label1, label2, repo,
+ got_diff_blob_output_unidiff, &arg);
done:
if (tree1)
got_object_tree_close(tree1);
blob - a55620128ddb9624806e98d9ca7ae693ec0db127
blob + 52d956f605b4ba9a40603a03256518c933e66992
--- regress/repository/repository_test.c
+++ regress/repository/repository_test.c
struct got_tree_object *tree1;
struct got_tree_object *tree2;
FILE *outfile;
+ struct got_diff_blob_output_unidiff_arg arg;
err = got_repo_open(&repo, repo_path);
if (err != NULL || repo == NULL)
} else
outfile = stdout;
test_printf("\n");
- got_diff_tree(tree1, tree2, "", "", 3, repo, outfile);
+ arg.diff_context = 3;
+ arg.outfile = outfile;
+ got_diff_tree(tree1, tree2, "", "", repo,
+ got_diff_blob_output_unidiff, &arg);
test_printf("\n");
got_object_tree_close(tree1);