diff options
Diffstat (limited to 'shared.c')
| -rw-r--r-- | shared.c | 79 |
1 files changed, 79 insertions, 0 deletions
| @@ -207,6 +207,85 @@ void cgit_diff_tree_cb(struct diff_queue_struct *q, | |||
| 207 | } | 207 | } |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | static int load_mmfile(mmfile_t *file, const unsigned char *sha1) | ||
| 211 | { | ||
| 212 | enum object_type type; | ||
| 213 | |||
| 214 | if (is_null_sha1(sha1)) { | ||
| 215 | file->ptr = (char *)""; | ||
| 216 | file->size = 0; | ||
| 217 | } else { | ||
| 218 | file->ptr = read_sha1_file(sha1, &type, &file->size); | ||
| 219 | } | ||
| 220 | return 1; | ||
| 221 | } | ||
| 222 | |||
| 223 | /* | ||
| 224 | * Receive diff-buffers from xdiff and concatenate them as | ||
| 225 | * needed across multiple callbacks. | ||
| 226 | * | ||
| 227 | * This is basically a copy of xdiff-interface.c/xdiff_outf(), | ||
| 228 | * ripped from git and modified to use globals instead of | ||
| 229 | * a special callback-struct. | ||
| 230 | */ | ||
| 231 | char *diffbuf = NULL; | ||
| 232 | int buflen = 0; | ||
| 233 | |||
| 234 | int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) | ||
| 235 | { | ||
| 236 | int i; | ||
| 237 | |||
| 238 | for (i = 0; i < nbuf; i++) { | ||
| 239 | if (mb[i].ptr[mb[i].size-1] != '\n') { | ||
| 240 | /* Incomplete line */ | ||
| 241 | diffbuf = xrealloc(diffbuf, buflen + mb[i].size); | ||
| 242 | memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); | ||
| 243 | buflen += mb[i].size; | ||
| 244 | continue; | ||
| 245 | } | ||
| 246 | |||
| 247 | /* we have a complete line */ | ||
| 248 | if (!diffbuf) { | ||
| 249 | ((linediff_fn)priv)(mb[i].ptr, mb[i].size); | ||
| 250 | continue; | ||
| 251 | } | ||
| 252 | diffbuf = xrealloc(diffbuf, buflen + mb[i].size); | ||
| 253 | memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); | ||
| 254 | ((linediff_fn)priv)(diffbuf, buflen + mb[i].size); | ||
| 255 | free(diffbuf); | ||
| 256 | diffbuf = NULL; | ||
| 257 | buflen = 0; | ||
| 258 | } | ||
| 259 | if (diffbuf) { | ||
| 260 | ((linediff_fn)priv)(diffbuf, buflen); | ||
| 261 | free(diffbuf); | ||
| 262 | diffbuf = NULL; | ||
| 263 | buflen = 0; | ||
| 264 | } | ||
| 265 | return 0; | ||
| 266 | } | ||
| 267 | |||
| 268 | int cgit_diff_files(const unsigned char *old_sha1, | ||
| 269 | const unsigned char *new_sha1, | ||
| 270 | linediff_fn fn) | ||
| 271 | { | ||
| 272 | mmfile_t file1, file2; | ||
| 273 | xpparam_t diff_params; | ||
| 274 | xdemitconf_t emit_params; | ||
| 275 | xdemitcb_t emit_cb; | ||
| 276 | |||
| 277 | if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1)) | ||
| 278 | return 1; | ||
| 279 | |||
| 280 | diff_params.flags = XDF_NEED_MINIMAL; | ||
| 281 | emit_params.ctxlen = 3; | ||
| 282 | emit_params.flags = XDL_EMIT_FUNCNAMES; | ||
| 283 | emit_cb.outf = filediff_cb; | ||
| 284 | emit_cb.priv = fn; | ||
| 285 | xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); | ||
| 286 | return 0; | ||
| 287 | } | ||
| 288 | |||
| 210 | void cgit_diff_tree(const unsigned char *old_sha1, | 289 | void cgit_diff_tree(const unsigned char *old_sha1, |
| 211 | const unsigned char *new_sha1, | 290 | const unsigned char *new_sha1, |
| 212 | filepair_fn fn) | 291 | filepair_fn fn) |
