4 #include "got_lib_object.h"
6 static const struct got_error *
7 -diff_blobs(struct got_diffreg_result **resultp,
8 -struct got_blob_object *blob1, struct got_blob_object *blob2,
9 +add_line_offset(off_t **line_offsets, size_t *nlines, off_t off)
13 + p = reallocarray(*line_offsets, *nlines + 1, sizeof(off_t));
15 + return got_error_from_errno("reallocarray");
17 + (*line_offsets)[*nlines] = off;
22 +static const struct got_error *
23 +diff_blobs(off_t **line_offsets, size_t *nlines,
24 + struct got_diffreg_result **resultp, struct got_blob_object *blob1,
25 + struct got_blob_object *blob2,
26 const char *label1, const char *label2, mode_t mode1, mode_t mode2,
27 int diff_context, int ignore_whitespace, FILE *outfile)
30 char *idstr1 = NULL, *idstr2 = NULL;
32 struct got_diffreg_result *result;
36 + if (line_offsets && *line_offsets && *nlines > 0)
37 + outoff = (*line_offsets)[*nlines - 1];
46 - fprintf(outfile, "blob - %s%s\n", idstr1,
47 + n = fprintf(outfile, "blob - %s%s\n", idstr1,
48 modestr1 ? modestr1 : "");
49 - fprintf(outfile, "blob + %s%s\n", idstr2,
51 + err = got_error_from_errno("fprintf");
56 + err = add_line_offset(line_offsets, nlines, outoff);
61 + n = fprintf(outfile, "blob + %s%s\n", idstr2,
62 modestr2 ? modestr2 : "");
64 + err = got_error_from_errno("fprintf");
69 + err = add_line_offset(line_offsets, nlines, outoff);
81 - err = got_diffreg_output(NULL, NULL, result, f1, f2,
82 + err = got_diffreg_output(line_offsets, nlines, result, f1, f2,
83 label1 ? label1 : idstr1,
84 label2 ? label2 : idstr2,
85 GOT_DIFF_OUTPUT_UNIDIFF, diff_context, outfile);
87 struct got_object_id *id2, const char *label1, const char *label2,
88 mode_t mode1, mode_t mode2, struct got_repository *repo)
90 - const struct got_error *err;
91 struct got_diff_blob_output_unidiff_arg *a = arg;
93 - err = diff_blobs(NULL, blob1, blob2, label1, label2, mode1, mode2,
94 - a->diff_context, a->ignore_whitespace, a->outfile);
96 + return diff_blobs(&a->line_offsets, &a->nlines, NULL,
97 + blob1, blob2, label1, label2, mode1, mode2, a->diff_context,
98 + a->ignore_whitespace, a->outfile);
101 const struct got_error *
102 -got_diff_blob(struct got_blob_object *blob1, struct got_blob_object *blob2,
103 +got_diff_blob(off_t **line_offsets, size_t *nlines,
104 + struct got_blob_object *blob1, struct got_blob_object *blob2,
105 const char *label1, const char *label2, int diff_context,
106 int ignore_whitespace, FILE *outfile)
108 - return diff_blobs(NULL, blob1, blob2, label1, label2, 0, 0, diff_context,
109 - ignore_whitespace, outfile);
110 + return diff_blobs(line_offsets, nlines, NULL, blob1, blob2,
111 + label1, label2, 0, 0, diff_context, ignore_whitespace, outfile);
114 static const struct got_error *
117 const struct got_error *err = NULL;
119 - err = diff_blobs(result, blob1, blob2, NULL, NULL, 0, 0, 3, 0, NULL);
120 + err = diff_blobs(NULL, NULL, result, blob1, blob2,
121 + NULL, NULL, 0, 0, 3, 0, NULL);
123 got_diffreg_result_free(*result);
128 const struct got_error *
129 -got_diff_objects_as_blobs(struct got_object_id *id1, struct got_object_id *id2,
130 +got_diff_objects_as_blobs(off_t **line_offsets, size_t *nlines,
131 + struct got_object_id *id1, struct got_object_id *id2,
132 const char *label1, const char *label2, int diff_context,
133 int ignore_whitespace, struct got_repository *repo, FILE *outfile)
139 - err = got_diff_blob(blob1, blob2, label1, label2, diff_context,
140 - ignore_whitespace, outfile);
141 + err = got_diff_blob(line_offsets, nlines, blob1, blob2,
142 + label1, label2, diff_context, ignore_whitespace, outfile);
145 got_object_blob_close(blob1);
146 @@ -733,13 +777,15 @@
149 const struct got_error *
150 -got_diff_objects_as_trees(struct got_object_id *id1, struct got_object_id *id2,
151 +got_diff_objects_as_trees(off_t **line_offsets, size_t *nlines,
152 + struct got_object_id *id1, struct got_object_id *id2,
153 char *label1, char *label2, int diff_context, int ignore_whitespace,
154 struct got_repository *repo, FILE *outfile)
156 const struct got_error *err;
157 struct got_tree_object *tree1 = NULL, *tree2 = NULL;
158 struct got_diff_blob_output_unidiff_arg arg;
159 + int want_lineoffsets = (line_offsets != NULL && *line_offsets != NULL);
161 if (id1 == NULL && id2 == NULL)
162 return got_error(GOT_ERR_NO_OBJ);
164 arg.diff_context = diff_context;
165 arg.ignore_whitespace = ignore_whitespace;
166 arg.outfile = outfile;
167 + if (want_lineoffsets) {
168 + arg.line_offsets = *line_offsets;
169 + arg.nlines = *nlines;
171 + arg.line_offsets = NULL;
174 err = got_diff_tree(tree1, tree2, label1, label2, repo,
175 got_diff_blob_output_unidiff, &arg, 1);
177 + if (want_lineoffsets) {
178 + *line_offsets = arg.line_offsets; /* was likely re-allocated */
179 + *nlines = arg.nlines;
183 got_object_tree_close(tree1);
187 const struct got_error *
188 -got_diff_objects_as_commits(struct got_object_id *id1,
189 - struct got_object_id *id2, int diff_context, int ignore_whitespace,
190 +got_diff_objects_as_commits(off_t **line_offsets, size_t *nlines,
191 + struct got_object_id *id1, struct got_object_id *id2,
192 + int diff_context, int ignore_whitespace,
193 struct got_repository *repo, FILE *outfile)
195 const struct got_error *err;
200 - err = got_diff_objects_as_trees(
201 + err = got_diff_objects_as_trees(line_offsets, nlines,
202 commit1 ? got_object_commit_get_tree_id(commit1) : NULL,
203 got_object_commit_get_tree_id(commit2), "", "", diff_context,
204 ignore_whitespace, repo, outfile);