summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2007-10-30 09:47:38 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2007-10-30 12:38:34 (UTC)
commit0c8e184e9cbf4d3a1e907de9125f6d8210c169d6 (patch) (unidiff)
tree2e82baf582b7ba0b34f498e1e7494800070067f9
parent10ac7ad1f30f914dc5ff36ba3651ef6dca11aaf7 (diff)
downloadcgit-0c8e184e9cbf4d3a1e907de9125f6d8210c169d6.zip
cgit-0c8e184e9cbf4d3a1e907de9125f6d8210c169d6.tar.gz
cgit-0c8e184e9cbf4d3a1e907de9125f6d8210c169d6.tar.bz2
Change the cgit layout
This modifies and hopefully improves the layout of all cgit pages: * Remove the header from all pages and replace it with a sidebar; most pages have sufficient width but many needs more height. * Add a dropdown-box to switch between branches, using a one-liner javascript to reload the current page in context of the selected branch. * Include refs found below refs/archives in the sidebar, appearing as a set of menuitems below a 'download' heading. * Include the brand new cgit logo Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.css149
-rw-r--r--cgit.h2
-rw-r--r--cgit.pngbin0 -> 3790 bytes
-rw-r--r--cgitrc9
-rw-r--r--shared.c31
-rw-r--r--ui-shared.c172
-rw-r--r--ui-summary.c65
7 files changed, 231 insertions, 197 deletions
diff --git a/cgit.css b/cgit.css
index 5d47099..6cf4517 100644
--- a/cgit.css
+++ b/cgit.css
@@ -1,217 +1,195 @@
1body {
2 font-family: arial, sans-serif;
3 font-size: 11pt;
4 color: black;
5 background: white;
6}
7
8body, table { 1body, table {
9 padding: 0em; 2 padding: 0em;
10 margin: 0em; 3 margin: 0em;
11} 4}
12 5
6body {
7 font-family: sans;
8 font-size: 10pt;
9 color: #333;
10 background: white;
11 padding-left: 4px;
12}
13
13table { 14table {
14 border-collapse: collapse; 15 border-collapse: collapse;
15} 16}
16 17
17h2 { 18h2 {
18 font-size: 120%; 19 font-size: 120%;
19 font-weight: bold; 20 font-weight: bold;
20 margin-top: 0em; 21 margin-top: 0em;
21 margin-bottom: 0.25em; 22 margin-bottom: 0.25em;
22} 23}
23 24
24h3 { 25h3 {
25 margin-top: 0em; 26 margin-top: 0em;
26 font-size: 100%; 27 font-size: 100%;
27 font-weight: normal; 28 font-weight: normal;
28} 29}
29 30
30h4 { 31h4 {
31 margin-top: 1.5em; 32 margin-top: 1.5em;
32 margin-bottom: 0.1em; 33 margin-bottom: 0.1em;
33 font-size: 100%; 34 font-size: 100%;
34 font-weight: bold; 35 font-weight: bold;
35} 36}
36 37
37a { 38a {
38 color: blue; 39 color: #600;
39 text-decoration: none; 40 text-decoration: none;
40} 41}
41 42
42a:hover { 43a:hover {
43 text-decoration: underline; 44 background-color: #ddd;
45 text-decoration: none;
44} 46}
45 47
46table.list { 48table.list {
47 border: none; 49 border: none;
48 border-collapse: collapse; 50 border-collapse: collapse;
49} 51}
50 52
51table.list tr { 53table.list tr {
52 background: white; 54 background: white;
53} 55}
54 56
55table.list tr:hover { 57table.list tr:hover {
56 background: #eee; 58 background: #f8f8f8;
57} 59}
58 60
59table.list tr.nohover:hover { 61table.list tr.nohover:hover {
60 background: white; 62 background: white;
61} 63}
62 64
63table.list th { 65table.list th {
64 font-weight: bold; 66 font-weight: bold;
65 border-bottom: solid 1px #777; 67 border-bottom: solid 1px #777;
66 padding: 0.1em 0.5em 0.1em 0.5em; 68 padding: 0.1em 0.5em 0.1em 0.5em;
67 vertical-align: baseline; 69 vertical-align: baseline;
68} 70}
69 71
70table.list td { 72table.list td {
71 border: none; 73 border: none;
72 padding: 0.1em 0.5em 0.1em 0.5em; 74 padding: 0.1em 0.5em 0.1em 0.5em;
73} 75}
74 76
75img { 77img {
76 border: none; 78 border: none;
77} 79}
78 80
79table#layout { 81div#sidebar {
80 width: 100%; 82 vertical-align: top;
81 border-collapse: collapse; 83 width: 162px;
82 margin: 0px; 84 padding: 0px 0px 0px 0px;
83} 85 margin: 4px;
84 86 float: left;
85td#header, td#logo {
86 color: #666;
87 background-color: #ddd;
88 border-bottom: solid 1px #000;
89}
90
91td#header {
92 font-size: 150%;
93 font-weight: bold;
94 padding: 0.2em 0.5em;
95 vertical-align: text-bottom;
96}
97
98td#header a {
99 color: #666;
100}
101
102td#header a:hover {
103 text-decoration: underline;
104} 87}
105 88
106td#logo { 89div#logo {
107 text-align: right; 90 margin: 0px;
108 vertical-align: middle; 91 padding: 4px 0px 4px 0px;
109 padding-right: 0.5em; 92 text-align: center;
93 background-color: #ccc;
94 border-top: solid 1px #eee;
95 border-left: solid 1px #eee;
96 border-right: solid 1px #aaa;
97 border-bottom: solid 1px #aaa;
110} 98}
111 99
112td#crumb, td#search { 100div#sidebar div.infobox {
113 color: #ccc; 101 margin: 0px 0px 0pax 0px;
114 border-top: solid 3px #555; 102 padding: 0.5em;
115 background-color: #666; 103 text-align: left;
116 border-bottom: solid 1px #333; 104 background-color: #ccc;
117 padding: 2px 1em; 105 border-top: solid 1px #eee;
106 border-left: solid 1px #eee;
107 border-right: solid 1px #aaa;
108 border-bottom: solid 1px #aaa;
118} 109}
119 110
120td#crumb { 111div#sidebar div.infobox h1 {
112 font-size: 11pt;
121 font-weight: bold; 113 font-weight: bold;
114 margin: 0px;
122} 115}
123 116
124td#crumb a { 117div#sidebar div.infobox a.menu {
125 color: #ccc; 118 display: block;
126 background-color: #666;
127 padding: 0em 0.5em 0em 0.5em;
128}
129
130td#crumb a:hover {
131 color: #666;
132 background-color: #ccc; 119 background-color: #ccc;
120 padding: 0.1em 0.5em;
133 text-decoration: none; 121 text-decoration: none;
134} 122}
135 123
136td#search { 124div#sidebar div.infobox a.menu:hover {
137 text-align: right; 125 background-color: #bbb;
138 vertical-align: middle; 126 text-decoration: none;
139 padding-right: 0.5em;
140}
141
142td#search form {
143 margin: 0px;
144 padding: 0px;
145} 127}
146 128
147td#search select { 129div#sidebar div.infobox select {
148 font-size: 9pt; 130 width: 100%;
131 border: solid 1px #aaa;
132 background-color: #bbb;
133 margin: 2px 0px 0px 0px;
149 padding: 0px; 134 padding: 0px;
150 border: solid 1px #333;
151 color: #333;
152 background-color: #fff;
153} 135}
154 136
155td#search input { 137div#sidebar div.infobox input.txt {
156 font-size: 9pt; 138 width: 100%;
157 padding: 0px; 139 border: solid 1px #aaa;
140 background-color: #bbb;
141 margin: 2px 0px 0px 0px;
142 padding: 0;
158} 143}
159 144
160td#search input.txt { 145table#grid {
161 width: 8em; 146 margin: 0px;
162 border: solid 1px #333;
163 color: #333;
164 background-color: #fff;
165} 147}
166 148
167td#search input.btn { 149td#content {
168 border: solid 1px #333; 150 vertical-align: top;
169 color: #333; 151 padding: 1em 2em 1em 1em;
170 background-color: #ccc; 152 border: none;
171} 153}
172 154
173div#summary { 155div#summary {
174 vertical-align: top; 156 vertical-align: top;
175 margin-bottom: 1em; 157 margin-bottom: 1em;
176} 158}
177 159
178table#downloads { 160table#downloads {
179 float: right; 161 float: right;
180 border-collapse: collapse; 162 border-collapse: collapse;
181 border: solid 1px #777; 163 border: solid 1px #777;
182 margin-left: 0.5em; 164 margin-left: 0.5em;
183 margin-bottom: 0.5em; 165 margin-bottom: 0.5em;
184} 166}
185 167
186table#downloads th { 168table#downloads th {
187 background-color: #ccc; 169 background-color: #ccc;
188} 170}
189 171
190td#content {
191 padding: 1em 0.5em;
192}
193
194div#blob { 172div#blob {
195 border: solid 1px black; 173 border: solid 1px black;
196} 174}
197 175
198div.error { 176div.error {
199 color: red; 177 color: red;
200 font-weight: bold; 178 font-weight: bold;
201 margin: 1em 2em; 179 margin: 1em 2em;
202} 180}
203 181
204a.ls-blob, a.ls-dir, a.ls-mod { 182a.ls-blob, a.ls-dir, a.ls-mod {
205 font-family: monospace; 183 font-family: monospace;
206} 184}
207 185
208td.ls-size { 186td.ls-size {
209 text-align: right; 187 text-align: right;
210} 188}
211 189
212td.ls-size { 190td.ls-size {
213 font-family: monospace; 191 font-family: monospace;
214} 192}
215 193
216td.ls-mode { 194td.ls-mode {
217 font-family: monospace; 195 font-family: monospace;
@@ -263,90 +241,89 @@ table.commit-info th {
263table.commit-info td { 241table.commit-info td {
264 font-weight: normal; 242 font-weight: normal;
265 padding: 0.1em 1em 0.1em 0.1em; 243 padding: 0.1em 1em 0.1em 0.1em;
266} 244}
267 245
268div.commit-subject { 246div.commit-subject {
269 font-weight: bold; 247 font-weight: bold;
270 font-size: 125%; 248 font-size: 125%;
271 margin: 1.5em 0em 0.5em 0em; 249 margin: 1.5em 0em 0.5em 0em;
272 padding: 0em; 250 padding: 0em;
273} 251}
274 252
275div.commit-msg { 253div.commit-msg {
276 white-space: pre; 254 white-space: pre;
277 font-family: monospace; 255 font-family: monospace;
278} 256}
279 257
280div.diffstat-header { 258div.diffstat-header {
281 font-weight: bold; 259 font-weight: bold;
282 padding-top: 1.5em; 260 padding-top: 1.5em;
283} 261}
284 262
285table.diffstat { 263table.diffstat {
286 border-collapse: collapse; 264 border-collapse: collapse;
287 width: 100%;
288 border: solid 1px #aaa; 265 border: solid 1px #aaa;
289 background-color: #eee; 266 background-color: #eee;
290} 267}
291 268
292table.diffstat th { 269table.diffstat th {
293 font-weight: normal; 270 font-weight: normal;
294 text-align: left; 271 text-align: left;
295 text-decoration: underline; 272 text-decoration: underline;
296 padding: 0.1em 1em 0.1em 0.1em; 273 padding: 0.1em 1em 0.1em 0.1em;
297 font-size: 100%; 274 font-size: 100%;
298} 275}
299 276
300table.diffstat td { 277table.diffstat td {
301 padding: 0.2em 0.2em 0.1em 0.1em; 278 padding: 0.2em 0.2em 0.1em 0.1em;
302 font-size: 100%; 279 font-size: 100%;
303 border: none; 280 border: none;
304} 281}
305 282
306table.diffstat td.mode { 283table.diffstat td.mode {
307 white-space: nowrap; 284 white-space: nowrap;
308} 285}
309 286
310table.diffstat td span.modechange { 287table.diffstat td span.modechange {
311 padding-left: 1em; 288 padding-left: 1em;
312 color: red; 289 color: red;
313} 290}
314 291
315table.diffstat td.add a { 292table.diffstat td.add a {
316 color: green; 293 color: green;
317} 294}
318 295
319table.diffstat td.del a { 296table.diffstat td.del a {
320 color: red; 297 color: red;
321} 298}
322 299
323table.diffstat td.upd a { 300table.diffstat td.upd a {
324 color: blue; 301 color: blue;
325} 302}
326 303
327table.diffstat td.graph { 304table.diffstat td.graph {
328 width: 75%; 305 width: 500px;
329 vertical-align: middle; 306 vertical-align: middle;
330} 307}
331 308
332table.diffstat td.graph table { 309table.diffstat td.graph table {
333 border: none; 310 border: none;
334} 311}
335 312
336table.diffstat td.graph td { 313table.diffstat td.graph td {
337 padding: 0px; 314 padding: 0px;
338 border: 0px; 315 border: 0px;
339 height: 7pt; 316 height: 7pt;
340} 317}
341 318
342table.diffstat td.graph td.add { 319table.diffstat td.graph td.add {
343 background-color: #5c5; 320 background-color: #5c5;
344} 321}
345 322
346table.diffstat td.graph td.rem { 323table.diffstat td.graph td.rem {
347 background-color: #c55; 324 background-color: #c55;
348} 325}
349 326
350div.diffstat-summary { 327div.diffstat-summary {
351 color: #888; 328 color: #888;
352 padding-top: 0.5em; 329 padding-top: 0.5em;
diff --git a/cgit.h b/cgit.h
index b8af970..42036c3 100644
--- a/cgit.h
+++ b/cgit.h
@@ -160,48 +160,50 @@ extern char *cgit_query_repo;
160extern char *cgit_query_page; 160extern char *cgit_query_page;
161extern char *cgit_query_search; 161extern char *cgit_query_search;
162extern char *cgit_query_grep; 162extern char *cgit_query_grep;
163extern char *cgit_query_head; 163extern char *cgit_query_head;
164extern char *cgit_query_sha1; 164extern char *cgit_query_sha1;
165extern char *cgit_query_sha2; 165extern char *cgit_query_sha2;
166extern char *cgit_query_path; 166extern char *cgit_query_path;
167extern char *cgit_query_name; 167extern char *cgit_query_name;
168extern int cgit_query_ofs; 168extern int cgit_query_ofs;
169 169
170extern int htmlfd; 170extern int htmlfd;
171 171
172extern int cgit_get_cmd_index(const char *cmd); 172extern int cgit_get_cmd_index(const char *cmd);
173extern struct repoinfo *cgit_get_repoinfo(const char *url); 173extern struct repoinfo *cgit_get_repoinfo(const char *url);
174extern void cgit_global_config_cb(const char *name, const char *value); 174extern void cgit_global_config_cb(const char *name, const char *value);
175extern void cgit_repo_config_cb(const char *name, const char *value); 175extern void cgit_repo_config_cb(const char *name, const char *value);
176extern void cgit_querystring_cb(const char *name, const char *value); 176extern void cgit_querystring_cb(const char *name, const char *value);
177 177
178extern int chk_zero(int result, char *msg); 178extern int chk_zero(int result, char *msg);
179extern int chk_positive(int result, char *msg); 179extern int chk_positive(int result, char *msg);
180extern int chk_non_negative(int result, char *msg); 180extern int chk_non_negative(int result, char *msg);
181 181
182extern int hextoint(char c); 182extern int hextoint(char c);
183extern char *trim_end(const char *str, char c); 183extern char *trim_end(const char *str, char c);
184extern char *strlpart(char *txt, int maxlen);
185extern char *strrpart(char *txt, int maxlen);
184 186
185extern void cgit_add_ref(struct reflist *list, struct refinfo *ref); 187extern void cgit_add_ref(struct reflist *list, struct refinfo *ref);
186extern int cgit_refs_cb(const char *refname, const unsigned char *sha1, 188extern int cgit_refs_cb(const char *refname, const unsigned char *sha1,
187 int flags, void *cb_data); 189 int flags, void *cb_data);
188 190
189extern void *cgit_free_commitinfo(struct commitinfo *info); 191extern void *cgit_free_commitinfo(struct commitinfo *info);
190 192
191extern int cgit_diff_files(const unsigned char *old_sha1, 193extern int cgit_diff_files(const unsigned char *old_sha1,
192 const unsigned char *new_sha1, 194 const unsigned char *new_sha1,
193 linediff_fn fn); 195 linediff_fn fn);
194 196
195extern void cgit_diff_tree(const unsigned char *old_sha1, 197extern void cgit_diff_tree(const unsigned char *old_sha1,
196 const unsigned char *new_sha1, 198 const unsigned char *new_sha1,
197 filepair_fn fn, const char *prefix); 199 filepair_fn fn, const char *prefix);
198 200
199extern void cgit_diff_commit(struct commit *commit, filepair_fn fn); 201extern void cgit_diff_commit(struct commit *commit, filepair_fn fn);
200 202
201extern char *fmt(const char *format,...); 203extern char *fmt(const char *format,...);
202 204
203extern void html(const char *txt); 205extern void html(const char *txt);
204extern void htmlf(const char *format,...); 206extern void htmlf(const char *format,...);
205extern void html_txt(char *txt); 207extern void html_txt(char *txt);
206extern void html_ntxt(int len, char *txt); 208extern void html_ntxt(int len, char *txt);
207extern void html_attr(char *txt); 209extern void html_attr(char *txt);
diff --git a/cgit.png b/cgit.png
new file mode 100644
index 0000000..ee48197
--- a/dev/null
+++ b/cgit.png
Binary files differ
diff --git a/cgitrc b/cgitrc
index 2b09e01..6363c9c 100644
--- a/cgitrc
+++ b/cgitrc
@@ -64,50 +64,55 @@
64## 64##
65## instead of 65## instead of
66## 66##
67## http://localhost/cgit/cgit.cgi?url=repo/log&h=branch 67## http://localhost/cgit/cgit.cgi?url=repo/log&h=branch
68## 68##
69## For this to work with apache, a rewrite rule must be added to httpd.conf, 69## For this to work with apache, a rewrite rule must be added to httpd.conf,
70## possibly looking something like this: 70## possibly looking something like this:
71## 71##
72## RewriteRule ^/git/(.*)$ /cgit/cgit.cgi?url=$1 [L,QSA] 72## RewriteRule ^/git/(.*)$ /cgit/cgit.cgi?url=$1 [L,QSA]
73## 73##
74## For this to work with lighttpd, the rewrite rule should look more like this: 74## For this to work with lighttpd, the rewrite rule should look more like this:
75## 75##
76## url.rewrite = ( 76## url.rewrite = (
77## "^/git/([^?/]+/[^?]*)?(?:\?(.*))?$" => "/cgit.cgi?url=$1&$2" 77## "^/git/([^?/]+/[^?]*)?(?:\?(.*))?$" => "/cgit.cgi?url=$1&$2"
78## ) 78## )
79## 79##
80## This setting is disabled by default. 80## This setting is disabled by default.
81#virtual-root=/git 81#virtual-root=/git
82 82
83 83
84## Set the title printed on the root page 84## Set the title printed on the root page
85#root-title=Git repository browser 85#root-title=Git repository browser
86 86
87 87
88## If specified, the file at this path will be included as HTML in the index 88## If specified, the file at this path will be included as HTML in the
89## of repositories 89## sidebar on the repository index page
90#index-info=
91
92
93## If specified, the file at this path will be included as HTML above
94## the repository index
90#index-header= 95#index-header=
91 96
92 97
93## Link to css file 98## Link to css file
94#css=/cgit/cgit.css 99#css=/cgit/cgit.css
95 100
96 101
97## Link to logo file 102## Link to logo file
98#logo=/cgit/git-logo.png 103#logo=/cgit/git-logo.png
99 104
100 105
101## Url loaded when clicking the logo 106## Url loaded when clicking the logo
102#logo-link=http://www.kernel.org/pub/software/scm/git/docs/ 107#logo-link=http://www.kernel.org/pub/software/scm/git/docs/
103 108
104 109
105## Url loaded when clicking a submodule link 110## Url loaded when clicking a submodule link
106#module-link=./?repo=%s&page=commit&id=%s 111#module-link=./?repo=%s&page=commit&id=%s
107 112
108 113
109## Number of chars shown of repo description (in repolist view) 114## Number of chars shown of repo description (in repolist view)
110#max-repodesc-length=60 115#max-repodesc-length=60
111 116
112 117
113## Number of chars shown of commit subject message (in log view) 118## Number of chars shown of commit subject message (in log view)
diff --git a/shared.c b/shared.c
index 50fe8e1..e06df91 100644
--- a/shared.c
+++ b/shared.c
@@ -282,48 +282,79 @@ int hextoint(char c)
282} 282}
283 283
284char *trim_end(const char *str, char c) 284char *trim_end(const char *str, char c)
285{ 285{
286 int len; 286 int len;
287 char *s, *t; 287 char *s, *t;
288 288
289 if (str == NULL) 289 if (str == NULL)
290 return NULL; 290 return NULL;
291 t = (char *)str; 291 t = (char *)str;
292 len = strlen(t); 292 len = strlen(t);
293 while(len > 0 && t[len - 1] == c) 293 while(len > 0 && t[len - 1] == c)
294 len--; 294 len--;
295 295
296 if (len == 0) 296 if (len == 0)
297 return NULL; 297 return NULL;
298 298
299 c = t[len]; 299 c = t[len];
300 t[len] = '\0'; 300 t[len] = '\0';
301 s = xstrdup(t); 301 s = xstrdup(t);
302 t[len] = c; 302 t[len] = c;
303 return s; 303 return s;
304} 304}
305 305
306char *strlpart(char *txt, int maxlen)
307{
308 char *result;
309
310 if (!txt)
311 return txt;
312
313 if (strlen(txt) <= maxlen)
314 return txt;
315 result = xmalloc(maxlen + 1);
316 memcpy(result, txt, maxlen - 3);
317 result[maxlen-1] = result[maxlen-2] = result[maxlen-3] = '.';
318 result[maxlen] = '\0';
319 return result;
320}
321
322char *strrpart(char *txt, int maxlen)
323{
324 char *result;
325
326 if (!txt)
327 return txt;
328
329 if (strlen(txt) <= maxlen)
330 return txt;
331 result = xmalloc(maxlen + 1);
332 memcpy(result + 3, txt + strlen(txt) - maxlen + 4, maxlen - 3);
333 result[0] = result[1] = result[2] = '.';
334 return result;
335}
336
306void cgit_add_ref(struct reflist *list, struct refinfo *ref) 337void cgit_add_ref(struct reflist *list, struct refinfo *ref)
307{ 338{
308 size_t size; 339 size_t size;
309 340
310 if (list->count >= list->alloc) { 341 if (list->count >= list->alloc) {
311 list->alloc += (list->alloc ? list->alloc : 4); 342 list->alloc += (list->alloc ? list->alloc : 4);
312 size = list->alloc * sizeof(struct refinfo *); 343 size = list->alloc * sizeof(struct refinfo *);
313 list->refs = xrealloc(list->refs, size); 344 list->refs = xrealloc(list->refs, size);
314 } 345 }
315 list->refs[list->count++] = ref; 346 list->refs[list->count++] = ref;
316} 347}
317 348
318struct refinfo *cgit_mk_refinfo(const char *refname, const unsigned char *sha1) 349struct refinfo *cgit_mk_refinfo(const char *refname, const unsigned char *sha1)
319{ 350{
320 struct refinfo *ref; 351 struct refinfo *ref;
321 352
322 ref = xmalloc(sizeof (struct refinfo)); 353 ref = xmalloc(sizeof (struct refinfo));
323 ref->refname = xstrdup(refname); 354 ref->refname = xstrdup(refname);
324 ref->object = parse_object(sha1); 355 ref->object = parse_object(sha1);
325 switch (ref->object->type) { 356 switch (ref->object->type) {
326 case OBJ_TAG: 357 case OBJ_TAG:
327 ref->tag = cgit_parse_tag((struct tag *)ref->object); 358 ref->tag = cgit_parse_tag((struct tag *)ref->object);
328 break; 359 break;
329 case OBJ_COMMIT: 360 case OBJ_COMMIT:
diff --git a/ui-shared.c b/ui-shared.c
index 1418010..1d66940 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -341,107 +341,179 @@ void cgit_print_age(time_t t, time_t max_relative, char *format)
341 341
342void cgit_print_docstart(char *title, struct cacheitem *item) 342void cgit_print_docstart(char *title, struct cacheitem *item)
343{ 343{
344 html("Content-Type: text/html; charset=utf-8\n"); 344 html("Content-Type: text/html; charset=utf-8\n");
345 htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime)); 345 htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime));
346 htmlf("Expires: %s\n", http_date(item->st.st_mtime + 346 htmlf("Expires: %s\n", http_date(item->st.st_mtime +
347 ttl_seconds(item->ttl))); 347 ttl_seconds(item->ttl)));
348 html("\n"); 348 html("\n");
349 html(cgit_doctype); 349 html(cgit_doctype);
350 html("<html>\n"); 350 html("<html>\n");
351 html("<head>\n"); 351 html("<head>\n");
352 html("<title>"); 352 html("<title>");
353 html_txt(title); 353 html_txt(title);
354 html("</title>\n"); 354 html("</title>\n");
355 htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version); 355 htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version);
356 html("<link rel='stylesheet' type='text/css' href='"); 356 html("<link rel='stylesheet' type='text/css' href='");
357 html_attr(cgit_css); 357 html_attr(cgit_css);
358 html("'/>\n"); 358 html("'/>\n");
359 html("</head>\n"); 359 html("</head>\n");
360 html("<body>\n"); 360 html("<body>\n");
361} 361}
362 362
363void cgit_print_docend() 363void cgit_print_docend()
364{ 364{
365 html("</td></tr></table>"); 365 html("</td>\n</tr>\n<table>\n</body>\n</html>\n");
366 html("</body>\n</html>\n"); 366}
367
368int print_branch_option(const char *refname, const unsigned char *sha1,
369 int flags, void *cb_data)
370{
371 char *name = (char *)refname;
372 html_option(name, name, cgit_query_head);
373 return 0;
374}
375
376int print_archive_ref(const char *refname, const unsigned char *sha1,
377 int flags, void *cb_data)
378{
379 struct tag *tag;
380 struct taginfo *info;
381 struct object *obj;
382 char buf[256], *url;
383 unsigned char fileid[20];
384 int *header = (int *)cb_data;
385
386 if (prefixcmp(refname, "refs/archives"))
387 return 0;
388 strncpy(buf, refname+14, sizeof(buf));
389 obj = parse_object(sha1);
390 if (!obj)
391 return 1;
392 if (obj->type == OBJ_TAG) {
393 tag = lookup_tag(sha1);
394 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag)))
395 return 0;
396 hashcpy(fileid, tag->tagged->sha1);
397 } else if (obj->type != OBJ_BLOB) {
398 return 0;
399 } else {
400 hashcpy(fileid, sha1);
401 }
402 if (!*header) {
403 html("<p><h1>download</h1>");
404 *header = 1;
405 }
406 url = cgit_pageurl(cgit_query_repo, "blob",
407 fmt("id=%s&amp;path=%s", sha1_to_hex(fileid),
408 buf));
409 html_link_open(url, NULL, "menu");
410 html_txt(strlpart(buf, 20));
411 html_link_close();
412 return 0;
413}
414
415void add_hidden_formfields(int incl_head, int incl_search)
416{
417 if (!cgit_virtual_root) {
418 if (cgit_query_repo)
419 html_hidden("r", cgit_query_repo);
420 if (cgit_query_page)
421 html_hidden("p", cgit_query_page);
422 }
423
424 if (incl_head && strcmp(cgit_query_head, cgit_repo->defbranch))
425 html_hidden("h", cgit_query_head);
426
427 if (cgit_query_sha1)
428 html_hidden("id", cgit_query_sha1);
429 if (cgit_query_sha2)
430 html_hidden("id2", cgit_query_sha2);
431
432 if (incl_search) {
433 if (cgit_query_grep)
434 html_hidden("qt", cgit_query_grep);
435 if (cgit_query_search)
436 html_hidden("q", cgit_query_search);
437 }
367} 438}
368 439
369void cgit_print_pageheader(char *title, int show_search) 440void cgit_print_pageheader(char *title, int show_search)
370{ 441{
371 html("<table id='layout'>"); 442 static const char *default_info = "This is cgit, a fast webinterface for git repositories";
372 html("<tr><td id='header'><a href='"); 443 int header = 0;
373 html_attr(cgit_rooturl()); 444
374 html("'>"); 445 html("<div id='sidebar'>\n");
375 html_txt(cgit_root_title);
376 html("</a></td><td id='logo'>");
377 html("<a href='"); 446 html("<a href='");
378 html_attr(cgit_logo_link); 447 html_attr(cgit_rooturl());
379 htmlf("'><img src='%s' alt='logo'/></a>", cgit_logo); 448 htmlf("'><div id='logo'><img src='%s' alt='cgit'/></div></a>\n",
380 html("</td></tr>"); 449 cgit_logo);
381 html("<tr><td id='crumb'>"); 450 html("<div class='infobox'>");
382 if (cgit_query_repo) { 451 if (cgit_query_repo) {
383 html_txt(cgit_repo->name); 452 html("<h1>");
384 html(" ("); 453 html_txt(strrpart(cgit_repo->name, 20));
385 html_txt(cgit_query_head); 454 html("</h1>\n");
386 html(") : &nbsp;"); 455 html_txt(cgit_repo->desc);
387 reporevlink(NULL, "summary", NULL, NULL, cgit_query_head, 456 if (cgit_repo->owner) {
457 html("<p>\n<h1>owner</h1>\n");
458 html_txt(cgit_repo->owner);
459 }
460 html("<p>\n<h1>navigate</h1>\n");
461 reporevlink(NULL, "summary", NULL, "menu", cgit_query_head,
388 NULL, NULL); 462 NULL, NULL);
389 html(" "); 463 cgit_log_link("log", NULL, "menu", cgit_query_head,
390 cgit_log_link("log", NULL, NULL, cgit_query_head,
391 cgit_query_sha1, cgit_query_path, 0); 464 cgit_query_sha1, cgit_query_path, 0);
392 html(" "); 465 cgit_tree_link("tree", NULL, "menu", cgit_query_head,
393 cgit_tree_link("tree", NULL, NULL, cgit_query_head,
394 cgit_query_sha1, NULL); 466 cgit_query_sha1, NULL);
395 html(" "); 467 cgit_commit_link("commit", NULL, "menu", cgit_query_head,
396 cgit_commit_link("commit", NULL, NULL, cgit_query_head,
397 cgit_query_sha1); 468 cgit_query_sha1);
398 html(" "); 469 cgit_diff_link("diff", NULL, "menu", cgit_query_head,
399 cgit_diff_link("diff", NULL, NULL, cgit_query_head,
400 cgit_query_sha1, cgit_query_sha2, 470 cgit_query_sha1, cgit_query_sha2,
401 cgit_query_path); 471 cgit_query_path);
402 } else { 472
403 html_txt("Index of repositories"); 473 for_each_ref(print_archive_ref, &header);
404 } 474
405 html("</td>"); 475 html("<p>\n<h1>branch</h1>\n");
406 html("<td id='search'>"); 476 html("<form method='get' action=''>\n");
407 if (show_search) { 477 add_hidden_formfields(0, 1);
478 html("<select name='h' onchange='this.form.submit();'>\n");
479 for_each_branch_ref(print_branch_option, cgit_query_head);
480 html("</select>\n");
481 html("</form>\n");
482
483 html("<p>\n<h1>search</h1>\n");
408 html("<form method='get' action='"); 484 html("<form method='get' action='");
409 html_attr(cgit_currurl()); 485 html_attr(cgit_pageurl(cgit_query_repo, "log", NULL));
410 html("'>"); 486 html("'>\n");
411 if (!cgit_virtual_root) { 487 add_hidden_formfields(1, 0);
412 if (cgit_query_repo) 488 html("<select name='qt'>\n");
413 html_hidden("r", cgit_query_repo);
414 if (cgit_query_page)
415 html_hidden("p", cgit_query_page);
416 }
417 if (cgit_query_head)
418 html_hidden("h", cgit_query_head);
419 if (cgit_query_sha1)
420 html_hidden("id", cgit_query_sha1);
421 if (cgit_query_sha2)
422 html_hidden("id2", cgit_query_sha2);
423 html("<select name='qt'>");
424 html_option("grep", "log msg", cgit_query_grep); 489 html_option("grep", "log msg", cgit_query_grep);
425 html_option("author", "author", cgit_query_grep); 490 html_option("author", "author", cgit_query_grep);
426 html_option("committer", "committer", cgit_query_grep); 491 html_option("committer", "committer", cgit_query_grep);
427 html("</select>"); 492 html("</select>\n");
428 html("<input class='txt' type='text' name='q' value='"); 493 html("<input class='txt' type='text' name='q' value='");
429 html_attr(cgit_query_search); 494 html_attr(cgit_query_search);
430 html("'/><input class='btn' type='submit' value='...'/></form>"); 495 html("'/>\n");
496 html("</form>\n");
497 } else {
498 if (!cgit_index_info || html_include(cgit_index_info))
499 html(default_info);
431 } 500 }
432 html("</td></tr>"); 501
433 html("<tr><td id='content' colspan='2'>"); 502 html("</div>\n");
503
504 html("</div>\n<table class='grid'><tr><td id='content'>\n");
434} 505}
435 506
507
436void cgit_print_snapshot_start(const char *mimetype, const char *filename, 508void cgit_print_snapshot_start(const char *mimetype, const char *filename,
437 struct cacheitem *item) 509 struct cacheitem *item)
438{ 510{
439 htmlf("Content-Type: %s\n", mimetype); 511 htmlf("Content-Type: %s\n", mimetype);
440 htmlf("Content-Disposition: inline; filename=\"%s\"\n", filename); 512 htmlf("Content-Disposition: inline; filename=\"%s\"\n", filename);
441 htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime)); 513 htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime));
442 htmlf("Expires: %s\n", http_date(item->st.st_mtime + 514 htmlf("Expires: %s\n", http_date(item->st.st_mtime +
443 ttl_seconds(item->ttl))); 515 ttl_seconds(item->ttl)));
444 html("\n"); 516 html("\n");
445} 517}
446 518
447/* vim:set sw=8: */ 519/* vim:set sw=8: */
diff --git a/ui-summary.c b/ui-summary.c
index ba90510..39fe330 100644
--- a/ui-summary.c
+++ b/ui-summary.c
@@ -99,89 +99,48 @@ static int print_tag(struct refinfo *ref)
99 html_link_open(url, NULL, NULL); 99 html_link_open(url, NULL, NULL);
100 html_txt(name); 100 html_txt(name);
101 html_link_close(); 101 html_link_close();
102 html("</td><td>"); 102 html("</td><td>");
103 if (info->tagger_date > 0) 103 if (info->tagger_date > 0)
104 cgit_print_age(info->tagger_date, -1, NULL); 104 cgit_print_age(info->tagger_date, -1, NULL);
105 html("</td><td>"); 105 html("</td><td>");
106 if (info->tagger) 106 if (info->tagger)
107 html(info->tagger); 107 html(info->tagger);
108 html("</td><td>"); 108 html("</td><td>");
109 cgit_object_link(tag->tagged); 109 cgit_object_link(tag->tagged);
110 html("</td></tr>\n"); 110 html("</td></tr>\n");
111 } else { 111 } else {
112 if (!header) 112 if (!header)
113 print_tag_header(); 113 print_tag_header();
114 html("<tr><td>"); 114 html("<tr><td>");
115 html_txt(name); 115 html_txt(name);
116 html("</td><td colspan='2'/><td>"); 116 html("</td><td colspan='2'/><td>");
117 cgit_object_link(ref->object); 117 cgit_object_link(ref->object);
118 html("</td></tr>\n"); 118 html("</td></tr>\n");
119 } 119 }
120 return 0; 120 return 0;
121} 121}
122 122
123static int cgit_print_archive_cb(const char *refname, const unsigned char *sha1,
124 int flags, void *cb_data)
125{
126 struct tag *tag;
127 struct taginfo *info;
128 struct object *obj;
129 char buf[256], *url;
130 unsigned char fileid[20];
131
132 if (prefixcmp(refname, "refs/archives"))
133 return 0;
134 strncpy(buf, refname+14, sizeof(buf));
135 obj = parse_object(sha1);
136 if (!obj)
137 return 1;
138 if (obj->type == OBJ_TAG) {
139 tag = lookup_tag(sha1);
140 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag)))
141 return 0;
142 hashcpy(fileid, tag->tagged->sha1);
143 } else if (obj->type != OBJ_BLOB) {
144 return 0;
145 } else {
146 hashcpy(fileid, sha1);
147 }
148 if (!header) {
149 html("<table id='downloads'>");
150 html("<tr><th>Downloads</th></tr>");
151 header = 1;
152 }
153 html("<tr><td>");
154 url = cgit_pageurl(cgit_query_repo, "blob",
155 fmt("id=%s&amp;path=%s", sha1_to_hex(fileid),
156 buf));
157 html_link_open(url, NULL, NULL);
158 html_txt(buf);
159 html_link_close();
160 html("</td></tr>");
161 return 0;
162}
163
164static void print_refs_link(char *path) 123static void print_refs_link(char *path)
165{ 124{
166 html("<tr class='nohover'><td colspan='4'>"); 125 html("<tr class='nohover'><td colspan='4'>");
167 cgit_refs_link("[...]", NULL, NULL, cgit_query_head, NULL, path); 126 cgit_refs_link("[...]", NULL, NULL, cgit_query_head, NULL, path);
168 html("</td></tr>"); 127 html("</td></tr>");
169} 128}
170 129
171void cgit_print_branches(int maxcount) 130void cgit_print_branches(int maxcount)
172{ 131{
173 struct reflist list; 132 struct reflist list;
174 int i; 133 int i;
175 134
176 html("<tr class='nohover'><th class='left'>Branch</th>" 135 html("<tr class='nohover'><th class='left'>Branch</th>"
177 "<th class='left'>Idle</th>" 136 "<th class='left'>Idle</th>"
178 "<th class='left'>Author</th>" 137 "<th class='left'>Author</th>"
179 "<th class='left'>Head commit</th></tr>\n"); 138 "<th class='left'>Head commit</th></tr>\n");
180 139
181 list.refs = NULL; 140 list.refs = NULL;
182 list.alloc = list.count = 0; 141 list.alloc = list.count = 0;
183 for_each_branch_ref(cgit_refs_cb, &list); 142 for_each_branch_ref(cgit_refs_cb, &list);
184 143
185 if (maxcount == 0 || maxcount > list.count) 144 if (maxcount == 0 || maxcount > list.count)
186 maxcount = list.count; 145 maxcount = list.count;
187 146
@@ -200,54 +159,42 @@ void cgit_print_branches(int maxcount)
200void cgit_print_tags(int maxcount) 159void cgit_print_tags(int maxcount)
201{ 160{
202 struct reflist list; 161 struct reflist list;
203 int i; 162 int i;
204 163
205 header = 0; 164 header = 0;
206 list.refs = NULL; 165 list.refs = NULL;
207 list.alloc = list.count = 0; 166 list.alloc = list.count = 0;
208 for_each_tag_ref(cgit_refs_cb, &list); 167 for_each_tag_ref(cgit_refs_cb, &list);
209 if (list.count == 0) 168 if (list.count == 0)
210 return; 169 return;
211 qsort(list.refs, list.count, sizeof(*list.refs), cmp_tag_age); 170 qsort(list.refs, list.count, sizeof(*list.refs), cmp_tag_age);
212 if (!maxcount) 171 if (!maxcount)
213 maxcount = list.count; 172 maxcount = list.count;
214 else if (maxcount > list.count) 173 else if (maxcount > list.count)
215 maxcount = list.count; 174 maxcount = list.count;
216 print_tag_header(); 175 print_tag_header();
217 for(i=0; i<maxcount; i++) 176 for(i=0; i<maxcount; i++)
218 print_tag(list.refs[i]); 177 print_tag(list.refs[i]);
219 178
220 if (maxcount < list.count) 179 if (maxcount < list.count)
221 print_refs_link("tags"); 180 print_refs_link("tags");
222} 181}
223 182
224static void cgit_print_archives()
225{
226 header = 0;
227 for_each_ref(cgit_print_archive_cb, NULL);
228 if (header)
229 html("</table>");
230}
231
232void cgit_print_summary() 183void cgit_print_summary()
233{ 184{
234 html("<div id='summary'>"); 185 if (cgit_repo->readme) {
235 cgit_print_archives(); 186 html("<div id='summary'>");
236 html("<h2>");
237 html_txt(cgit_repo->name);
238 html(" - ");
239 html_txt(cgit_repo->desc);
240 html("</h2>");
241 if (cgit_repo->readme)
242 html_include(cgit_repo->readme); 187 html_include(cgit_repo->readme);
243 html("</div>"); 188 html("</div>");
189 }
244 if (cgit_summary_log > 0) 190 if (cgit_summary_log > 0)
245 cgit_print_log(cgit_query_head, 0, cgit_summary_log, NULL, NULL, NULL, 0); 191 cgit_print_log(cgit_query_head, 0, cgit_summary_log, NULL,
192 NULL, NULL, 0);
246 html("<table class='list nowrap'>"); 193 html("<table class='list nowrap'>");
247 if (cgit_summary_log > 0) 194 if (cgit_summary_log > 0)
248 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>"); 195 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>");
249 cgit_print_branches(cgit_summary_branches); 196 cgit_print_branches(cgit_summary_branches);
250 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>"); 197 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>");
251 cgit_print_tags(cgit_summary_tags); 198 cgit_print_tags(cgit_summary_tags);
252 html("</table>"); 199 html("</table>");
253} 200}