summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2007-05-15 22:14:51 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2007-05-15 22:16:00 (UTC)
commitb28b105ec172b258ae5d629381a5890697c2f938 (patch) (unidiff)
tree0673dc5ed94c8ce99c714d1204b6582f9ba96fc5
parent47a81c77fdd017227632c4df9a0b7b135b8a738d (diff)
downloadcgit-b28b105ec172b258ae5d629381a5890697c2f938.zip
cgit-b28b105ec172b258ae5d629381a5890697c2f938.tar.gz
cgit-b28b105ec172b258ae5d629381a5890697c2f938.tar.bz2
Enable default value for head parameter
Pages which expect head to be specified in the querystring can now be given a default value, configurable per repository (via repo.defbranch, which defaults to "master"). Currently, only the log page actually works without parameters, but the defbranch is bound to be exploited. This also removes some dead code from shared.c Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c3
-rw-r--r--cgit.h1
-rw-r--r--shared.c17
3 files changed, 7 insertions, 14 deletions
diff --git a/cgit.c b/cgit.c
index 3c11ff0..b282a67 100644
--- a/cgit.c
+++ b/cgit.c
@@ -1,262 +1,265 @@
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)
69 cgit_query_head = cgit_repo->defbranch;
70
68 if (chdir(cgit_repo->path)) { 71 if (chdir(cgit_repo->path)) {
69 title = fmt("%s - %s", cgit_root_title, "Bad request"); 72 title = fmt("%s - %s", cgit_root_title, "Bad request");
70 cgit_print_docstart(title, item); 73 cgit_print_docstart(title, item);
71 cgit_print_pageheader(title, 0); 74 cgit_print_pageheader(title, 0);
72 cgit_print_error(fmt("Unable to scan repository: %s", 75 cgit_print_error(fmt("Unable to scan repository: %s",
73 strerror(errno))); 76 strerror(errno)));
74 cgit_print_docend(); 77 cgit_print_docend();
75 return; 78 return;
76 } 79 }
77 80
78 title = fmt("%s - %s", cgit_repo->name, cgit_repo->desc); 81 title = fmt("%s - %s", cgit_repo->name, cgit_repo->desc);
79 show_search = 0; 82 show_search = 0;
80 setenv("GIT_DIR", cgit_repo->path, 1); 83 setenv("GIT_DIR", cgit_repo->path, 1);
81 84
82 if (cgit_query_page) { 85 if (cgit_query_page) {
83 if (cgit_repo->snapshots && !strcmp(cgit_query_page, "snapshot")) { 86 if (cgit_repo->snapshots && !strcmp(cgit_query_page, "snapshot")) {
84 cgit_print_snapshot(item, cgit_query_sha1, "zip", 87 cgit_print_snapshot(item, cgit_query_sha1, "zip",
85 cgit_repo->url, cgit_query_name); 88 cgit_repo->url, cgit_query_name);
86 return; 89 return;
87 } 90 }
88 if (!strcmp(cgit_query_page, "blob")) { 91 if (!strcmp(cgit_query_page, "blob")) {
89 cgit_print_blob(item, cgit_query_sha1, cgit_query_path); 92 cgit_print_blob(item, cgit_query_sha1, cgit_query_path);
90 return; 93 return;
91 } 94 }
92 } 95 }
93 96
94 if (cgit_query_page && !strcmp(cgit_query_page, "log")) 97 if (cgit_query_page && !strcmp(cgit_query_page, "log"))
95 show_search = 1; 98 show_search = 1;
96 99
97 cgit_print_docstart(title, item); 100 cgit_print_docstart(title, item);
98 101
99 102
100 if (!cgit_query_page) { 103 if (!cgit_query_page) {
101 cgit_print_pageheader("summary", show_search); 104 cgit_print_pageheader("summary", show_search);
102 cgit_print_summary(); 105 cgit_print_summary();
103 cgit_print_docend(); 106 cgit_print_docend();
104 return; 107 return;
105 } 108 }
106 109
107 cgit_print_pageheader(cgit_query_page, show_search); 110 cgit_print_pageheader(cgit_query_page, show_search);
108 111
109 if (!strcmp(cgit_query_page, "log")) { 112 if (!strcmp(cgit_query_page, "log")) {
110 cgit_print_log(cgit_query_head, cgit_query_ofs, 113 cgit_print_log(cgit_query_head, cgit_query_ofs,
111 cgit_max_commit_count, cgit_query_search, 114 cgit_max_commit_count, cgit_query_search,
112 cgit_query_path); 115 cgit_query_path);
113 } else if (!strcmp(cgit_query_page, "tree")) { 116 } else if (!strcmp(cgit_query_page, "tree")) {
114 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);
115 } else if (!strcmp(cgit_query_page, "commit")) { 118 } else if (!strcmp(cgit_query_page, "commit")) {
116 cgit_print_commit(cgit_query_sha1); 119 cgit_print_commit(cgit_query_sha1);
117 } else if (!strcmp(cgit_query_page, "view")) { 120 } else if (!strcmp(cgit_query_page, "view")) {
118 cgit_print_view(cgit_query_sha1, cgit_query_path); 121 cgit_print_view(cgit_query_sha1, cgit_query_path);
119 } else if (!strcmp(cgit_query_page, "diff")) { 122 } else if (!strcmp(cgit_query_page, "diff")) {
120 cgit_print_diff(cgit_query_sha1, cgit_query_sha2, cgit_query_path); 123 cgit_print_diff(cgit_query_sha1, cgit_query_sha2, cgit_query_path);
121 } else { 124 } else {
122 cgit_print_error("Invalid request"); 125 cgit_print_error("Invalid request");
123 } 126 }
124 cgit_print_docend(); 127 cgit_print_docend();
125} 128}
126 129
127static void cgit_fill_cache(struct cacheitem *item, int use_cache) 130static void cgit_fill_cache(struct cacheitem *item, int use_cache)
128{ 131{
129 static char buf[PATH_MAX]; 132 static char buf[PATH_MAX];
130 int stdout2; 133 int stdout2;
131 134
132 getcwd(buf, sizeof(buf)); 135 getcwd(buf, sizeof(buf));
133 item->st.st_mtime = time(NULL); 136 item->st.st_mtime = time(NULL);
134 137
135 if (use_cache) { 138 if (use_cache) {
136 stdout2 = chk_positive(dup(STDOUT_FILENO), 139 stdout2 = chk_positive(dup(STDOUT_FILENO),
137 "Preserving STDOUT"); 140 "Preserving STDOUT");
138 chk_zero(close(STDOUT_FILENO), "Closing STDOUT"); 141 chk_zero(close(STDOUT_FILENO), "Closing STDOUT");
139 chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)"); 142 chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)");
140 } 143 }
141 144
142 if (cgit_query_repo) 145 if (cgit_query_repo)
143 cgit_print_repo_page(item); 146 cgit_print_repo_page(item);
144 else 147 else
145 cgit_print_repolist(item); 148 cgit_print_repolist(item);
146 149
147 if (use_cache) { 150 if (use_cache) {
148 chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT"); 151 chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT");
149 chk_positive(dup2(stdout2, STDOUT_FILENO), 152 chk_positive(dup2(stdout2, STDOUT_FILENO),
150 "Restoring original STDOUT"); 153 "Restoring original STDOUT");
151 chk_zero(close(stdout2), "Closing temporary STDOUT"); 154 chk_zero(close(stdout2), "Closing temporary STDOUT");
152 } 155 }
153 156
154 chdir(buf); 157 chdir(buf);
155} 158}
156 159
157static void cgit_check_cache(struct cacheitem *item) 160static void cgit_check_cache(struct cacheitem *item)
158{ 161{
159 int i = 0; 162 int i = 0;
160 163
161 top: 164 top:
162 if (++i > cgit_max_lock_attempts) { 165 if (++i > cgit_max_lock_attempts) {
163 die("cgit_refresh_cache: unable to lock %s: %s", 166 die("cgit_refresh_cache: unable to lock %s: %s",
164 item->name, strerror(errno)); 167 item->name, strerror(errno));
165 } 168 }
166 if (!cache_exist(item)) { 169 if (!cache_exist(item)) {
167 if (!cache_lock(item)) { 170 if (!cache_lock(item)) {
168 sleep(1); 171 sleep(1);
169 goto top; 172 goto top;
170 } 173 }
171 if (!cache_exist(item)) { 174 if (!cache_exist(item)) {
172 cgit_fill_cache(item, 1); 175 cgit_fill_cache(item, 1);
173 cache_unlock(item); 176 cache_unlock(item);
174 } else { 177 } else {
175 cache_cancel_lock(item); 178 cache_cancel_lock(item);
176 } 179 }
177 } else if (cache_expired(item) && cache_lock(item)) { 180 } else if (cache_expired(item) && cache_lock(item)) {
178 if (cache_expired(item)) { 181 if (cache_expired(item)) {
179 cgit_fill_cache(item, 1); 182 cgit_fill_cache(item, 1);
180 cache_unlock(item); 183 cache_unlock(item);
181 } else { 184 } else {
182 cache_cancel_lock(item); 185 cache_cancel_lock(item);
183 } 186 }
184 } 187 }
185} 188}
186 189
187static void cgit_print_cache(struct cacheitem *item) 190static void cgit_print_cache(struct cacheitem *item)
188{ 191{
189 static char buf[4096]; 192 static char buf[4096];
190 ssize_t i; 193 ssize_t i;
191 194
192 int fd = open(item->name, O_RDONLY); 195 int fd = open(item->name, O_RDONLY);
193 if (fd<0) 196 if (fd<0)
194 die("Unable to open cached file %s", item->name); 197 die("Unable to open cached file %s", item->name);
195 198
196 while((i=read(fd, buf, sizeof(buf))) > 0) 199 while((i=read(fd, buf, sizeof(buf))) > 0)
197 write(STDOUT_FILENO, buf, i); 200 write(STDOUT_FILENO, buf, i);
198 201
199 close(fd); 202 close(fd);
200} 203}
201 204
202static void cgit_parse_args(int argc, const char **argv) 205static void cgit_parse_args(int argc, const char **argv)
203{ 206{
204 int i; 207 int i;
205 208
206 for (i = 1; i < argc; i++) { 209 for (i = 1; i < argc; i++) {
207 if (!strncmp(argv[i], "--cache=", 8)) { 210 if (!strncmp(argv[i], "--cache=", 8)) {
208 cgit_cache_root = xstrdup(argv[i]+8); 211 cgit_cache_root = xstrdup(argv[i]+8);
209 } 212 }
210 if (!strcmp(argv[i], "--nocache")) { 213 if (!strcmp(argv[i], "--nocache")) {
211 cgit_nocache = 1; 214 cgit_nocache = 1;
212 } 215 }
213 if (!strncmp(argv[i], "--query=", 8)) { 216 if (!strncmp(argv[i], "--query=", 8)) {
214 cgit_querystring = xstrdup(argv[i]+8); 217 cgit_querystring = xstrdup(argv[i]+8);
215 } 218 }
216 if (!strncmp(argv[i], "--repo=", 7)) { 219 if (!strncmp(argv[i], "--repo=", 7)) {
217 cgit_query_repo = xstrdup(argv[i]+7); 220 cgit_query_repo = xstrdup(argv[i]+7);
218 } 221 }
219 if (!strncmp(argv[i], "--page=", 7)) { 222 if (!strncmp(argv[i], "--page=", 7)) {
220 cgit_query_page = xstrdup(argv[i]+7); 223 cgit_query_page = xstrdup(argv[i]+7);
221 } 224 }
222 if (!strncmp(argv[i], "--head=", 7)) { 225 if (!strncmp(argv[i], "--head=", 7)) {
223 cgit_query_head = xstrdup(argv[i]+7); 226 cgit_query_head = xstrdup(argv[i]+7);
224 cgit_query_has_symref = 1; 227 cgit_query_has_symref = 1;
225 } 228 }
226 if (!strncmp(argv[i], "--sha1=", 7)) { 229 if (!strncmp(argv[i], "--sha1=", 7)) {
227 cgit_query_sha1 = xstrdup(argv[i]+7); 230 cgit_query_sha1 = xstrdup(argv[i]+7);
228 cgit_query_has_sha1 = 1; 231 cgit_query_has_sha1 = 1;
229 } 232 }
230 if (!strncmp(argv[i], "--ofs=", 6)) { 233 if (!strncmp(argv[i], "--ofs=", 6)) {
231 cgit_query_ofs = atoi(argv[i]+6); 234 cgit_query_ofs = atoi(argv[i]+6);
232 } 235 }
233 } 236 }
234} 237}
235 238
236int main(int argc, const char **argv) 239int main(int argc, const char **argv)
237{ 240{
238 struct cacheitem item; 241 struct cacheitem item;
239 242
240 htmlfd = STDOUT_FILENO; 243 htmlfd = STDOUT_FILENO;
241 item.st.st_mtime = time(NULL); 244 item.st.st_mtime = time(NULL);
242 cgit_repolist.length = 0; 245 cgit_repolist.length = 0;
243 cgit_repolist.count = 0; 246 cgit_repolist.count = 0;
244 cgit_repolist.repos = NULL; 247 cgit_repolist.repos = NULL;
245 248
246 cgit_read_config(CGIT_CONFIG, cgit_global_config_cb); 249 cgit_read_config(CGIT_CONFIG, cgit_global_config_cb);
247 if (getenv("SCRIPT_NAME")) 250 if (getenv("SCRIPT_NAME"))
248 cgit_script_name = xstrdup(getenv("SCRIPT_NAME")); 251 cgit_script_name = xstrdup(getenv("SCRIPT_NAME"));
249 if (getenv("QUERY_STRING")) 252 if (getenv("QUERY_STRING"))
250 cgit_querystring = xstrdup(getenv("QUERY_STRING")); 253 cgit_querystring = xstrdup(getenv("QUERY_STRING"));
251 cgit_parse_args(argc, argv); 254 cgit_parse_args(argc, argv);
252 cgit_parse_query(cgit_querystring, cgit_querystring_cb); 255 cgit_parse_query(cgit_querystring, cgit_querystring_cb);
253 if (!cgit_prepare_cache(&item)) 256 if (!cgit_prepare_cache(&item))
254 return 0; 257 return 0;
255 if (cgit_nocache) { 258 if (cgit_nocache) {
256 cgit_fill_cache(&item, 0); 259 cgit_fill_cache(&item, 0);
257 } else { 260 } else {
258 cgit_check_cache(&item); 261 cgit_check_cache(&item);
259 cgit_print_cache(&item); 262 cgit_print_cache(&item);
260 } 263 }
261 return 0; 264 return 0;
262} 265}
diff --git a/cgit.h b/cgit.h
index f5906ad..ac710a6 100644
--- a/cgit.h
+++ b/cgit.h
@@ -1,183 +1,184 @@
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 *module_link; 39 char *module_link;
39 int snapshots; 40 int snapshots;
40}; 41};
41 42
42struct repolist { 43struct repolist {
43 int length; 44 int length;
44 int count; 45 int count;
45 struct repoinfo *repos; 46 struct repoinfo *repos;
46}; 47};
47 48
48struct commitinfo { 49struct commitinfo {
49 struct commit *commit; 50 struct commit *commit;
50 char *author; 51 char *author;
51 char *author_email; 52 char *author_email;
52 unsigned long author_date; 53 unsigned long author_date;
53 char *committer; 54 char *committer;
54 char *committer_email; 55 char *committer_email;
55 unsigned long committer_date; 56 unsigned long committer_date;
56 char *subject; 57 char *subject;
57 char *msg; 58 char *msg;
58}; 59};
59 60
60struct taginfo { 61struct taginfo {
61 char *tagger; 62 char *tagger;
62 char *tagger_email; 63 char *tagger_email;
63 int tagger_date; 64 int tagger_date;
64 char *msg; 65 char *msg;
65}; 66};
66 67
67extern const char cgit_version[]; 68extern const char cgit_version[];
68 69
69extern struct repolist cgit_repolist; 70extern struct repolist cgit_repolist;
70extern struct repoinfo *cgit_repo; 71extern struct repoinfo *cgit_repo;
71 72
72extern char *cgit_root_title; 73extern char *cgit_root_title;
73extern char *cgit_css; 74extern char *cgit_css;
74extern char *cgit_logo; 75extern char *cgit_logo;
75extern char *cgit_logo_link; 76extern char *cgit_logo_link;
76extern char *cgit_module_link; 77extern char *cgit_module_link;
77extern char *cgit_virtual_root; 78extern char *cgit_virtual_root;
78extern char *cgit_script_name; 79extern char *cgit_script_name;
79extern char *cgit_cache_root; 80extern char *cgit_cache_root;
80 81
81extern int cgit_nocache; 82extern int cgit_nocache;
82extern int cgit_snapshots; 83extern int cgit_snapshots;
83extern int cgit_max_lock_attempts; 84extern int cgit_max_lock_attempts;
84extern int cgit_cache_root_ttl; 85extern int cgit_cache_root_ttl;
85extern int cgit_cache_repo_ttl; 86extern int cgit_cache_repo_ttl;
86extern int cgit_cache_dynamic_ttl; 87extern int cgit_cache_dynamic_ttl;
87extern int cgit_cache_static_ttl; 88extern int cgit_cache_static_ttl;
88extern int cgit_cache_max_create_time; 89extern int cgit_cache_max_create_time;
89 90
90extern int cgit_max_msg_len; 91extern int cgit_max_msg_len;
91extern int cgit_max_commit_count; 92extern int cgit_max_commit_count;
92 93
93extern char *cgit_repo_name; 94extern char *cgit_repo_name;
94extern char *cgit_repo_desc; 95extern char *cgit_repo_desc;
95extern char *cgit_repo_owner; 96extern char *cgit_repo_owner;
96 97
97extern int cgit_query_has_symref; 98extern int cgit_query_has_symref;
98extern int cgit_query_has_sha1; 99extern int cgit_query_has_sha1;
99 100
100extern char *cgit_querystring; 101extern char *cgit_querystring;
101extern char *cgit_query_repo; 102extern char *cgit_query_repo;
102extern char *cgit_query_page; 103extern char *cgit_query_page;
103extern char *cgit_query_search; 104extern char *cgit_query_search;
104extern char *cgit_query_head; 105extern char *cgit_query_head;
105extern char *cgit_query_sha1; 106extern char *cgit_query_sha1;
106extern char *cgit_query_sha2; 107extern char *cgit_query_sha2;
107extern char *cgit_query_path; 108extern char *cgit_query_path;
108extern char *cgit_query_name; 109extern char *cgit_query_name;
109extern int cgit_query_ofs; 110extern int cgit_query_ofs;
110 111
111extern int htmlfd; 112extern int htmlfd;
112 113
113extern void cgit_global_config_cb(const char *name, const char *value); 114extern void cgit_global_config_cb(const char *name, const char *value);
114extern void cgit_repo_config_cb(const char *name, const char *value); 115extern void cgit_repo_config_cb(const char *name, const char *value);
115extern void cgit_querystring_cb(const char *name, const char *value); 116extern void cgit_querystring_cb(const char *name, const char *value);
116 117
117extern int chk_zero(int result, char *msg); 118extern int chk_zero(int result, char *msg);
118extern int chk_positive(int result, char *msg); 119extern int chk_positive(int result, char *msg);
119 120
120extern int hextoint(char c); 121extern int hextoint(char c);
121 122
122extern void *cgit_free_commitinfo(struct commitinfo *info); 123extern void *cgit_free_commitinfo(struct commitinfo *info);
123 124
124extern int cgit_diff_files(const unsigned char *old_sha1, 125extern int cgit_diff_files(const unsigned char *old_sha1,
125 const unsigned char *new_sha1, 126 const unsigned char *new_sha1,
126 linediff_fn fn); 127 linediff_fn fn);
127 128
128extern void cgit_diff_tree(const unsigned char *old_sha1, 129extern void cgit_diff_tree(const unsigned char *old_sha1,
129 const unsigned char *new_sha1, 130 const unsigned char *new_sha1,
130 filepair_fn fn); 131 filepair_fn fn);
131 132
132extern void cgit_diff_commit(struct commit *commit, filepair_fn fn); 133extern void cgit_diff_commit(struct commit *commit, filepair_fn fn);
133 134
134extern char *fmt(const char *format,...); 135extern char *fmt(const char *format,...);
135 136
136extern void html(const char *txt); 137extern void html(const char *txt);
137extern void htmlf(const char *format,...); 138extern void htmlf(const char *format,...);
138extern void html_txt(char *txt); 139extern void html_txt(char *txt);
139extern void html_ntxt(int len, char *txt); 140extern void html_ntxt(int len, char *txt);
140extern void html_attr(char *txt); 141extern void html_attr(char *txt);
141extern void html_hidden(char *name, char *value); 142extern void html_hidden(char *name, char *value);
142extern void html_link_open(char *url, char *title, char *class); 143extern void html_link_open(char *url, char *title, char *class);
143extern void html_link_close(void); 144extern void html_link_close(void);
144extern void html_filemode(unsigned short mode); 145extern void html_filemode(unsigned short mode);
145 146
146extern int cgit_read_config(const char *filename, configfn fn); 147extern int cgit_read_config(const char *filename, configfn fn);
147extern int cgit_parse_query(char *txt, configfn fn); 148extern int cgit_parse_query(char *txt, configfn fn);
148extern struct commitinfo *cgit_parse_commit(struct commit *commit); 149extern struct commitinfo *cgit_parse_commit(struct commit *commit);
149extern struct taginfo *cgit_parse_tag(struct tag *tag); 150extern struct taginfo *cgit_parse_tag(struct tag *tag);
150 151
151extern char *cache_safe_filename(const char *unsafe); 152extern char *cache_safe_filename(const char *unsafe);
152extern int cache_lock(struct cacheitem *item); 153extern int cache_lock(struct cacheitem *item);
153extern int cache_unlock(struct cacheitem *item); 154extern int cache_unlock(struct cacheitem *item);
154extern int cache_cancel_lock(struct cacheitem *item); 155extern int cache_cancel_lock(struct cacheitem *item);
155extern int cache_exist(struct cacheitem *item); 156extern int cache_exist(struct cacheitem *item);
156extern int cache_expired(struct cacheitem *item); 157extern int cache_expired(struct cacheitem *item);
157 158
158extern char *cgit_repourl(const char *reponame); 159extern char *cgit_repourl(const char *reponame);
159extern char *cgit_pageurl(const char *reponame, const char *pagename, 160extern char *cgit_pageurl(const char *reponame, const char *pagename,
160 const char *query); 161 const char *query);
161 162
162extern void cgit_print_error(char *msg); 163extern void cgit_print_error(char *msg);
163extern void cgit_print_date(unsigned long secs); 164extern void cgit_print_date(unsigned long secs);
164extern void cgit_print_docstart(char *title, struct cacheitem *item); 165extern void cgit_print_docstart(char *title, struct cacheitem *item);
165extern void cgit_print_docend(); 166extern void cgit_print_docend();
166extern void cgit_print_pageheader(char *title, int show_search); 167extern void cgit_print_pageheader(char *title, int show_search);
167extern void cgit_print_snapshot_start(const char *mimetype, 168extern void cgit_print_snapshot_start(const char *mimetype,
168 const char *filename, 169 const char *filename,
169 struct cacheitem *item); 170 struct cacheitem *item);
170 171
171extern void cgit_print_repolist(struct cacheitem *item); 172extern void cgit_print_repolist(struct cacheitem *item);
172extern void cgit_print_summary(); 173extern void cgit_print_summary();
173extern 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);
174extern void cgit_print_view(const char *hex, char *path); 175extern void cgit_print_view(const char *hex, char *path);
175extern 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);
176extern 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);
177extern void cgit_print_commit(const char *hex); 178extern void cgit_print_commit(const char *hex);
178extern void cgit_print_diff(const char *old_hex, const char *new_hex, char *path); 179extern void cgit_print_diff(const char *old_hex, const char *new_hex, char *path);
179extern void cgit_print_snapshot(struct cacheitem *item, const char *hex, 180extern void cgit_print_snapshot(struct cacheitem *item, const char *hex,
180 const char *format, const char *prefix, 181 const char *format, const char *prefix,
181 const char *filename); 182 const char *filename);
182 183
183#endif /* CGIT_H */ 184#endif /* CGIT_H */
diff --git a/shared.c b/shared.c
index 8505397..a1e1acd 100644
--- a/shared.c
+++ b/shared.c
@@ -1,324 +1,313 @@
1/* shared.c: global vars + some callback functions 1/* shared.c: global vars + some callback functions
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
11struct repolist cgit_repolist; 11struct repolist cgit_repolist;
12struct repoinfo *cgit_repo; 12struct repoinfo *cgit_repo;
13 13
14char *cgit_root_title = "Git repository browser"; 14char *cgit_root_title = "Git repository browser";
15char *cgit_css = "/cgit.css"; 15char *cgit_css = "/cgit.css";
16char *cgit_logo = "/git-logo.png"; 16char *cgit_logo = "/git-logo.png";
17char *cgit_logo_link = "http://www.kernel.org/pub/software/scm/git/docs/"; 17char *cgit_logo_link = "http://www.kernel.org/pub/software/scm/git/docs/";
18char *cgit_module_link = "./?repo=%s&page=commit&id=%s"; 18char *cgit_module_link = "./?repo=%s&page=commit&id=%s";
19char *cgit_virtual_root = NULL; 19char *cgit_virtual_root = NULL;
20char *cgit_script_name = CGIT_SCRIPT_NAME; 20char *cgit_script_name = CGIT_SCRIPT_NAME;
21char *cgit_cache_root = "/var/cache/cgit"; 21char *cgit_cache_root = "/var/cache/cgit";
22 22
23int cgit_nocache = 0; 23int cgit_nocache = 0;
24int cgit_snapshots = 0; 24int cgit_snapshots = 0;
25int cgit_max_lock_attempts = 5; 25int cgit_max_lock_attempts = 5;
26int cgit_cache_root_ttl = 5; 26int cgit_cache_root_ttl = 5;
27int cgit_cache_repo_ttl = 5; 27int cgit_cache_repo_ttl = 5;
28int cgit_cache_dynamic_ttl = 5; 28int cgit_cache_dynamic_ttl = 5;
29int cgit_cache_static_ttl = -1; 29int cgit_cache_static_ttl = -1;
30int cgit_cache_max_create_time = 5; 30int cgit_cache_max_create_time = 5;
31 31
32int cgit_max_msg_len = 60; 32int cgit_max_msg_len = 60;
33int cgit_max_commit_count = 50; 33int cgit_max_commit_count = 50;
34 34
35char *cgit_repo_name = NULL;
36char *cgit_repo_desc = NULL;
37char *cgit_repo_owner = NULL;
38
39int cgit_query_has_symref = 0; 35int cgit_query_has_symref = 0;
40int cgit_query_has_sha1 = 0; 36int cgit_query_has_sha1 = 0;
41 37
42char *cgit_querystring = NULL; 38char *cgit_querystring = NULL;
43char *cgit_query_repo = NULL; 39char *cgit_query_repo = NULL;
44char *cgit_query_page = NULL; 40char *cgit_query_page = NULL;
45char *cgit_query_head = NULL; 41char *cgit_query_head = NULL;
46char *cgit_query_search = NULL; 42char *cgit_query_search = NULL;
47char *cgit_query_sha1 = NULL; 43char *cgit_query_sha1 = NULL;
48char *cgit_query_sha2 = NULL; 44char *cgit_query_sha2 = NULL;
49char *cgit_query_path = NULL; 45char *cgit_query_path = NULL;
50char *cgit_query_name = NULL; 46char *cgit_query_name = NULL;
51int cgit_query_ofs = 0; 47int cgit_query_ofs = 0;
52 48
53int htmlfd = 0; 49int htmlfd = 0;
54 50
55int chk_zero(int result, char *msg) 51int chk_zero(int result, char *msg)
56{ 52{
57 if (result != 0) 53 if (result != 0)
58 die("%s: %s", msg, strerror(errno)); 54 die("%s: %s", msg, strerror(errno));
59 return result; 55 return result;
60} 56}
61 57
62int chk_positive(int result, char *msg) 58int chk_positive(int result, char *msg)
63{ 59{
64 if (result <= 0) 60 if (result <= 0)
65 die("%s: %s", msg, strerror(errno)); 61 die("%s: %s", msg, strerror(errno));
66 return result; 62 return result;
67} 63}
68 64
69struct repoinfo *add_repo(const char *url) 65struct repoinfo *add_repo(const char *url)
70{ 66{
71 struct repoinfo *ret; 67 struct repoinfo *ret;
72 68
73 if (++cgit_repolist.count > cgit_repolist.length) { 69 if (++cgit_repolist.count > cgit_repolist.length) {
74 if (cgit_repolist.length == 0) 70 if (cgit_repolist.length == 0)
75 cgit_repolist.length = 8; 71 cgit_repolist.length = 8;
76 else 72 else
77 cgit_repolist.length *= 2; 73 cgit_repolist.length *= 2;
78 cgit_repolist.repos = xrealloc(cgit_repolist.repos, 74 cgit_repolist.repos = xrealloc(cgit_repolist.repos,
79 cgit_repolist.length * 75 cgit_repolist.length *
80 sizeof(struct repoinfo)); 76 sizeof(struct repoinfo));
81 } 77 }
82 78
83 ret = &cgit_repolist.repos[cgit_repolist.count-1]; 79 ret = &cgit_repolist.repos[cgit_repolist.count-1];
84 ret->url = xstrdup(url); 80 ret->url = xstrdup(url);
85 ret->name = ret->url; 81 ret->name = ret->url;
86 ret->path = NULL; 82 ret->path = NULL;
87 ret->desc = NULL; 83 ret->desc = NULL;
88 ret->owner = NULL; 84 ret->owner = NULL;
85 ret->defbranch = "master";
89 ret->snapshots = cgit_snapshots; 86 ret->snapshots = cgit_snapshots;
90 ret->module_link = cgit_module_link; 87 ret->module_link = cgit_module_link;
91 return ret; 88 return ret;
92} 89}
93 90
94void cgit_global_config_cb(const char *name, const char *value) 91void cgit_global_config_cb(const char *name, const char *value)
95{ 92{
96 if (!strcmp(name, "root-title")) 93 if (!strcmp(name, "root-title"))
97 cgit_root_title = xstrdup(value); 94 cgit_root_title = xstrdup(value);
98 else if (!strcmp(name, "css")) 95 else if (!strcmp(name, "css"))
99 cgit_css = xstrdup(value); 96 cgit_css = xstrdup(value);
100 else if (!strcmp(name, "logo")) 97 else if (!strcmp(name, "logo"))
101 cgit_logo = xstrdup(value); 98 cgit_logo = xstrdup(value);
102 else if (!strcmp(name, "logo-link")) 99 else if (!strcmp(name, "logo-link"))
103 cgit_logo_link = xstrdup(value); 100 cgit_logo_link = xstrdup(value);
104 else if (!strcmp(name, "module-link")) 101 else if (!strcmp(name, "module-link"))
105 cgit_module_link = xstrdup(value); 102 cgit_module_link = xstrdup(value);
106 else if (!strcmp(name, "virtual-root")) 103 else if (!strcmp(name, "virtual-root"))
107 cgit_virtual_root = xstrdup(value); 104 cgit_virtual_root = xstrdup(value);
108 else if (!strcmp(name, "nocache")) 105 else if (!strcmp(name, "nocache"))
109 cgit_nocache = atoi(value); 106 cgit_nocache = atoi(value);
110 else if (!strcmp(name, "snapshots")) 107 else if (!strcmp(name, "snapshots"))
111 cgit_snapshots = atoi(value); 108 cgit_snapshots = atoi(value);
112 else if (!strcmp(name, "cache-root")) 109 else if (!strcmp(name, "cache-root"))
113 cgit_cache_root = xstrdup(value); 110 cgit_cache_root = xstrdup(value);
114 else if (!strcmp(name, "cache-root-ttl")) 111 else if (!strcmp(name, "cache-root-ttl"))
115 cgit_cache_root_ttl = atoi(value); 112 cgit_cache_root_ttl = atoi(value);
116 else if (!strcmp(name, "cache-repo-ttl")) 113 else if (!strcmp(name, "cache-repo-ttl"))
117 cgit_cache_repo_ttl = atoi(value); 114 cgit_cache_repo_ttl = atoi(value);
118 else if (!strcmp(name, "cache-static-ttl")) 115 else if (!strcmp(name, "cache-static-ttl"))
119 cgit_cache_static_ttl = atoi(value); 116 cgit_cache_static_ttl = atoi(value);
120 else if (!strcmp(name, "cache-dynamic-ttl")) 117 else if (!strcmp(name, "cache-dynamic-ttl"))
121 cgit_cache_dynamic_ttl = atoi(value); 118 cgit_cache_dynamic_ttl = atoi(value);
122 else if (!strcmp(name, "max-message-length")) 119 else if (!strcmp(name, "max-message-length"))
123 cgit_max_msg_len = atoi(value); 120 cgit_max_msg_len = atoi(value);
124 else if (!strcmp(name, "max-commit-count")) 121 else if (!strcmp(name, "max-commit-count"))
125 cgit_max_commit_count = atoi(value); 122 cgit_max_commit_count = atoi(value);
126 else if (!strcmp(name, "repo.url")) 123 else if (!strcmp(name, "repo.url"))
127 cgit_repo = add_repo(value); 124 cgit_repo = add_repo(value);
128 else if (!strcmp(name, "repo.name")) 125 else if (!strcmp(name, "repo.name"))
129 cgit_repo->name = xstrdup(value); 126 cgit_repo->name = xstrdup(value);
130 else if (cgit_repo && !strcmp(name, "repo.path")) 127 else if (cgit_repo && !strcmp(name, "repo.path"))
131 cgit_repo->path = xstrdup(value); 128 cgit_repo->path = xstrdup(value);
132 else if (cgit_repo && !strcmp(name, "repo.desc")) 129 else if (cgit_repo && !strcmp(name, "repo.desc"))
133 cgit_repo->desc = xstrdup(value); 130 cgit_repo->desc = xstrdup(value);
134 else if (cgit_repo && !strcmp(name, "repo.owner")) 131 else if (cgit_repo && !strcmp(name, "repo.owner"))
135 cgit_repo->owner = xstrdup(value); 132 cgit_repo->owner = xstrdup(value);
133 else if (cgit_repo && !strcmp(name, "repo.defbranch"))
134 cgit_repo->defbranch = xstrdup(value);
136 else if (cgit_repo && !strcmp(name, "repo.snapshots")) 135 else if (cgit_repo && !strcmp(name, "repo.snapshots"))
137 cgit_repo->snapshots = atoi(value); 136 cgit_repo->snapshots = atoi(value);
138 else if (cgit_repo && !strcmp(name, "repo.module-link")) 137 else if (cgit_repo && !strcmp(name, "repo.module-link"))
139 cgit_repo->module_link= xstrdup(value); 138 cgit_repo->module_link= xstrdup(value);
140 else if (!strcmp(name, "include")) 139 else if (!strcmp(name, "include"))
141 cgit_read_config(value, cgit_global_config_cb); 140 cgit_read_config(value, cgit_global_config_cb);
142} 141}
143 142
144void cgit_repo_config_cb(const char *name, const char *value)
145{
146 if (!strcmp(name, "name"))
147 cgit_repo_name = xstrdup(value);
148 else if (!strcmp(name, "desc"))
149 cgit_repo_desc = xstrdup(value);
150 else if (!strcmp(name, "owner"))
151 cgit_repo_owner = xstrdup(value);
152}
153
154void cgit_querystring_cb(const char *name, const char *value) 143void cgit_querystring_cb(const char *name, const char *value)
155{ 144{
156 if (!strcmp(name,"r")) { 145 if (!strcmp(name,"r")) {
157 cgit_query_repo = xstrdup(value); 146 cgit_query_repo = xstrdup(value);
158 } else if (!strcmp(name, "p")) { 147 } else if (!strcmp(name, "p")) {
159 cgit_query_page = xstrdup(value); 148 cgit_query_page = xstrdup(value);
160 } else if (!strcmp(name, "q")) { 149 } else if (!strcmp(name, "q")) {
161 cgit_query_search = xstrdup(value); 150 cgit_query_search = xstrdup(value);
162 } else if (!strcmp(name, "h")) { 151 } else if (!strcmp(name, "h")) {
163 cgit_query_head = xstrdup(value); 152 cgit_query_head = xstrdup(value);
164 cgit_query_has_symref = 1; 153 cgit_query_has_symref = 1;
165 } else if (!strcmp(name, "id")) { 154 } else if (!strcmp(name, "id")) {
166 cgit_query_sha1 = xstrdup(value); 155 cgit_query_sha1 = xstrdup(value);
167 cgit_query_has_sha1 = 1; 156 cgit_query_has_sha1 = 1;
168 } else if (!strcmp(name, "id2")) { 157 } else if (!strcmp(name, "id2")) {
169 cgit_query_sha2 = xstrdup(value); 158 cgit_query_sha2 = xstrdup(value);
170 cgit_query_has_sha1 = 1; 159 cgit_query_has_sha1 = 1;
171 } else if (!strcmp(name, "ofs")) { 160 } else if (!strcmp(name, "ofs")) {
172 cgit_query_ofs = atoi(value); 161 cgit_query_ofs = atoi(value);
173 } else if (!strcmp(name, "path")) { 162 } else if (!strcmp(name, "path")) {
174 cgit_query_path = xstrdup(value); 163 cgit_query_path = xstrdup(value);
175 } else if (!strcmp(name, "name")) { 164 } else if (!strcmp(name, "name")) {
176 cgit_query_name = xstrdup(value); 165 cgit_query_name = xstrdup(value);
177 } 166 }
178} 167}
179 168
180void *cgit_free_commitinfo(struct commitinfo *info) 169void *cgit_free_commitinfo(struct commitinfo *info)
181{ 170{
182 free(info->author); 171 free(info->author);
183 free(info->author_email); 172 free(info->author_email);
184 free(info->committer); 173 free(info->committer);
185 free(info->committer_email); 174 free(info->committer_email);
186 free(info->subject); 175 free(info->subject);
187 free(info); 176 free(info);
188 return NULL; 177 return NULL;
189} 178}
190 179
191int hextoint(char c) 180int hextoint(char c)
192{ 181{
193 if (c >= 'a' && c <= 'f') 182 if (c >= 'a' && c <= 'f')
194 return 10 + c - 'a'; 183 return 10 + c - 'a';
195 else if (c >= 'A' && c <= 'F') 184 else if (c >= 'A' && c <= 'F')
196 return 10 + c - 'A'; 185 return 10 + c - 'A';
197 else if (c >= '0' && c <= '9') 186 else if (c >= '0' && c <= '9')
198 return c - '0'; 187 return c - '0';
199 else 188 else
200 return -1; 189 return -1;
201} 190}
202 191
203void cgit_diff_tree_cb(struct diff_queue_struct *q, 192void cgit_diff_tree_cb(struct diff_queue_struct *q,
204 struct diff_options *options, void *data) 193 struct diff_options *options, void *data)
205{ 194{
206 int i; 195 int i;
207 196
208 for (i = 0; i < q->nr; i++) { 197 for (i = 0; i < q->nr; i++) {
209 if (q->queue[i]->status == 'U') 198 if (q->queue[i]->status == 'U')
210 continue; 199 continue;
211 ((filepair_fn)data)(q->queue[i]); 200 ((filepair_fn)data)(q->queue[i]);
212 } 201 }
213} 202}
214 203
215static int load_mmfile(mmfile_t *file, const unsigned char *sha1) 204static int load_mmfile(mmfile_t *file, const unsigned char *sha1)
216{ 205{
217 enum object_type type; 206 enum object_type type;
218 207
219 if (is_null_sha1(sha1)) { 208 if (is_null_sha1(sha1)) {
220 file->ptr = (char *)""; 209 file->ptr = (char *)"";
221 file->size = 0; 210 file->size = 0;
222 } else { 211 } else {
223 file->ptr = read_sha1_file(sha1, &type, &file->size); 212 file->ptr = read_sha1_file(sha1, &type, &file->size);
224 } 213 }
225 return 1; 214 return 1;
226} 215}
227 216
228/* 217/*
229 * Receive diff-buffers from xdiff and concatenate them as 218 * Receive diff-buffers from xdiff and concatenate them as
230 * needed across multiple callbacks. 219 * needed across multiple callbacks.
231 * 220 *
232 * This is basically a copy of xdiff-interface.c/xdiff_outf(), 221 * This is basically a copy of xdiff-interface.c/xdiff_outf(),
233 * ripped from git and modified to use globals instead of 222 * ripped from git and modified to use globals instead of
234 * a special callback-struct. 223 * a special callback-struct.
235 */ 224 */
236char *diffbuf = NULL; 225char *diffbuf = NULL;
237int buflen = 0; 226int buflen = 0;
238 227
239int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) 228int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf)
240{ 229{
241 int i; 230 int i;
242 231
243 for (i = 0; i < nbuf; i++) { 232 for (i = 0; i < nbuf; i++) {
244 if (mb[i].ptr[mb[i].size-1] != '\n') { 233 if (mb[i].ptr[mb[i].size-1] != '\n') {
245 /* Incomplete line */ 234 /* Incomplete line */
246 diffbuf = xrealloc(diffbuf, buflen + mb[i].size); 235 diffbuf = xrealloc(diffbuf, buflen + mb[i].size);
247 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); 236 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size);
248 buflen += mb[i].size; 237 buflen += mb[i].size;
249 continue; 238 continue;
250 } 239 }
251 240
252 /* we have a complete line */ 241 /* we have a complete line */
253 if (!diffbuf) { 242 if (!diffbuf) {
254 ((linediff_fn)priv)(mb[i].ptr, mb[i].size); 243 ((linediff_fn)priv)(mb[i].ptr, mb[i].size);
255 continue; 244 continue;
256 } 245 }
257 diffbuf = xrealloc(diffbuf, buflen + mb[i].size); 246 diffbuf = xrealloc(diffbuf, buflen + mb[i].size);
258 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); 247 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size);
259 ((linediff_fn)priv)(diffbuf, buflen + mb[i].size); 248 ((linediff_fn)priv)(diffbuf, buflen + mb[i].size);
260 free(diffbuf); 249 free(diffbuf);
261 diffbuf = NULL; 250 diffbuf = NULL;
262 buflen = 0; 251 buflen = 0;
263 } 252 }
264 if (diffbuf) { 253 if (diffbuf) {
265 ((linediff_fn)priv)(diffbuf, buflen); 254 ((linediff_fn)priv)(diffbuf, buflen);
266 free(diffbuf); 255 free(diffbuf);
267 diffbuf = NULL; 256 diffbuf = NULL;
268 buflen = 0; 257 buflen = 0;
269 } 258 }
270 return 0; 259 return 0;
271} 260}
272 261
273int cgit_diff_files(const unsigned char *old_sha1, 262int cgit_diff_files(const unsigned char *old_sha1,
274 const unsigned char *new_sha1, 263 const unsigned char *new_sha1,
275 linediff_fn fn) 264 linediff_fn fn)
276{ 265{
277 mmfile_t file1, file2; 266 mmfile_t file1, file2;
278 xpparam_t diff_params; 267 xpparam_t diff_params;
279 xdemitconf_t emit_params; 268 xdemitconf_t emit_params;
280 xdemitcb_t emit_cb; 269 xdemitcb_t emit_cb;
281 270
282 if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1)) 271 if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1))
283 return 1; 272 return 1;
284 273
285 diff_params.flags = XDF_NEED_MINIMAL; 274 diff_params.flags = XDF_NEED_MINIMAL;
286 emit_params.ctxlen = 3; 275 emit_params.ctxlen = 3;
287 emit_params.flags = XDL_EMIT_FUNCNAMES; 276 emit_params.flags = XDL_EMIT_FUNCNAMES;
288 emit_cb.outf = filediff_cb; 277 emit_cb.outf = filediff_cb;
289 emit_cb.priv = fn; 278 emit_cb.priv = fn;
290 xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); 279 xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb);
291 return 0; 280 return 0;
292} 281}
293 282
294void cgit_diff_tree(const unsigned char *old_sha1, 283void cgit_diff_tree(const unsigned char *old_sha1,
295 const unsigned char *new_sha1, 284 const unsigned char *new_sha1,
296 filepair_fn fn) 285 filepair_fn fn)
297{ 286{
298 struct diff_options opt; 287 struct diff_options opt;
299 int ret; 288 int ret;
300 289
301 diff_setup(&opt); 290 diff_setup(&opt);
302 opt.output_format = DIFF_FORMAT_CALLBACK; 291 opt.output_format = DIFF_FORMAT_CALLBACK;
303 opt.detect_rename = 1; 292 opt.detect_rename = 1;
304 opt.recursive = 1; 293 opt.recursive = 1;
305 opt.format_callback = cgit_diff_tree_cb; 294 opt.format_callback = cgit_diff_tree_cb;
306 opt.format_callback_data = fn; 295 opt.format_callback_data = fn;
307 diff_setup_done(&opt); 296 diff_setup_done(&opt);
308 297
309 if (old_sha1) 298 if (old_sha1)
310 ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt); 299 ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt);
311 else 300 else
312 ret = diff_root_tree_sha1(new_sha1, "", &opt); 301 ret = diff_root_tree_sha1(new_sha1, "", &opt);
313 diffcore_std(&opt); 302 diffcore_std(&opt);
314 diff_flush(&opt); 303 diff_flush(&opt);
315} 304}
316 305
317void cgit_diff_commit(struct commit *commit, filepair_fn fn) 306void cgit_diff_commit(struct commit *commit, filepair_fn fn)
318{ 307{
319 unsigned char *old_sha1 = NULL; 308 unsigned char *old_sha1 = NULL;
320 309
321 if (commit->parents) 310 if (commit->parents)
322 old_sha1 = commit->parents->item->object.sha1; 311 old_sha1 = commit->parents->item->object.sha1;
323 cgit_diff_tree(old_sha1, commit->object.sha1, fn); 312 cgit_diff_tree(old_sha1, commit->object.sha1, fn);
324} 313}