summaryrefslogtreecommitdiffabout
path: root/ui-diff.c
authorLars Hjemli <hjemli@gmail.com>2006-12-20 21:48:27 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2006-12-20 21:48:27 (UTC)
commit36aba00273e7af1b94bf8c5dd5068709d983d01e (patch) (unidiff)
treed9be4e6f27b115a799af40cad43445f63fbf2238 /ui-diff.c
parenta53042865a4ac8b1fa1d6b37720787601e181495 (diff)
downloadcgit-36aba00273e7af1b94bf8c5dd5068709d983d01e.zip
cgit-36aba00273e7af1b94bf8c5dd5068709d983d01e.tar.gz
cgit-36aba00273e7af1b94bf8c5dd5068709d983d01e.tar.bz2
Add basic diff view
Finally, xdiff is used to show per-file diffs via commit view. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'ui-diff.c') (more/less context) (ignore whitespace changes)
-rw-r--r--ui-diff.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/ui-diff.c b/ui-diff.c
new file mode 100644
index 0000000..0bd9ade
--- a/dev/null
+++ b/ui-diff.c
@@ -0,0 +1,131 @@
1/* ui-diff.c: show diff between two blobs
2 *
3 * Copyright (C) 2006 Lars Hjemli
4 *
5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text)
7 */
8
9#include "cgit.h"
10#include "xdiff.h"
11
12char *diff_buffer;
13int diff_buffer_size;
14
15
16/*
17 * print a single line returned from xdiff
18 */
19static void print_line(char *line, int len)
20{
21 char *class = "ctx";
22 char c = line[len-1];
23
24 if (line[0] == '+')
25 class = "add";
26 else if (line[0] == '-')
27 class = "del";
28 else if (line[0] == '@')
29 class = "hunk";
30
31 htmlf("<div class='%s'>", class);
32 line[len-1] = '\0';
33 html_txt(line);
34 html("</div>");
35 line[len-1] = c;
36}
37
38/*
39 * Receive diff-buffers from xdiff and concatenate them as
40 * needed across multiple callbacks.
41 *
42 * This is basically a copy of xdiff-interface.c/xdiff_outf(),
43 * ripped from git and modified to use globals instead of
44 * a special callback-struct.
45 */
46int diff_cb(void *priv_, mmbuffer_t *mb, int nbuf)
47{
48 int i;
49
50 for (i = 0; i < nbuf; i++) {
51 if (mb[i].ptr[mb[i].size-1] != '\n') {
52 /* Incomplete line */
53 diff_buffer = xrealloc(diff_buffer,
54 diff_buffer_size + mb[i].size);
55 memcpy(diff_buffer + diff_buffer_size,
56 mb[i].ptr, mb[i].size);
57 diff_buffer_size += mb[i].size;
58 continue;
59 }
60
61 /* we have a complete line */
62 if (!diff_buffer) {
63 print_line(mb[i].ptr, mb[i].size);
64 continue;
65 }
66 diff_buffer = xrealloc(diff_buffer,
67 diff_buffer_size + mb[i].size);
68 memcpy(diff_buffer + diff_buffer_size, mb[i].ptr, mb[i].size);
69 print_line(diff_buffer, diff_buffer_size + mb[i].size);
70 free(diff_buffer);
71 diff_buffer = NULL;
72 diff_buffer_size = 0;
73 }
74 if (diff_buffer) {
75 print_line(diff_buffer, diff_buffer_size);
76 free(diff_buffer);
77 diff_buffer = NULL;
78 diff_buffer_size = 0;
79 }
80 return 0;
81}
82
83static int load_mmfile(mmfile_t *file, const unsigned char *sha1)
84{
85 char type[20];
86
87 if (is_null_sha1(sha1)) {
88 file->ptr = (char *)"";
89 file->size = 0;
90 } else {
91 file->ptr = read_sha1_file(sha1, type, &file->size);
92 }
93 return 1;
94}
95
96static void run_diff(const unsigned char *sha1, const unsigned char *sha2)
97{
98 mmfile_t file1, file2;
99 xpparam_t diff_params;
100 xdemitconf_t emit_params;
101 xdemitcb_t emit_cb;
102
103 if (!load_mmfile(&file1, sha1) || !load_mmfile(&file2, sha2)) {
104 cgit_print_error("Unable to load files for diff");
105 return;
106 }
107
108 diff_params.flags = XDF_NEED_MINIMAL;
109
110 emit_params.ctxlen = 3;
111 emit_params.flags = XDL_EMIT_FUNCNAMES;
112
113 emit_cb.outf = diff_cb;
114
115 xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb);
116}
117
118
119
120void cgit_print_diff(const char *old_hex, const char *new_hex)
121{
122 unsigned char sha1[20], sha2[20];
123
124 get_sha1(old_hex, sha1);
125 get_sha1(new_hex, sha2);
126
127 html("<h2>diff</h2>\n");
128 html("<table class='diff'><tr><td>");
129 run_diff(sha1, sha2);
130 html("</td></tr></table>");
131}