summaryrefslogtreecommitdiffabout
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
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 (more/less context) (ignore whitespace changes)
-rw-r--r--Makefile2
-rw-r--r--cgit.c2
-rw-r--r--cgit.css25
-rw-r--r--cgit.h2
-rw-r--r--shared.c4
-rw-r--r--ui-diff.c131
-rw-r--r--xdiff.h105
7 files changed, 270 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 58a583b..4aa7afe 100644
--- a/Makefile
+++ b/Makefile
@@ -7,5 +7,5 @@ CACHE_ROOT = /var/cache/cgit
7EXTLIBS = ../git/libgit.a ../git/xdiff/lib.a -lz -lcrypto 7EXTLIBS = ../git/libgit.a ../git/xdiff/lib.a -lz -lcrypto
8OBJECTS = shared.o cache.o parsing.o html.o ui-shared.o ui-repolist.o \ 8OBJECTS = shared.o cache.o parsing.o html.o ui-shared.o ui-repolist.o \
9 ui-summary.o ui-log.o ui-view.c ui-tree.c ui-commit.c 9 ui-summary.o ui-log.o ui-view.c ui-tree.c ui-commit.c ui-diff.o
10 10
11CFLAGS += -Wall 11CFLAGS += -Wall
diff --git a/cgit.c b/cgit.c
index 372b436..ac43441 100644
--- a/cgit.c
+++ b/cgit.c
@@ -37,4 +37,6 @@ static void cgit_print_repo_page(struct cacheitem *item)
37 } else if (!strcmp(cgit_query_page, "view")) { 37 } else if (!strcmp(cgit_query_page, "view")) {
38 cgit_print_view(cgit_query_sha1); 38 cgit_print_view(cgit_query_sha1);
39 } else if (!strcmp(cgit_query_page, "diff")) {
40 cgit_print_diff(cgit_query_sha1, cgit_query_sha2);
39 } 41 }
40 cgit_print_docend(); 42 cgit_print_docend();
diff --git a/cgit.css b/cgit.css
index 5f01926..7b8e468 100644
--- a/cgit.css
+++ b/cgit.css
@@ -78,4 +78,7 @@ div.error {
78 margin: 1em 2em; 78 margin: 1em 2em;
79} 79}
80div.ls-blob, div.ls-dir {
81 font-family: monospace;
82}
80div.ls-dir a { 83div.ls-dir a {
81 font-weight: bold; 84 font-weight: bold;
@@ -84,4 +87,7 @@ th.filesize, td.filesize {
84 text-align: right; 87 text-align: right;
85} 88}
89td.filesize {
90 font-family: monospace;
91}
86td.filemode { 92td.filemode {
87 font-family: monospace; 93 font-family: monospace;
@@ -155,4 +161,23 @@ table.diffstat td.summary {
155 padding-top: 0.5em; 161 padding-top: 0.5em;
156} 162}
163
164table.diff td {
165 border: solid 1px black;
166 font-family: monospace;
167 white-space: pre;
168}
169
170table.diff td div.hunk {
171 background: #ccc;
172}
173
174table.diff td div.add {
175 color: green;
176}
177
178table.diff td div.del {
179 color: red;
180}
181
157.sha1 { 182.sha1 {
158 font-family: courier; 183 font-family: courier;
diff --git a/cgit.h b/cgit.h
index 37584d6..bba2d6c 100644
--- a/cgit.h
+++ b/cgit.h
@@ -58,4 +58,5 @@ extern char *cgit_query_page;
58extern char *cgit_query_head; 58extern char *cgit_query_head;
59extern char *cgit_query_sha1; 59extern char *cgit_query_sha1;
60extern char *cgit_query_sha2;
60extern int cgit_query_ofs; 61extern int cgit_query_ofs;
61 62
@@ -105,4 +106,5 @@ extern void cgit_print_view(const char *hex);
105extern void cgit_print_tree(const char *hex); 106extern void cgit_print_tree(const char *hex);
106extern void cgit_print_commit(const char *hex); 107extern void cgit_print_commit(const char *hex);
108extern void cgit_print_diff(const char *old_hex, const char *new_hex);
107 109
108#endif /* CGIT_H */ 110#endif /* CGIT_H */
diff --git a/shared.c b/shared.c
index b576df8..762eb38 100644
--- a/shared.c
+++ b/shared.c
@@ -38,4 +38,5 @@ char *cgit_query_page = NULL;
38char *cgit_query_head = NULL; 38char *cgit_query_head = NULL;
39char *cgit_query_sha1 = NULL; 39char *cgit_query_sha1 = NULL;
40char *cgit_query_sha2 = NULL;
40int cgit_query_ofs = 0; 41int cgit_query_ofs = 0;
41 42
@@ -84,4 +85,7 @@ void cgit_querystring_cb(const char *name, const char *value)
84 cgit_query_sha1 = xstrdup(value); 85 cgit_query_sha1 = xstrdup(value);
85 cgit_query_has_sha1 = 1; 86 cgit_query_has_sha1 = 1;
87 } else if (!strcmp(name, "id2")) {
88 cgit_query_sha2 = xstrdup(value);
89 cgit_query_has_sha1 = 1;
86 } else if (!strcmp(name, "ofs")) { 90 } else if (!strcmp(name, "ofs")) {
87 cgit_query_ofs = atoi(value); 91 cgit_query_ofs = atoi(value);
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}
diff --git a/xdiff.h b/xdiff.h
new file mode 100644
index 0000000..fa409d5
--- a/dev/null
+++ b/xdiff.h
@@ -0,0 +1,105 @@
1/*
2 * LibXDiff by Davide Libenzi ( File Differential Library )
3 * Copyright (C) 2003 Davide Libenzi
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Davide Libenzi <davidel@xmailserver.org>
20 *
21 */
22
23#if !defined(XDIFF_H)
24#define XDIFF_H
25
26#ifdef __cplusplus
27extern "C" {
28#endif /* #ifdef __cplusplus */
29
30
31#define XDF_NEED_MINIMAL (1 << 1)
32#define XDF_IGNORE_WHITESPACE (1 << 2)
33#define XDF_IGNORE_WHITESPACE_CHANGE (1 << 3)
34#define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE)
35
36#define XDL_PATCH_NORMAL '-'
37#define XDL_PATCH_REVERSE '+'
38#define XDL_PATCH_MODEMASK ((1 << 8) - 1)
39#define XDL_PATCH_IGNOREBSPACE (1 << 8)
40
41#define XDL_EMIT_FUNCNAMES (1 << 0)
42#define XDL_EMIT_COMMON (1 << 1)
43
44#define XDL_MMB_READONLY (1 << 0)
45
46#define XDL_MMF_ATOMIC (1 << 0)
47
48#define XDL_BDOP_INS 1
49#define XDL_BDOP_CPY 2
50#define XDL_BDOP_INSB 3
51
52#define XDL_MERGE_MINIMAL 0
53#define XDL_MERGE_EAGER 1
54#define XDL_MERGE_ZEALOUS 2
55
56typedef struct s_mmfile {
57 char *ptr;
58 long size;
59} mmfile_t;
60
61typedef struct s_mmbuffer {
62 char *ptr;
63 long size;
64} mmbuffer_t;
65
66typedef struct s_xpparam {
67 unsigned long flags;
68} xpparam_t;
69
70typedef struct s_xdemitcb {
71 void *priv;
72 int (*outf)(void *, mmbuffer_t *, int);
73} xdemitcb_t;
74
75typedef struct s_xdemitconf {
76 long ctxlen;
77 unsigned long flags;
78} xdemitconf_t;
79
80typedef struct s_bdiffparam {
81 long bsize;
82} bdiffparam_t;
83
84
85#define xdl_malloc(x) malloc(x)
86#define xdl_free(ptr) free(ptr)
87#define xdl_realloc(ptr,x) realloc(ptr,x)
88
89void *xdl_mmfile_first(mmfile_t *mmf, long *size);
90void *xdl_mmfile_next(mmfile_t *mmf, long *size);
91long xdl_mmfile_size(mmfile_t *mmf);
92
93int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
94 xdemitconf_t const *xecfg, xdemitcb_t *ecb);
95
96int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
97 mmfile_t *mf2, const char *name2,
98 xpparam_t const *xpp, int level, mmbuffer_t *result);
99
100#ifdef __cplusplus
101}
102#endif /* #ifdef __cplusplus */
103
104#endif /* #if !defined(XDIFF_H) */
105