summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2007-05-15 22:58:35 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2007-05-15 22:58:35 (UTC)
commitf9ff7df613b4ee86fe5914c4ae3400650882c03d (patch) (unidiff)
treec26fde3a4d3485943c275232f18359bebd133f1a
parenta2ddc10479ec463708e422ca5ce7ec02c22a7d02 (diff)
downloadcgit-f9ff7df613b4ee86fe5914c4ae3400650882c03d.zip
cgit-f9ff7df613b4ee86fe5914c4ae3400650882c03d.tar.gz
cgit-f9ff7df613b4ee86fe5914c4ae3400650882c03d.tar.bz2
Add support for commitdiff via h parameter
The commitdiff will be generated against the first parent, and the diff page also gets the benefit of repo.defbranch. Cleaned up some bad whitespace in cgit.h while at it. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c3
-rw-r--r--cgit.h11
-rw-r--r--ui-diff.c14
3 files changed, 21 insertions, 7 deletions
diff --git a/cgit.c b/cgit.c
index 9b4815d..3e7e595 100644
--- a/cgit.c
+++ b/cgit.c
@@ -1,265 +1,266 @@
1/* cgit.c: cgi for the git scm 1/* cgit.c: cgi for the git scm
2 * 2 *
3 * Copyright (C) 2006 Lars Hjemli 3 * Copyright (C) 2006 Lars Hjemli
4 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
10 10
11const char cgit_version[] = CGIT_VERSION; 11const char cgit_version[] = CGIT_VERSION;
12 12
13 13
14static struct repoinfo *cgit_get_repoinfo(char *url) 14static struct repoinfo *cgit_get_repoinfo(char *url)
15{ 15{
16 int i; 16 int i;
17 struct repoinfo *repo; 17 struct repoinfo *repo;
18 18
19 for (i=0; i<cgit_repolist.count; i++) { 19 for (i=0; i<cgit_repolist.count; i++) {
20 repo = &cgit_repolist.repos[i]; 20 repo = &cgit_repolist.repos[i];
21 if (!strcmp(repo->url, url)) 21 if (!strcmp(repo->url, url))
22 return repo; 22 return repo;
23 } 23 }
24 return NULL; 24 return NULL;
25} 25}
26 26
27 27
28static int cgit_prepare_cache(struct cacheitem *item) 28static int cgit_prepare_cache(struct cacheitem *item)
29{ 29{
30 if (!cgit_query_repo) { 30 if (!cgit_query_repo) {
31 item->name = xstrdup(fmt("%s/index.html", cgit_cache_root)); 31 item->name = xstrdup(fmt("%s/index.html", cgit_cache_root));
32 item->ttl = cgit_cache_root_ttl; 32 item->ttl = cgit_cache_root_ttl;
33 return 1; 33 return 1;
34 } 34 }
35 cgit_repo = cgit_get_repoinfo(cgit_query_repo); 35 cgit_repo = cgit_get_repoinfo(cgit_query_repo);
36 if (!cgit_repo) { 36 if (!cgit_repo) {
37 char *title = fmt("%s - %s", cgit_root_title, "Bad request"); 37 char *title = fmt("%s - %s", cgit_root_title, "Bad request");
38 cgit_print_docstart(title, item); 38 cgit_print_docstart(title, item);
39 cgit_print_pageheader(title, 0); 39 cgit_print_pageheader(title, 0);
40 cgit_print_error(fmt("Unknown repo: %s", cgit_query_repo)); 40 cgit_print_error(fmt("Unknown repo: %s", cgit_query_repo));
41 cgit_print_docend(); 41 cgit_print_docend();
42 return 0; 42 return 0;
43 } 43 }
44 44
45 if (!cgit_query_page) { 45 if (!cgit_query_page) {
46 item->name = xstrdup(fmt("%s/%s/index.html", cgit_cache_root, 46 item->name = xstrdup(fmt("%s/%s/index.html", cgit_cache_root,
47 cgit_repo->url)); 47 cgit_repo->url));
48 item->ttl = cgit_cache_repo_ttl; 48 item->ttl = cgit_cache_repo_ttl;
49 } else { 49 } else {
50 item->name = xstrdup(fmt("%s/%s/%s/%s.html", cgit_cache_root, 50 item->name = xstrdup(fmt("%s/%s/%s/%s.html", cgit_cache_root,
51 cgit_repo->url, cgit_query_page, 51 cgit_repo->url, cgit_query_page,
52 cache_safe_filename(cgit_querystring))); 52 cache_safe_filename(cgit_querystring)));
53 if (cgit_query_has_symref) 53 if (cgit_query_has_symref)
54 item->ttl = cgit_cache_dynamic_ttl; 54 item->ttl = cgit_cache_dynamic_ttl;
55 else if (cgit_query_has_sha1) 55 else if (cgit_query_has_sha1)
56 item->ttl = cgit_cache_static_ttl; 56 item->ttl = cgit_cache_static_ttl;
57 else 57 else
58 item->ttl = cgit_cache_repo_ttl; 58 item->ttl = cgit_cache_repo_ttl;
59 } 59 }
60 return 1; 60 return 1;
61} 61}
62 62
63static void cgit_print_repo_page(struct cacheitem *item) 63static void cgit_print_repo_page(struct cacheitem *item)
64{ 64{
65 char *title; 65 char *title;
66 int show_search; 66 int show_search;
67 67
68 if (!cgit_query_head) 68 if (!cgit_query_head)
69 cgit_query_head = cgit_repo->defbranch; 69 cgit_query_head = cgit_repo->defbranch;
70 70
71 if (chdir(cgit_repo->path)) { 71 if (chdir(cgit_repo->path)) {
72 title = fmt("%s - %s", cgit_root_title, "Bad request"); 72 title = fmt("%s - %s", cgit_root_title, "Bad request");
73 cgit_print_docstart(title, item); 73 cgit_print_docstart(title, item);
74 cgit_print_pageheader(title, 0); 74 cgit_print_pageheader(title, 0);
75 cgit_print_error(fmt("Unable to scan repository: %s", 75 cgit_print_error(fmt("Unable to scan repository: %s",
76 strerror(errno))); 76 strerror(errno)));
77 cgit_print_docend(); 77 cgit_print_docend();
78 return; 78 return;
79 } 79 }
80 80
81 title = fmt("%s - %s", cgit_repo->name, cgit_repo->desc); 81 title = fmt("%s - %s", cgit_repo->name, cgit_repo->desc);
82 show_search = 0; 82 show_search = 0;
83 setenv("GIT_DIR", cgit_repo->path, 1); 83 setenv("GIT_DIR", cgit_repo->path, 1);
84 84
85 if (cgit_query_page) { 85 if (cgit_query_page) {
86 if (cgit_repo->snapshots && !strcmp(cgit_query_page, "snapshot")) { 86 if (cgit_repo->snapshots && !strcmp(cgit_query_page, "snapshot")) {
87 cgit_print_snapshot(item, cgit_query_sha1, "zip", 87 cgit_print_snapshot(item, cgit_query_sha1, "zip",
88 cgit_repo->url, cgit_query_name); 88 cgit_repo->url, cgit_query_name);
89 return; 89 return;
90 } 90 }
91 if (!strcmp(cgit_query_page, "blob")) { 91 if (!strcmp(cgit_query_page, "blob")) {
92 cgit_print_blob(item, cgit_query_sha1, cgit_query_path); 92 cgit_print_blob(item, cgit_query_sha1, cgit_query_path);
93 return; 93 return;
94 } 94 }
95 } 95 }
96 96
97 if (cgit_query_page && !strcmp(cgit_query_page, "log")) 97 if (cgit_query_page && !strcmp(cgit_query_page, "log"))
98 show_search = 1; 98 show_search = 1;
99 99
100 cgit_print_docstart(title, item); 100 cgit_print_docstart(title, item);
101 101
102 102
103 if (!cgit_query_page) { 103 if (!cgit_query_page) {
104 cgit_print_pageheader("summary", show_search); 104 cgit_print_pageheader("summary", show_search);
105 cgit_print_summary(); 105 cgit_print_summary();
106 cgit_print_docend(); 106 cgit_print_docend();
107 return; 107 return;
108 } 108 }
109 109
110 cgit_print_pageheader(cgit_query_page, show_search); 110 cgit_print_pageheader(cgit_query_page, show_search);
111 111
112 if (!strcmp(cgit_query_page, "log")) { 112 if (!strcmp(cgit_query_page, "log")) {
113 cgit_print_log(cgit_query_head, cgit_query_ofs, 113 cgit_print_log(cgit_query_head, cgit_query_ofs,
114 cgit_max_commit_count, cgit_query_search, 114 cgit_max_commit_count, cgit_query_search,
115 cgit_query_path); 115 cgit_query_path);
116 } else if (!strcmp(cgit_query_page, "tree")) { 116 } else if (!strcmp(cgit_query_page, "tree")) {
117 cgit_print_tree(cgit_query_head, cgit_query_sha1, cgit_query_path); 117 cgit_print_tree(cgit_query_head, cgit_query_sha1, cgit_query_path);
118 } else if (!strcmp(cgit_query_page, "commit")) { 118 } else if (!strcmp(cgit_query_page, "commit")) {
119 cgit_print_commit(cgit_query_head); 119 cgit_print_commit(cgit_query_head);
120 } else if (!strcmp(cgit_query_page, "view")) { 120 } else if (!strcmp(cgit_query_page, "view")) {
121 cgit_print_view(cgit_query_sha1, cgit_query_path); 121 cgit_print_view(cgit_query_sha1, cgit_query_path);
122 } else if (!strcmp(cgit_query_page, "diff")) { 122 } else if (!strcmp(cgit_query_page, "diff")) {
123 cgit_print_diff(cgit_query_sha1, cgit_query_sha2, cgit_query_path); 123 cgit_print_diff(cgit_query_head, cgit_query_sha1, cgit_query_sha2,
124 cgit_query_path);
124 } else { 125 } else {
125 cgit_print_error("Invalid request"); 126 cgit_print_error("Invalid request");
126 } 127 }
127 cgit_print_docend(); 128 cgit_print_docend();
128} 129}
129 130
130static void cgit_fill_cache(struct cacheitem *item, int use_cache) 131static void cgit_fill_cache(struct cacheitem *item, int use_cache)
131{ 132{
132 static char buf[PATH_MAX]; 133 static char buf[PATH_MAX];
133 int stdout2; 134 int stdout2;
134 135
135 getcwd(buf, sizeof(buf)); 136 getcwd(buf, sizeof(buf));
136 item->st.st_mtime = time(NULL); 137 item->st.st_mtime = time(NULL);
137 138
138 if (use_cache) { 139 if (use_cache) {
139 stdout2 = chk_positive(dup(STDOUT_FILENO), 140 stdout2 = chk_positive(dup(STDOUT_FILENO),
140 "Preserving STDOUT"); 141 "Preserving STDOUT");
141 chk_zero(close(STDOUT_FILENO), "Closing STDOUT"); 142 chk_zero(close(STDOUT_FILENO), "Closing STDOUT");
142 chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)"); 143 chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)");
143 } 144 }
144 145
145 if (cgit_query_repo) 146 if (cgit_query_repo)
146 cgit_print_repo_page(item); 147 cgit_print_repo_page(item);
147 else 148 else
148 cgit_print_repolist(item); 149 cgit_print_repolist(item);
149 150
150 if (use_cache) { 151 if (use_cache) {
151 chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT"); 152 chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT");
152 chk_positive(dup2(stdout2, STDOUT_FILENO), 153 chk_positive(dup2(stdout2, STDOUT_FILENO),
153 "Restoring original STDOUT"); 154 "Restoring original STDOUT");
154 chk_zero(close(stdout2), "Closing temporary STDOUT"); 155 chk_zero(close(stdout2), "Closing temporary STDOUT");
155 } 156 }
156 157
157 chdir(buf); 158 chdir(buf);
158} 159}
159 160
160static void cgit_check_cache(struct cacheitem *item) 161static void cgit_check_cache(struct cacheitem *item)
161{ 162{
162 int i = 0; 163 int i = 0;
163 164
164 top: 165 top:
165 if (++i > cgit_max_lock_attempts) { 166 if (++i > cgit_max_lock_attempts) {
166 die("cgit_refresh_cache: unable to lock %s: %s", 167 die("cgit_refresh_cache: unable to lock %s: %s",
167 item->name, strerror(errno)); 168 item->name, strerror(errno));
168 } 169 }
169 if (!cache_exist(item)) { 170 if (!cache_exist(item)) {
170 if (!cache_lock(item)) { 171 if (!cache_lock(item)) {
171 sleep(1); 172 sleep(1);
172 goto top; 173 goto top;
173 } 174 }
174 if (!cache_exist(item)) { 175 if (!cache_exist(item)) {
175 cgit_fill_cache(item, 1); 176 cgit_fill_cache(item, 1);
176 cache_unlock(item); 177 cache_unlock(item);
177 } else { 178 } else {
178 cache_cancel_lock(item); 179 cache_cancel_lock(item);
179 } 180 }
180 } else if (cache_expired(item) && cache_lock(item)) { 181 } else if (cache_expired(item) && cache_lock(item)) {
181 if (cache_expired(item)) { 182 if (cache_expired(item)) {
182 cgit_fill_cache(item, 1); 183 cgit_fill_cache(item, 1);
183 cache_unlock(item); 184 cache_unlock(item);
184 } else { 185 } else {
185 cache_cancel_lock(item); 186 cache_cancel_lock(item);
186 } 187 }
187 } 188 }
188} 189}
189 190
190static void cgit_print_cache(struct cacheitem *item) 191static void cgit_print_cache(struct cacheitem *item)
191{ 192{
192 static char buf[4096]; 193 static char buf[4096];
193 ssize_t i; 194 ssize_t i;
194 195
195 int fd = open(item->name, O_RDONLY); 196 int fd = open(item->name, O_RDONLY);
196 if (fd<0) 197 if (fd<0)
197 die("Unable to open cached file %s", item->name); 198 die("Unable to open cached file %s", item->name);
198 199
199 while((i=read(fd, buf, sizeof(buf))) > 0) 200 while((i=read(fd, buf, sizeof(buf))) > 0)
200 write(STDOUT_FILENO, buf, i); 201 write(STDOUT_FILENO, buf, i);
201 202
202 close(fd); 203 close(fd);
203} 204}
204 205
205static void cgit_parse_args(int argc, const char **argv) 206static void cgit_parse_args(int argc, const char **argv)
206{ 207{
207 int i; 208 int i;
208 209
209 for (i = 1; i < argc; i++) { 210 for (i = 1; i < argc; i++) {
210 if (!strncmp(argv[i], "--cache=", 8)) { 211 if (!strncmp(argv[i], "--cache=", 8)) {
211 cgit_cache_root = xstrdup(argv[i]+8); 212 cgit_cache_root = xstrdup(argv[i]+8);
212 } 213 }
213 if (!strcmp(argv[i], "--nocache")) { 214 if (!strcmp(argv[i], "--nocache")) {
214 cgit_nocache = 1; 215 cgit_nocache = 1;
215 } 216 }
216 if (!strncmp(argv[i], "--query=", 8)) { 217 if (!strncmp(argv[i], "--query=", 8)) {
217 cgit_querystring = xstrdup(argv[i]+8); 218 cgit_querystring = xstrdup(argv[i]+8);
218 } 219 }
219 if (!strncmp(argv[i], "--repo=", 7)) { 220 if (!strncmp(argv[i], "--repo=", 7)) {
220 cgit_query_repo = xstrdup(argv[i]+7); 221 cgit_query_repo = xstrdup(argv[i]+7);
221 } 222 }
222 if (!strncmp(argv[i], "--page=", 7)) { 223 if (!strncmp(argv[i], "--page=", 7)) {
223 cgit_query_page = xstrdup(argv[i]+7); 224 cgit_query_page = xstrdup(argv[i]+7);
224 } 225 }
225 if (!strncmp(argv[i], "--head=", 7)) { 226 if (!strncmp(argv[i], "--head=", 7)) {
226 cgit_query_head = xstrdup(argv[i]+7); 227 cgit_query_head = xstrdup(argv[i]+7);
227 cgit_query_has_symref = 1; 228 cgit_query_has_symref = 1;
228 } 229 }
229 if (!strncmp(argv[i], "--sha1=", 7)) { 230 if (!strncmp(argv[i], "--sha1=", 7)) {
230 cgit_query_sha1 = xstrdup(argv[i]+7); 231 cgit_query_sha1 = xstrdup(argv[i]+7);
231 cgit_query_has_sha1 = 1; 232 cgit_query_has_sha1 = 1;
232 } 233 }
233 if (!strncmp(argv[i], "--ofs=", 6)) { 234 if (!strncmp(argv[i], "--ofs=", 6)) {
234 cgit_query_ofs = atoi(argv[i]+6); 235 cgit_query_ofs = atoi(argv[i]+6);
235 } 236 }
236 } 237 }
237} 238}
238 239
239int main(int argc, const char **argv) 240int main(int argc, const char **argv)
240{ 241{
241 struct cacheitem item; 242 struct cacheitem item;
242 243
243 htmlfd = STDOUT_FILENO; 244 htmlfd = STDOUT_FILENO;
244 item.st.st_mtime = time(NULL); 245 item.st.st_mtime = time(NULL);
245 cgit_repolist.length = 0; 246 cgit_repolist.length = 0;
246 cgit_repolist.count = 0; 247 cgit_repolist.count = 0;
247 cgit_repolist.repos = NULL; 248 cgit_repolist.repos = NULL;
248 249
249 cgit_read_config(CGIT_CONFIG, cgit_global_config_cb); 250 cgit_read_config(CGIT_CONFIG, cgit_global_config_cb);
250 if (getenv("SCRIPT_NAME")) 251 if (getenv("SCRIPT_NAME"))
251 cgit_script_name = xstrdup(getenv("SCRIPT_NAME")); 252 cgit_script_name = xstrdup(getenv("SCRIPT_NAME"));
252 if (getenv("QUERY_STRING")) 253 if (getenv("QUERY_STRING"))
253 cgit_querystring = xstrdup(getenv("QUERY_STRING")); 254 cgit_querystring = xstrdup(getenv("QUERY_STRING"));
254 cgit_parse_args(argc, argv); 255 cgit_parse_args(argc, argv);
255 cgit_parse_query(cgit_querystring, cgit_querystring_cb); 256 cgit_parse_query(cgit_querystring, cgit_querystring_cb);
256 if (!cgit_prepare_cache(&item)) 257 if (!cgit_prepare_cache(&item))
257 return 0; 258 return 0;
258 if (cgit_nocache) { 259 if (cgit_nocache) {
259 cgit_fill_cache(&item, 0); 260 cgit_fill_cache(&item, 0);
260 } else { 261 } else {
261 cgit_check_cache(&item); 262 cgit_check_cache(&item);
262 cgit_print_cache(&item); 263 cgit_print_cache(&item);
263 } 264 }
264 return 0; 265 return 0;
265} 266}
diff --git a/cgit.h b/cgit.h
index ac710a6..764225d 100644
--- a/cgit.h
+++ b/cgit.h
@@ -1,184 +1,185 @@
1#ifndef CGIT_H 1#ifndef CGIT_H
2#define CGIT_H 2#define CGIT_H
3 3
4 4
5#include <git-compat-util.h> 5#include <git-compat-util.h>
6#include <cache.h> 6#include <cache.h>
7#include <grep.h> 7#include <grep.h>
8#include <object.h> 8#include <object.h>
9#include <tree.h> 9#include <tree.h>
10#include <commit.h> 10#include <commit.h>
11#include <tag.h> 11#include <tag.h>
12#include <diff.h> 12#include <diff.h>
13#include <diffcore.h> 13#include <diffcore.h>
14#include <refs.h> 14#include <refs.h>
15#include <revision.h> 15#include <revision.h>
16#include <log-tree.h> 16#include <log-tree.h>
17#include <archive.h> 17#include <archive.h>
18#include <xdiff/xdiff.h> 18#include <xdiff/xdiff.h>
19 19
20 20
21typedef void (*configfn)(const char *name, const char *value); 21typedef void (*configfn)(const char *name, const char *value);
22typedef void (*filepair_fn)(struct diff_filepair *pair); 22typedef void (*filepair_fn)(struct diff_filepair *pair);
23typedef void (*linediff_fn)(char *line, int len); 23typedef void (*linediff_fn)(char *line, int len);
24 24
25struct cacheitem { 25struct cacheitem {
26 char *name; 26 char *name;
27 struct stat st; 27 struct stat st;
28 int ttl; 28 int ttl;
29 int fd; 29 int fd;
30}; 30};
31 31
32struct repoinfo { 32struct repoinfo {
33 char *url; 33 char *url;
34 char *name; 34 char *name;
35 char *path; 35 char *path;
36 char *desc; 36 char *desc;
37 char *owner; 37 char *owner;
38 char *defbranch; 38 char *defbranch;
39 char *module_link; 39 char *module_link;
40 int snapshots; 40 int snapshots;
41}; 41};
42 42
43struct repolist { 43struct repolist {
44 int length; 44 int length;
45 int count; 45 int count;
46 struct repoinfo *repos; 46 struct repoinfo *repos;
47}; 47};
48 48
49struct commitinfo { 49struct commitinfo {
50 struct commit *commit; 50 struct commit *commit;
51 char *author; 51 char *author;
52 char *author_email; 52 char *author_email;
53 unsigned long author_date; 53 unsigned long author_date;
54 char *committer; 54 char *committer;
55 char *committer_email; 55 char *committer_email;
56 unsigned long committer_date; 56 unsigned long committer_date;
57 char *subject; 57 char *subject;
58 char *msg; 58 char *msg;
59}; 59};
60 60
61struct taginfo { 61struct taginfo {
62 char *tagger; 62 char *tagger;
63 char *tagger_email; 63 char *tagger_email;
64 int tagger_date; 64 int tagger_date;
65 char *msg; 65 char *msg;
66}; 66};
67 67
68extern const char cgit_version[]; 68extern const char cgit_version[];
69 69
70extern struct repolist cgit_repolist; 70extern struct repolist cgit_repolist;
71extern struct repoinfo *cgit_repo; 71extern struct repoinfo *cgit_repo;
72 72
73extern char *cgit_root_title; 73extern char *cgit_root_title;
74extern char *cgit_css; 74extern char *cgit_css;
75extern char *cgit_logo; 75extern char *cgit_logo;
76extern char *cgit_logo_link; 76extern char *cgit_logo_link;
77extern char *cgit_module_link; 77extern char *cgit_module_link;
78extern char *cgit_virtual_root; 78extern char *cgit_virtual_root;
79extern char *cgit_script_name; 79extern char *cgit_script_name;
80extern char *cgit_cache_root; 80extern char *cgit_cache_root;
81 81
82extern int cgit_nocache; 82extern int cgit_nocache;
83extern int cgit_snapshots; 83extern int cgit_snapshots;
84extern int cgit_max_lock_attempts; 84extern int cgit_max_lock_attempts;
85extern int cgit_cache_root_ttl; 85extern int cgit_cache_root_ttl;
86extern int cgit_cache_repo_ttl; 86extern int cgit_cache_repo_ttl;
87extern int cgit_cache_dynamic_ttl; 87extern int cgit_cache_dynamic_ttl;
88extern int cgit_cache_static_ttl; 88extern int cgit_cache_static_ttl;
89extern int cgit_cache_max_create_time; 89extern int cgit_cache_max_create_time;
90 90
91extern int cgit_max_msg_len; 91extern int cgit_max_msg_len;
92extern int cgit_max_commit_count; 92extern int cgit_max_commit_count;
93 93
94extern char *cgit_repo_name; 94extern char *cgit_repo_name;
95extern char *cgit_repo_desc; 95extern char *cgit_repo_desc;
96extern char *cgit_repo_owner; 96extern char *cgit_repo_owner;
97 97
98extern int cgit_query_has_symref; 98extern int cgit_query_has_symref;
99extern int cgit_query_has_sha1; 99extern int cgit_query_has_sha1;
100 100
101extern char *cgit_querystring; 101extern char *cgit_querystring;
102extern char *cgit_query_repo; 102extern char *cgit_query_repo;
103extern char *cgit_query_page; 103extern char *cgit_query_page;
104extern char *cgit_query_search; 104extern char *cgit_query_search;
105extern char *cgit_query_head; 105extern char *cgit_query_head;
106extern char *cgit_query_sha1; 106extern char *cgit_query_sha1;
107extern char *cgit_query_sha2; 107extern char *cgit_query_sha2;
108extern char *cgit_query_path; 108extern char *cgit_query_path;
109extern char *cgit_query_name; 109extern char *cgit_query_name;
110extern int cgit_query_ofs; 110extern int cgit_query_ofs;
111 111
112extern int htmlfd; 112extern int htmlfd;
113 113
114extern void cgit_global_config_cb(const char *name, const char *value); 114extern void cgit_global_config_cb(const char *name, const char *value);
115extern void cgit_repo_config_cb(const char *name, const char *value); 115extern void cgit_repo_config_cb(const char *name, const char *value);
116extern void cgit_querystring_cb(const char *name, const char *value); 116extern void cgit_querystring_cb(const char *name, const char *value);
117 117
118extern int chk_zero(int result, char *msg); 118extern int chk_zero(int result, char *msg);
119extern int chk_positive(int result, char *msg); 119extern int chk_positive(int result, char *msg);
120 120
121extern int hextoint(char c); 121extern int hextoint(char c);
122 122
123extern void *cgit_free_commitinfo(struct commitinfo *info); 123extern void *cgit_free_commitinfo(struct commitinfo *info);
124 124
125extern int cgit_diff_files(const unsigned char *old_sha1, 125extern int cgit_diff_files(const unsigned char *old_sha1,
126 const unsigned char *new_sha1, 126 const unsigned char *new_sha1,
127 linediff_fn fn); 127 linediff_fn fn);
128 128
129extern void cgit_diff_tree(const unsigned char *old_sha1, 129extern void cgit_diff_tree(const unsigned char *old_sha1,
130 const unsigned char *new_sha1, 130 const unsigned char *new_sha1,
131 filepair_fn fn); 131 filepair_fn fn);
132 132
133extern void cgit_diff_commit(struct commit *commit, filepair_fn fn); 133extern void cgit_diff_commit(struct commit *commit, filepair_fn fn);
134 134
135extern char *fmt(const char *format,...); 135extern char *fmt(const char *format,...);
136 136
137extern void html(const char *txt); 137extern void html(const char *txt);
138extern void htmlf(const char *format,...); 138extern void htmlf(const char *format,...);
139extern void html_txt(char *txt); 139extern void html_txt(char *txt);
140extern void html_ntxt(int len, char *txt); 140extern void html_ntxt(int len, char *txt);
141extern void html_attr(char *txt); 141extern void html_attr(char *txt);
142extern void html_hidden(char *name, char *value); 142extern void html_hidden(char *name, char *value);
143extern void html_link_open(char *url, char *title, char *class); 143extern void html_link_open(char *url, char *title, char *class);
144extern void html_link_close(void); 144extern void html_link_close(void);
145extern void html_filemode(unsigned short mode); 145extern void html_filemode(unsigned short mode);
146 146
147extern int cgit_read_config(const char *filename, configfn fn); 147extern int cgit_read_config(const char *filename, configfn fn);
148extern int cgit_parse_query(char *txt, configfn fn); 148extern int cgit_parse_query(char *txt, configfn fn);
149extern struct commitinfo *cgit_parse_commit(struct commit *commit); 149extern struct commitinfo *cgit_parse_commit(struct commit *commit);
150extern struct taginfo *cgit_parse_tag(struct tag *tag); 150extern struct taginfo *cgit_parse_tag(struct tag *tag);
151 151
152extern char *cache_safe_filename(const char *unsafe); 152extern char *cache_safe_filename(const char *unsafe);
153extern int cache_lock(struct cacheitem *item); 153extern int cache_lock(struct cacheitem *item);
154extern int cache_unlock(struct cacheitem *item); 154extern int cache_unlock(struct cacheitem *item);
155extern int cache_cancel_lock(struct cacheitem *item); 155extern int cache_cancel_lock(struct cacheitem *item);
156extern int cache_exist(struct cacheitem *item); 156extern int cache_exist(struct cacheitem *item);
157extern int cache_expired(struct cacheitem *item); 157extern int cache_expired(struct cacheitem *item);
158 158
159extern char *cgit_repourl(const char *reponame); 159extern char *cgit_repourl(const char *reponame);
160extern char *cgit_pageurl(const char *reponame, const char *pagename, 160extern char *cgit_pageurl(const char *reponame, const char *pagename,
161 const char *query); 161 const char *query);
162 162
163extern void cgit_print_error(char *msg); 163extern void cgit_print_error(char *msg);
164extern void cgit_print_date(unsigned long secs); 164extern void cgit_print_date(unsigned long secs);
165extern void cgit_print_docstart(char *title, struct cacheitem *item); 165extern void cgit_print_docstart(char *title, struct cacheitem *item);
166extern void cgit_print_docend(); 166extern void cgit_print_docend();
167extern void cgit_print_pageheader(char *title, int show_search); 167extern void cgit_print_pageheader(char *title, int show_search);
168extern void cgit_print_snapshot_start(const char *mimetype, 168extern void cgit_print_snapshot_start(const char *mimetype,
169 const char *filename, 169 const char *filename,
170 struct cacheitem *item); 170 struct cacheitem *item);
171 171
172extern void cgit_print_repolist(struct cacheitem *item); 172extern void cgit_print_repolist(struct cacheitem *item);
173extern void cgit_print_summary(); 173extern void cgit_print_summary();
174extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *path); 174extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *path);
175extern void cgit_print_view(const char *hex, char *path); 175extern void cgit_print_view(const char *hex, char *path);
176extern void cgit_print_blob(struct cacheitem *item, const char *hex, char *path); 176extern void cgit_print_blob(struct cacheitem *item, const char *hex, char *path);
177extern void cgit_print_tree(const char *rev, const char *hex, char *path); 177extern void cgit_print_tree(const char *rev, const char *hex, char *path);
178extern void cgit_print_commit(const char *hex); 178extern void cgit_print_commit(const char *hex);
179extern void cgit_print_diff(const char *old_hex, const char *new_hex, char *path); 179extern void cgit_print_diff(const char *head, const char *old_hex, const char *new_hex,
180extern void cgit_print_snapshot(struct cacheitem *item, const char *hex, 180 char *path);
181extern void cgit_print_snapshot(struct cacheitem *item, const char *hex,
181 const char *format, const char *prefix, 182 const char *format, const char *prefix,
182 const char *filename); 183 const char *filename);
183 184
184#endif /* CGIT_H */ 185#endif /* CGIT_H */
diff --git a/ui-diff.c b/ui-diff.c
index 999b6f3..afe1c90 100644
--- a/ui-diff.c
+++ b/ui-diff.c
@@ -1,105 +1,117 @@
1/* ui-diff.c: show diff between two blobs 1/* ui-diff.c: show diff between two blobs
2 * 2 *
3 * Copyright (C) 2006 Lars Hjemli 3 * Copyright (C) 2006 Lars Hjemli
4 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
10 10
11 11
12/* 12/*
13 * print a single line returned from xdiff 13 * print a single line returned from xdiff
14 */ 14 */
15static void print_line(char *line, int len) 15static void print_line(char *line, int len)
16{ 16{
17 char *class = "ctx"; 17 char *class = "ctx";
18 char c = line[len-1]; 18 char c = line[len-1];
19 19
20 if (line[0] == '+') 20 if (line[0] == '+')
21 class = "add"; 21 class = "add";
22 else if (line[0] == '-') 22 else if (line[0] == '-')
23 class = "del"; 23 class = "del";
24 else if (line[0] == '@') 24 else if (line[0] == '@')
25 class = "hunk"; 25 class = "hunk";
26 26
27 htmlf("<div class='%s'>", class); 27 htmlf("<div class='%s'>", class);
28 line[len-1] = '\0'; 28 line[len-1] = '\0';
29 html_txt(line); 29 html_txt(line);
30 html("</div>"); 30 html("</div>");
31 line[len-1] = c; 31 line[len-1] = c;
32} 32}
33 33
34static void header(unsigned char *sha1, char *path1, 34static void header(unsigned char *sha1, char *path1,
35 unsigned char *sha2, char *path2) 35 unsigned char *sha2, char *path2)
36{ 36{
37 char *abbrev1, *abbrev2; 37 char *abbrev1, *abbrev2;
38 if (is_null_sha1(sha1)) 38 if (is_null_sha1(sha1))
39 path1 = "dev/null"; 39 path1 = "dev/null";
40 if (is_null_sha1(sha2)) 40 if (is_null_sha1(sha2))
41 path2 = "dev/null"; 41 path2 = "dev/null";
42 html("<tr><td>"); 42 html("<tr><td>");
43 html("<div class='head'>"); 43 html("<div class='head'>");
44 html("diff --git a/"); 44 html("diff --git a/");
45 html_txt(path1); 45 html_txt(path1);
46 html(" b/"); 46 html(" b/");
47 html_txt(path2); 47 html_txt(path2);
48 abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); 48 abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV));
49 abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); 49 abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV));
50 htmlf("\nindex %s..%s", abbrev1, abbrev2); 50 htmlf("\nindex %s..%s", abbrev1, abbrev2);
51 free(abbrev1); 51 free(abbrev1);
52 free(abbrev2); 52 free(abbrev2);
53 html("\n--- a/"); 53 html("\n--- a/");
54 html_txt(path1); 54 html_txt(path1);
55 html("\n+++ b/"); 55 html("\n+++ b/");
56 html_txt(path2); 56 html_txt(path2);
57 html("</div>"); 57 html("</div>");
58} 58}
59 59
60static void filepair_cb(struct diff_filepair *pair) 60static void filepair_cb(struct diff_filepair *pair)
61{ 61{
62 header(pair->one->sha1, pair->one->path, 62 header(pair->one->sha1, pair->one->path,
63 pair->two->sha1, pair->two->path); 63 pair->two->sha1, pair->two->path);
64 if (cgit_diff_files(pair->one->sha1, pair->two->sha1, print_line)) 64 if (cgit_diff_files(pair->one->sha1, pair->two->sha1, print_line))
65 cgit_print_error("Error running diff"); 65 cgit_print_error("Error running diff");
66 html("</tr></td>"); 66 html("</tr></td>");
67} 67}
68 68
69void cgit_print_diff(const char *old_hex, const char *new_hex, char *path) 69void cgit_print_diff(const char *head, const char *old_hex, const char *new_hex, char *path)
70{ 70{
71 unsigned char sha1[20], sha2[20]; 71 unsigned char sha1[20], sha2[20];
72 enum object_type type; 72 enum object_type type;
73 unsigned long size; 73 unsigned long size;
74 struct commit *commit;
75
76 if (head && !old_hex && !new_hex) {
77 get_sha1(head, sha1);
78 commit = lookup_commit_reference(sha1);
79 if (commit && !parse_commit(commit)) {
80 html("<table class='diff'>");
81 cgit_diff_commit(commit, filepair_cb);
82 html("</td></tr></table>");
83 }
84 return;
85 }
74 86
75 get_sha1(old_hex, sha1); 87 get_sha1(old_hex, sha1);
76 get_sha1(new_hex, sha2); 88 get_sha1(new_hex, sha2);
77 89
78 type = sha1_object_info(sha1, &size); 90 type = sha1_object_info(sha1, &size);
79 if (type == OBJ_BAD) { 91 if (type == OBJ_BAD) {
80 type = sha1_object_info(sha2, &size); 92 type = sha1_object_info(sha2, &size);
81 if (type == OBJ_BAD) { 93 if (type == OBJ_BAD) {
82 cgit_print_error(fmt("Bad object names: %s, %s", old_hex, new_hex)); 94 cgit_print_error(fmt("Bad object names: %s, %s", old_hex, new_hex));
83 return; 95 return;
84 } 96 }
85 } 97 }
86 98
87 html("<table class='diff'>"); 99 html("<table class='diff'>");
88 switch(type) { 100 switch(type) {
89 case OBJ_BLOB: 101 case OBJ_BLOB:
90 html("<tr><td>"); 102 html("<tr><td>");
91 header(sha1, path, sha2, path); 103 header(sha1, path, sha2, path);
92 if (cgit_diff_files(sha1, sha2, print_line)) 104 if (cgit_diff_files(sha1, sha2, print_line))
93 cgit_print_error("Error running diff"); 105 cgit_print_error("Error running diff");
94 html("</tr></td>"); 106 html("</tr></td>");
95 break; 107 break;
96 case OBJ_TREE: 108 case OBJ_TREE:
97 cgit_diff_tree(sha1, sha2, filepair_cb); 109 cgit_diff_tree(sha1, sha2, filepair_cb);
98 break; 110 break;
99 default: 111 default:
100 cgit_print_error(fmt("Unhandled object type: %s", 112 cgit_print_error(fmt("Unhandled object type: %s",
101 typename(type))); 113 typename(type)));
102 break; 114 break;
103 } 115 }
104 html("</td></tr></table>"); 116 html("</td></tr></table>");
105} 117}