author | Lars Hjemli <hjemli@gmail.com> | 2007-05-15 22:58:35 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2007-05-15 22:58:35 (UTC) |
commit | f9ff7df613b4ee86fe5914c4ae3400650882c03d (patch) (unidiff) | |
tree | c26fde3a4d3485943c275232f18359bebd133f1a | |
parent | a2ddc10479ec463708e422ca5ce7ec02c22a7d02 (diff) | |
download | cgit-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>
-rw-r--r-- | cgit.c | 3 | ||||
-rw-r--r-- | cgit.h | 11 | ||||
-rw-r--r-- | ui-diff.c | 14 |
3 files changed, 21 insertions, 7 deletions
@@ -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 | ||
11 | const char cgit_version[] = CGIT_VERSION; | 11 | const char cgit_version[] = CGIT_VERSION; |
12 | 12 | ||
13 | 13 | ||
14 | static struct repoinfo *cgit_get_repoinfo(char *url) | 14 | static 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 | ||
28 | static int cgit_prepare_cache(struct cacheitem *item) | 28 | static 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 | ||
63 | static void cgit_print_repo_page(struct cacheitem *item) | 63 | static 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 | ||
130 | static void cgit_fill_cache(struct cacheitem *item, int use_cache) | 131 | static 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 | ||
160 | static void cgit_check_cache(struct cacheitem *item) | 161 | static 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 | ||
190 | static void cgit_print_cache(struct cacheitem *item) | 191 | static 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 | ||
205 | static void cgit_parse_args(int argc, const char **argv) | 206 | static 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 | ||
239 | int main(int argc, const char **argv) | 240 | int 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 | } |
@@ -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 | ||
21 | typedef void (*configfn)(const char *name, const char *value); | 21 | typedef void (*configfn)(const char *name, const char *value); |
22 | typedef void (*filepair_fn)(struct diff_filepair *pair); | 22 | typedef void (*filepair_fn)(struct diff_filepair *pair); |
23 | typedef void (*linediff_fn)(char *line, int len); | 23 | typedef void (*linediff_fn)(char *line, int len); |
24 | 24 | ||
25 | struct cacheitem { | 25 | struct 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 | ||
32 | struct repoinfo { | 32 | struct 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 | ||
43 | struct repolist { | 43 | struct 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 | ||
49 | struct commitinfo { | 49 | struct 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 | ||
61 | struct taginfo { | 61 | struct 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 | ||
68 | extern const char cgit_version[]; | 68 | extern const char cgit_version[]; |
69 | 69 | ||
70 | extern struct repolist cgit_repolist; | 70 | extern struct repolist cgit_repolist; |
71 | extern struct repoinfo *cgit_repo; | 71 | extern struct repoinfo *cgit_repo; |
72 | 72 | ||
73 | extern char *cgit_root_title; | 73 | extern char *cgit_root_title; |
74 | extern char *cgit_css; | 74 | extern char *cgit_css; |
75 | extern char *cgit_logo; | 75 | extern char *cgit_logo; |
76 | extern char *cgit_logo_link; | 76 | extern char *cgit_logo_link; |
77 | extern char *cgit_module_link; | 77 | extern char *cgit_module_link; |
78 | extern char *cgit_virtual_root; | 78 | extern char *cgit_virtual_root; |
79 | extern char *cgit_script_name; | 79 | extern char *cgit_script_name; |
80 | extern char *cgit_cache_root; | 80 | extern char *cgit_cache_root; |
81 | 81 | ||
82 | extern int cgit_nocache; | 82 | extern int cgit_nocache; |
83 | extern int cgit_snapshots; | 83 | extern int cgit_snapshots; |
84 | extern int cgit_max_lock_attempts; | 84 | extern int cgit_max_lock_attempts; |
85 | extern int cgit_cache_root_ttl; | 85 | extern int cgit_cache_root_ttl; |
86 | extern int cgit_cache_repo_ttl; | 86 | extern int cgit_cache_repo_ttl; |
87 | extern int cgit_cache_dynamic_ttl; | 87 | extern int cgit_cache_dynamic_ttl; |
88 | extern int cgit_cache_static_ttl; | 88 | extern int cgit_cache_static_ttl; |
89 | extern int cgit_cache_max_create_time; | 89 | extern int cgit_cache_max_create_time; |
90 | 90 | ||
91 | extern int cgit_max_msg_len; | 91 | extern int cgit_max_msg_len; |
92 | extern int cgit_max_commit_count; | 92 | extern int cgit_max_commit_count; |
93 | 93 | ||
94 | extern char *cgit_repo_name; | 94 | extern char *cgit_repo_name; |
95 | extern char *cgit_repo_desc; | 95 | extern char *cgit_repo_desc; |
96 | extern char *cgit_repo_owner; | 96 | extern char *cgit_repo_owner; |
97 | 97 | ||
98 | extern int cgit_query_has_symref; | 98 | extern int cgit_query_has_symref; |
99 | extern int cgit_query_has_sha1; | 99 | extern int cgit_query_has_sha1; |
100 | 100 | ||
101 | extern char *cgit_querystring; | 101 | extern char *cgit_querystring; |
102 | extern char *cgit_query_repo; | 102 | extern char *cgit_query_repo; |
103 | extern char *cgit_query_page; | 103 | extern char *cgit_query_page; |
104 | extern char *cgit_query_search; | 104 | extern char *cgit_query_search; |
105 | extern char *cgit_query_head; | 105 | extern char *cgit_query_head; |
106 | extern char *cgit_query_sha1; | 106 | extern char *cgit_query_sha1; |
107 | extern char *cgit_query_sha2; | 107 | extern char *cgit_query_sha2; |
108 | extern char *cgit_query_path; | 108 | extern char *cgit_query_path; |
109 | extern char *cgit_query_name; | 109 | extern char *cgit_query_name; |
110 | extern int cgit_query_ofs; | 110 | extern int cgit_query_ofs; |
111 | 111 | ||
112 | extern int htmlfd; | 112 | extern int htmlfd; |
113 | 113 | ||
114 | extern void cgit_global_config_cb(const char *name, const char *value); | 114 | extern void cgit_global_config_cb(const char *name, const char *value); |
115 | extern void cgit_repo_config_cb(const char *name, const char *value); | 115 | extern void cgit_repo_config_cb(const char *name, const char *value); |
116 | extern void cgit_querystring_cb(const char *name, const char *value); | 116 | extern void cgit_querystring_cb(const char *name, const char *value); |
117 | 117 | ||
118 | extern int chk_zero(int result, char *msg); | 118 | extern int chk_zero(int result, char *msg); |
119 | extern int chk_positive(int result, char *msg); | 119 | extern int chk_positive(int result, char *msg); |
120 | 120 | ||
121 | extern int hextoint(char c); | 121 | extern int hextoint(char c); |
122 | 122 | ||
123 | extern void *cgit_free_commitinfo(struct commitinfo *info); | 123 | extern void *cgit_free_commitinfo(struct commitinfo *info); |
124 | 124 | ||
125 | extern int cgit_diff_files(const unsigned char *old_sha1, | 125 | extern 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 | ||
129 | extern void cgit_diff_tree(const unsigned char *old_sha1, | 129 | extern 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 | ||
133 | extern void cgit_diff_commit(struct commit *commit, filepair_fn fn); | 133 | extern void cgit_diff_commit(struct commit *commit, filepair_fn fn); |
134 | 134 | ||
135 | extern char *fmt(const char *format,...); | 135 | extern char *fmt(const char *format,...); |
136 | 136 | ||
137 | extern void html(const char *txt); | 137 | extern void html(const char *txt); |
138 | extern void htmlf(const char *format,...); | 138 | extern void htmlf(const char *format,...); |
139 | extern void html_txt(char *txt); | 139 | extern void html_txt(char *txt); |
140 | extern void html_ntxt(int len, char *txt); | 140 | extern void html_ntxt(int len, char *txt); |
141 | extern void html_attr(char *txt); | 141 | extern void html_attr(char *txt); |
142 | extern void html_hidden(char *name, char *value); | 142 | extern void html_hidden(char *name, char *value); |
143 | extern void html_link_open(char *url, char *title, char *class); | 143 | extern void html_link_open(char *url, char *title, char *class); |
144 | extern void html_link_close(void); | 144 | extern void html_link_close(void); |
145 | extern void html_filemode(unsigned short mode); | 145 | extern void html_filemode(unsigned short mode); |
146 | 146 | ||
147 | extern int cgit_read_config(const char *filename, configfn fn); | 147 | extern int cgit_read_config(const char *filename, configfn fn); |
148 | extern int cgit_parse_query(char *txt, configfn fn); | 148 | extern int cgit_parse_query(char *txt, configfn fn); |
149 | extern struct commitinfo *cgit_parse_commit(struct commit *commit); | 149 | extern struct commitinfo *cgit_parse_commit(struct commit *commit); |
150 | extern struct taginfo *cgit_parse_tag(struct tag *tag); | 150 | extern struct taginfo *cgit_parse_tag(struct tag *tag); |
151 | 151 | ||
152 | extern char *cache_safe_filename(const char *unsafe); | 152 | extern char *cache_safe_filename(const char *unsafe); |
153 | extern int cache_lock(struct cacheitem *item); | 153 | extern int cache_lock(struct cacheitem *item); |
154 | extern int cache_unlock(struct cacheitem *item); | 154 | extern int cache_unlock(struct cacheitem *item); |
155 | extern int cache_cancel_lock(struct cacheitem *item); | 155 | extern int cache_cancel_lock(struct cacheitem *item); |
156 | extern int cache_exist(struct cacheitem *item); | 156 | extern int cache_exist(struct cacheitem *item); |
157 | extern int cache_expired(struct cacheitem *item); | 157 | extern int cache_expired(struct cacheitem *item); |
158 | 158 | ||
159 | extern char *cgit_repourl(const char *reponame); | 159 | extern char *cgit_repourl(const char *reponame); |
160 | extern char *cgit_pageurl(const char *reponame, const char *pagename, | 160 | extern char *cgit_pageurl(const char *reponame, const char *pagename, |
161 | const char *query); | 161 | const char *query); |
162 | 162 | ||
163 | extern void cgit_print_error(char *msg); | 163 | extern void cgit_print_error(char *msg); |
164 | extern void cgit_print_date(unsigned long secs); | 164 | extern void cgit_print_date(unsigned long secs); |
165 | extern void cgit_print_docstart(char *title, struct cacheitem *item); | 165 | extern void cgit_print_docstart(char *title, struct cacheitem *item); |
166 | extern void cgit_print_docend(); | 166 | extern void cgit_print_docend(); |
167 | extern void cgit_print_pageheader(char *title, int show_search); | 167 | extern void cgit_print_pageheader(char *title, int show_search); |
168 | extern void cgit_print_snapshot_start(const char *mimetype, | 168 | extern 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 | ||
172 | extern void cgit_print_repolist(struct cacheitem *item); | 172 | extern void cgit_print_repolist(struct cacheitem *item); |
173 | extern void cgit_print_summary(); | 173 | extern void cgit_print_summary(); |
174 | extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *path); | 174 | extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *path); |
175 | extern void cgit_print_view(const char *hex, char *path); | 175 | extern void cgit_print_view(const char *hex, char *path); |
176 | extern void cgit_print_blob(struct cacheitem *item, const char *hex, char *path); | 176 | extern void cgit_print_blob(struct cacheitem *item, const char *hex, char *path); |
177 | extern void cgit_print_tree(const char *rev, const char *hex, char *path); | 177 | extern void cgit_print_tree(const char *rev, const char *hex, char *path); |
178 | extern void cgit_print_commit(const char *hex); | 178 | extern void cgit_print_commit(const char *hex); |
179 | extern void cgit_print_diff(const char *old_hex, const char *new_hex, char *path); | 179 | extern void cgit_print_diff(const char *head, const char *old_hex, const char *new_hex, |
180 | extern void cgit_print_snapshot(struct cacheitem *item, const char *hex, | 180 | char *path); |
181 | extern 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 */ |
@@ -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 | */ |
15 | static void print_line(char *line, int len) | 15 | static 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 | ||
34 | static void header(unsigned char *sha1, char *path1, | 34 | static 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 | ||
60 | static void filepair_cb(struct diff_filepair *pair) | 60 | static 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 | ||
69 | void cgit_print_diff(const char *old_hex, const char *new_hex, char *path) | 69 | void 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 | } |