summaryrefslogtreecommitdiffabout
Unidiff
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
@@ -1,21 +1,21 @@
1CGIT_VERSION = 0.1-pre 1CGIT_VERSION = 0.1-pre
2 2
3INSTALL_BIN = /var/www/htdocs/cgit.cgi 3INSTALL_BIN = /var/www/htdocs/cgit.cgi
4INSTALL_CSS = /var/www/htdocs/cgit.css 4INSTALL_CSS = /var/www/htdocs/cgit.css
5CACHE_ROOT = /var/cache/cgit 5CACHE_ROOT = /var/cache/cgit
6 6
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
12 12
13all: cgit 13all: cgit
14 14
15install: all clean-cache 15install: all clean-cache
16 install cgit $(INSTALL_BIN) 16 install cgit $(INSTALL_BIN)
17 install cgit.css $(INSTALL_CSS) 17 install cgit.css $(INSTALL_CSS)
18 18
19cgit: cgit.c cgit.h git.h $(OBJECTS) 19cgit: cgit.c cgit.h git.h $(OBJECTS)
20 $(CC) $(CFLAGS) -DCGIT_VERSION='"$(CGIT_VERSION)"' cgit.c -o cgit \ 20 $(CC) $(CFLAGS) -DCGIT_VERSION='"$(CGIT_VERSION)"' cgit.c -o cgit \
21 $(OBJECTS) $(EXTLIBS) 21 $(OBJECTS) $(EXTLIBS)
diff --git a/cgit.c b/cgit.c
index 372b436..ac43441 100644
--- a/cgit.c
+++ b/cgit.c
@@ -27,24 +27,26 @@ static void cgit_print_repo_page(struct cacheitem *item)
27 cgit_print_docstart(title, item); 27 cgit_print_docstart(title, item);
28 cgit_print_pageheader(title); 28 cgit_print_pageheader(title);
29 if (!cgit_query_page) { 29 if (!cgit_query_page) {
30 cgit_print_summary(); 30 cgit_print_summary();
31 } else if (!strcmp(cgit_query_page, "log")) { 31 } else if (!strcmp(cgit_query_page, "log")) {
32 cgit_print_log(cgit_query_head, cgit_query_ofs, 100); 32 cgit_print_log(cgit_query_head, cgit_query_ofs, 100);
33 } else if (!strcmp(cgit_query_page, "tree")) { 33 } else if (!strcmp(cgit_query_page, "tree")) {
34 cgit_print_tree(cgit_query_sha1); 34 cgit_print_tree(cgit_query_sha1);
35 } else if (!strcmp(cgit_query_page, "commit")) { 35 } else if (!strcmp(cgit_query_page, "commit")) {
36 cgit_print_commit(cgit_query_sha1); 36 cgit_print_commit(cgit_query_sha1);
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();
41} 43}
42 44
43static void cgit_fill_cache(struct cacheitem *item) 45static void cgit_fill_cache(struct cacheitem *item)
44{ 46{
45 static char buf[PATH_MAX]; 47 static char buf[PATH_MAX];
46 48
47 getcwd(buf, sizeof(buf)); 49 getcwd(buf, sizeof(buf));
48 htmlfd = item->fd; 50 htmlfd = item->fd;
49 item->st.st_mtime = time(NULL); 51 item->st.st_mtime = time(NULL);
50 if (cgit_query_repo) 52 if (cgit_query_repo)
diff --git a/cgit.css b/cgit.css
index 5f01926..7b8e468 100644
--- a/cgit.css
+++ b/cgit.css
@@ -68,30 +68,36 @@ div#content {
68 margin: 0.5em 0.5em; 68 margin: 0.5em 0.5em;
69} 69}
70 70
71div#blob { 71div#blob {
72 border: solid 1px black; 72 border: solid 1px black;
73} 73}
74 74
75div.error { 75div.error {
76 color: red; 76 color: red;
77 font-weight: bold; 77 font-weight: bold;
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;
82} 85}
83th.filesize, td.filesize { 86th.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;
88} 94}
89 95
90td.blob { 96td.blob {
91 white-space: pre; 97 white-space: pre;
92 font-family: courier; 98 font-family: courier;
93 font-size: 100%; 99 font-size: 100%;
94 background-color: white; 100 background-color: white;
95} 101}
96 102
97table.log td { 103table.log td {
@@ -145,22 +151,41 @@ table.diffstat td.add a {
145} 151}
146table.diffstat td.del a { 152table.diffstat td.del a {
147 color: red; 153 color: red;
148} 154}
149table.diffstat td.upd a { 155table.diffstat td.upd a {
150 color: blue; 156 color: blue;
151} 157}
152table.diffstat td.summary { 158table.diffstat td.summary {
153 /* border-top: solid 1px black; */ 159 /* border-top: solid 1px black; */
154 color: #888; 160 color: #888;
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;
159 font-size: 90%; 184 font-size: 90%;
160} 185}
161.left { 186.left {
162 text-align: left; 187 text-align: left;
163} 188}
164.right { 189.right {
165 text-align: right; 190 text-align: right;
166} 191}
diff --git a/cgit.h b/cgit.h
index 37584d6..bba2d6c 100644
--- a/cgit.h
+++ b/cgit.h
@@ -48,24 +48,25 @@ extern int cgit_cache_max_create_time;
48extern char *cgit_repo_name; 48extern char *cgit_repo_name;
49extern char *cgit_repo_desc; 49extern char *cgit_repo_desc;
50extern char *cgit_repo_owner; 50extern char *cgit_repo_owner;
51 51
52extern int cgit_query_has_symref; 52extern int cgit_query_has_symref;
53extern int cgit_query_has_sha1; 53extern int cgit_query_has_sha1;
54 54
55extern char *cgit_querystring; 55extern char *cgit_querystring;
56extern char *cgit_query_repo; 56extern char *cgit_query_repo;
57extern char *cgit_query_page; 57extern 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
62extern int htmlfd; 63extern int htmlfd;
63 64
64extern void cgit_global_config_cb(const char *name, const char *value); 65extern void cgit_global_config_cb(const char *name, const char *value);
65extern void cgit_repo_config_cb(const char *name, const char *value); 66extern void cgit_repo_config_cb(const char *name, const char *value);
66extern void cgit_querystring_cb(const char *name, const char *value); 67extern void cgit_querystring_cb(const char *name, const char *value);
67 68
68extern void *cgit_free_commitinfo(struct commitinfo *info); 69extern void *cgit_free_commitinfo(struct commitinfo *info);
69 70
70extern char *fmt(const char *format,...); 71extern char *fmt(const char *format,...);
71 72
@@ -95,14 +96,15 @@ extern char *cgit_pageurl(const char *reponame, const char *pagename,
95extern void cgit_print_error(char *msg); 96extern void cgit_print_error(char *msg);
96extern void cgit_print_date(unsigned long secs); 97extern void cgit_print_date(unsigned long secs);
97extern void cgit_print_docstart(char *title, struct cacheitem *item); 98extern void cgit_print_docstart(char *title, struct cacheitem *item);
98extern void cgit_print_docend(); 99extern void cgit_print_docend();
99extern void cgit_print_pageheader(char *title); 100extern void cgit_print_pageheader(char *title);
100 101
101extern void cgit_print_repolist(struct cacheitem *item); 102extern void cgit_print_repolist(struct cacheitem *item);
102extern void cgit_print_summary(); 103extern void cgit_print_summary();
103extern void cgit_print_log(const char *tip, int ofs, int cnt); 104extern void cgit_print_log(const char *tip, int ofs, int cnt);
104extern void cgit_print_view(const char *hex); 105extern 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
@@ -28,24 +28,25 @@ int cgit_cache_max_create_time = 5;
28char *cgit_repo_name = NULL; 28char *cgit_repo_name = NULL;
29char *cgit_repo_desc = NULL; 29char *cgit_repo_desc = NULL;
30char *cgit_repo_owner = NULL; 30char *cgit_repo_owner = NULL;
31 31
32int cgit_query_has_symref = 0; 32int cgit_query_has_symref = 0;
33int cgit_query_has_sha1 = 0; 33int cgit_query_has_sha1 = 0;
34 34
35char *cgit_querystring = NULL; 35char *cgit_querystring = NULL;
36char *cgit_query_repo = NULL; 36char *cgit_query_repo = NULL;
37char *cgit_query_page = NULL; 37char *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
42int htmlfd = 0; 43int htmlfd = 0;
43 44
44void cgit_global_config_cb(const char *name, const char *value) 45void cgit_global_config_cb(const char *name, const char *value)
45{ 46{
46 if (!strcmp(name, "root")) 47 if (!strcmp(name, "root"))
47 cgit_root = xstrdup(value); 48 cgit_root = xstrdup(value);
48 else if (!strcmp(name, "root-title")) 49 else if (!strcmp(name, "root-title"))
49 cgit_root_title = xstrdup(value); 50 cgit_root_title = xstrdup(value);
50 else if (!strcmp(name, "css")) 51 else if (!strcmp(name, "css"))
51 cgit_css = xstrdup(value); 52 cgit_css = xstrdup(value);
@@ -74,24 +75,27 @@ void cgit_repo_config_cb(const char *name, const char *value)
74void cgit_querystring_cb(const char *name, const char *value) 75void cgit_querystring_cb(const char *name, const char *value)
75{ 76{
76 if (!strcmp(name,"r")) { 77 if (!strcmp(name,"r")) {
77 cgit_query_repo = xstrdup(value); 78 cgit_query_repo = xstrdup(value);
78 } else if (!strcmp(name, "p")) { 79 } else if (!strcmp(name, "p")) {
79 cgit_query_page = xstrdup(value); 80 cgit_query_page = xstrdup(value);
80 } else if (!strcmp(name, "h")) { 81 } else if (!strcmp(name, "h")) {
81 cgit_query_head = xstrdup(value); 82 cgit_query_head = xstrdup(value);
82 cgit_query_has_symref = 1; 83 cgit_query_has_symref = 1;
83 } else if (!strcmp(name, "id")) { 84 } else if (!strcmp(name, "id")) {
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);
88 } 92 }
89} 93}
90 94
91void *cgit_free_commitinfo(struct commitinfo *info) 95void *cgit_free_commitinfo(struct commitinfo *info)
92{ 96{
93 free(info->author); 97 free(info->author);
94 free(info->author_email); 98 free(info->author_email);
95 free(info->committer); 99 free(info->committer);
96 free(info->committer_email); 100 free(info->committer_email);
97 free(info->subject); 101 free(info->subject);
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