summaryrefslogtreecommitdiffabout
path: root/ui-tree.c
Unidiff
Diffstat (limited to 'ui-tree.c') (more/less context) (ignore whitespace changes)
-rw-r--r--ui-tree.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/ui-tree.c b/ui-tree.c
index 816e121..caf6a9e 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -1,272 +1,272 @@
1/* ui-tree.c: functions for tree output 1/* ui-tree.c: functions for tree output
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 <ctype.h> 9#include <ctype.h>
10#include "cgit.h" 10#include "cgit.h"
11#include "html.h" 11#include "html.h"
12#include "ui-shared.h" 12#include "ui-shared.h"
13 13
14char *curr_rev; 14char *curr_rev;
15char *match_path; 15char *match_path;
16int header = 0; 16int header = 0;
17 17
18static void print_text_buffer(const char *name, char *buf, unsigned long size) 18static void print_text_buffer(const char *name, char *buf, unsigned long size)
19{ 19{
20 unsigned long lineno, idx; 20 unsigned long lineno, idx;
21 const char *numberfmt = 21 const char *numberfmt =
22 "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n"; 22 "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n";
23 23
24 html("<table summary='blob content' class='blob'>\n"); 24 html("<table summary='blob content' class='blob'>\n");
25 if (ctx.cfg.source_filter) { 25 if (ctx.repo->source_filter) {
26 html("<tr><td class='lines'><pre><code>"); 26 html("<tr><td class='lines'><pre><code>");
27 ctx.cfg.source_filter->argv[1] = xstrdup(name); 27 ctx.repo->source_filter->argv[1] = xstrdup(name);
28 cgit_open_filter(ctx.cfg.source_filter); 28 cgit_open_filter(ctx.repo->source_filter);
29 write(STDOUT_FILENO, buf, size); 29 write(STDOUT_FILENO, buf, size);
30 cgit_close_filter(ctx.cfg.source_filter); 30 cgit_close_filter(ctx.repo->source_filter);
31 html("</code></pre></td></tr></table>\n"); 31 html("</code></pre></td></tr></table>\n");
32 return; 32 return;
33 } 33 }
34 34
35 html("<tr><td class='linenumbers'><pre>"); 35 html("<tr><td class='linenumbers'><pre>");
36 idx = 0; 36 idx = 0;
37 lineno = 0; 37 lineno = 0;
38 38
39 if (size) { 39 if (size) {
40 htmlf(numberfmt, ++lineno); 40 htmlf(numberfmt, ++lineno);
41 while(idx < size - 1) { // skip absolute last newline 41 while(idx < size - 1) { // skip absolute last newline
42 if (buf[idx] == '\n') 42 if (buf[idx] == '\n')
43 htmlf(numberfmt, ++lineno); 43 htmlf(numberfmt, ++lineno);
44 idx++; 44 idx++;
45 } 45 }
46 } 46 }
47 html("</pre></td>\n"); 47 html("</pre></td>\n");
48 html("<td class='lines'><pre><code>"); 48 html("<td class='lines'><pre><code>");
49 html_txt(buf); 49 html_txt(buf);
50 html("</code></pre></td></tr></table>\n"); 50 html("</code></pre></td></tr></table>\n");
51} 51}
52 52
53#define ROWLEN 32 53#define ROWLEN 32
54 54
55static void print_binary_buffer(char *buf, unsigned long size) 55static void print_binary_buffer(char *buf, unsigned long size)
56{ 56{
57 unsigned long ofs, idx; 57 unsigned long ofs, idx;
58 static char ascii[ROWLEN + 1]; 58 static char ascii[ROWLEN + 1];
59 59
60 html("<table summary='blob content' class='bin-blob'>\n"); 60 html("<table summary='blob content' class='bin-blob'>\n");
61 html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>"); 61 html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>");
62 for (ofs = 0; ofs < size; ofs += ROWLEN, buf += ROWLEN) { 62 for (ofs = 0; ofs < size; ofs += ROWLEN, buf += ROWLEN) {
63 htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs); 63 htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs);
64 for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) 64 for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++)
65 htmlf("%*s%02x", 65 htmlf("%*s%02x",
66 idx == 16 ? 4 : 1, "", 66 idx == 16 ? 4 : 1, "",
67 buf[idx] & 0xff); 67 buf[idx] & 0xff);
68 html(" </td><td class='hex'>"); 68 html(" </td><td class='hex'>");
69 for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) 69 for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++)
70 ascii[idx] = isgraph(buf[idx]) ? buf[idx] : '.'; 70 ascii[idx] = isgraph(buf[idx]) ? buf[idx] : '.';
71 ascii[idx] = '\0'; 71 ascii[idx] = '\0';
72 html_txt(ascii); 72 html_txt(ascii);
73 html("</td></tr>\n"); 73 html("</td></tr>\n");
74 } 74 }
75 html("</table>\n"); 75 html("</table>\n");
76} 76}
77 77
78static void print_object(const unsigned char *sha1, char *path, const char *basename) 78static void print_object(const unsigned char *sha1, char *path, const char *basename)
79{ 79{
80 enum object_type type; 80 enum object_type type;
81 char *buf; 81 char *buf;
82 unsigned long size; 82 unsigned long size;
83 83
84 type = sha1_object_info(sha1, &size); 84 type = sha1_object_info(sha1, &size);
85 if (type == OBJ_BAD) { 85 if (type == OBJ_BAD) {
86 cgit_print_error(fmt("Bad object name: %s", 86 cgit_print_error(fmt("Bad object name: %s",
87 sha1_to_hex(sha1))); 87 sha1_to_hex(sha1)));
88 return; 88 return;
89 } 89 }
90 90
91 buf = read_sha1_file(sha1, &type, &size); 91 buf = read_sha1_file(sha1, &type, &size);
92 if (!buf) { 92 if (!buf) {
93 cgit_print_error(fmt("Error reading object %s", 93 cgit_print_error(fmt("Error reading object %s",
94 sha1_to_hex(sha1))); 94 sha1_to_hex(sha1)));
95 return; 95 return;
96 } 96 }
97 97
98 html(" ("); 98 html(" (");
99 cgit_plain_link("plain", NULL, NULL, ctx.qry.head, 99 cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
100 curr_rev, path); 100 curr_rev, path);
101 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1)); 101 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1));
102 102
103 if (buffer_is_binary(buf, size)) 103 if (buffer_is_binary(buf, size))
104 print_binary_buffer(buf, size); 104 print_binary_buffer(buf, size);
105 else 105 else
106 print_text_buffer(basename, buf, size); 106 print_text_buffer(basename, buf, size);
107} 107}
108 108
109 109
110static int ls_item(const unsigned char *sha1, const char *base, int baselen, 110static int ls_item(const unsigned char *sha1, const char *base, int baselen,
111 const char *pathname, unsigned int mode, int stage, 111 const char *pathname, unsigned int mode, int stage,
112 void *cbdata) 112 void *cbdata)
113{ 113{
114 char *name; 114 char *name;
115 char *fullpath; 115 char *fullpath;
116 enum object_type type; 116 enum object_type type;
117 unsigned long size = 0; 117 unsigned long size = 0;
118 118
119 name = xstrdup(pathname); 119 name = xstrdup(pathname);
120 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", 120 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "",
121 ctx.qry.path ? "/" : "", name); 121 ctx.qry.path ? "/" : "", name);
122 122
123 if (!S_ISGITLINK(mode)) { 123 if (!S_ISGITLINK(mode)) {
124 type = sha1_object_info(sha1, &size); 124 type = sha1_object_info(sha1, &size);
125 if (type == OBJ_BAD) { 125 if (type == OBJ_BAD) {
126 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", 126 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>",
127 name, 127 name,
128 sha1_to_hex(sha1)); 128 sha1_to_hex(sha1));
129 return 0; 129 return 0;
130 } 130 }
131 } 131 }
132 132
133 html("<tr><td class='ls-mode'>"); 133 html("<tr><td class='ls-mode'>");
134 cgit_print_filemode(mode); 134 cgit_print_filemode(mode);
135 html("</td><td>"); 135 html("</td><td>");
136 if (S_ISGITLINK(mode)) { 136 if (S_ISGITLINK(mode)) {
137 htmlf("<a class='ls-mod' href='"); 137 htmlf("<a class='ls-mod' href='");
138 html_attr(fmt(ctx.repo->module_link, 138 html_attr(fmt(ctx.repo->module_link,
139 name, 139 name,
140 sha1_to_hex(sha1))); 140 sha1_to_hex(sha1)));
141 html("'>"); 141 html("'>");
142 html_txt(name); 142 html_txt(name);
143 html("</a>"); 143 html("</a>");
144 } else if (S_ISDIR(mode)) { 144 } else if (S_ISDIR(mode)) {
145 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, 145 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head,
146 curr_rev, fullpath); 146 curr_rev, fullpath);
147 } else { 147 } else {
148 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head, 148 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head,
149 curr_rev, fullpath); 149 curr_rev, fullpath);
150 } 150 }
151 htmlf("</td><td class='ls-size'>%li</td>", size); 151 htmlf("</td><td class='ls-size'>%li</td>", size);
152 152
153 html("<td>"); 153 html("<td>");
154 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, 154 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev,
155 fullpath, 0, NULL, NULL, ctx.qry.showmsg); 155 fullpath, 0, NULL, NULL, ctx.qry.showmsg);
156 if (ctx.repo->max_stats) 156 if (ctx.repo->max_stats)
157 cgit_stats_link("stats", NULL, "button", ctx.qry.head, 157 cgit_stats_link("stats", NULL, "button", ctx.qry.head,
158 fullpath); 158 fullpath);
159 html("</td></tr>\n"); 159 html("</td></tr>\n");
160 free(name); 160 free(name);
161 return 0; 161 return 0;
162} 162}
163 163
164static void ls_head() 164static void ls_head()
165{ 165{
166 html("<table summary='tree listing' class='list'>\n"); 166 html("<table summary='tree listing' class='list'>\n");
167 html("<tr class='nohover'>"); 167 html("<tr class='nohover'>");
168 html("<th class='left'>Mode</th>"); 168 html("<th class='left'>Mode</th>");
169 html("<th class='left'>Name</th>"); 169 html("<th class='left'>Name</th>");
170 html("<th class='right'>Size</th>"); 170 html("<th class='right'>Size</th>");
171 html("<th/>"); 171 html("<th/>");
172 html("</tr>\n"); 172 html("</tr>\n");
173 header = 1; 173 header = 1;
174} 174}
175 175
176static void ls_tail() 176static void ls_tail()
177{ 177{
178 if (!header) 178 if (!header)
179 return; 179 return;
180 html("</table>\n"); 180 html("</table>\n");
181 header = 0; 181 header = 0;
182} 182}
183 183
184static void ls_tree(const unsigned char *sha1, char *path) 184static void ls_tree(const unsigned char *sha1, char *path)
185{ 185{
186 struct tree *tree; 186 struct tree *tree;
187 187
188 tree = parse_tree_indirect(sha1); 188 tree = parse_tree_indirect(sha1);
189 if (!tree) { 189 if (!tree) {
190 cgit_print_error(fmt("Not a tree object: %s", 190 cgit_print_error(fmt("Not a tree object: %s",
191 sha1_to_hex(sha1))); 191 sha1_to_hex(sha1)));
192 return; 192 return;
193 } 193 }
194 194
195 ls_head(); 195 ls_head();
196 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL); 196 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL);
197 ls_tail(); 197 ls_tail();
198} 198}
199 199
200 200
201static int walk_tree(const unsigned char *sha1, const char *base, int baselen, 201static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
202 const char *pathname, unsigned mode, int stage, 202 const char *pathname, unsigned mode, int stage,
203 void *cbdata) 203 void *cbdata)
204{ 204{
205 static int state; 205 static int state;
206 static char buffer[PATH_MAX]; 206 static char buffer[PATH_MAX];
207 char *url; 207 char *url;
208 208
209 if (state == 0) { 209 if (state == 0) {
210 memcpy(buffer, base, baselen); 210 memcpy(buffer, base, baselen);
211 strcpy(buffer+baselen, pathname); 211 strcpy(buffer+baselen, pathname);
212 url = cgit_pageurl(ctx.qry.repo, "tree", 212 url = cgit_pageurl(ctx.qry.repo, "tree",
213 fmt("h=%s&amp;path=%s", curr_rev, buffer)); 213 fmt("h=%s&amp;path=%s", curr_rev, buffer));
214 html("/"); 214 html("/");
215 cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head, 215 cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head,
216 curr_rev, buffer); 216 curr_rev, buffer);
217 217
218 if (strcmp(match_path, buffer)) 218 if (strcmp(match_path, buffer))
219 return READ_TREE_RECURSIVE; 219 return READ_TREE_RECURSIVE;
220 220
221 if (S_ISDIR(mode)) { 221 if (S_ISDIR(mode)) {
222 state = 1; 222 state = 1;
223 ls_head(); 223 ls_head();
224 return READ_TREE_RECURSIVE; 224 return READ_TREE_RECURSIVE;
225 } else { 225 } else {
226 print_object(sha1, buffer, pathname); 226 print_object(sha1, buffer, pathname);
227 return 0; 227 return 0;
228 } 228 }
229 } 229 }
230 ls_item(sha1, base, baselen, pathname, mode, stage, NULL); 230 ls_item(sha1, base, baselen, pathname, mode, stage, NULL);
231 return 0; 231 return 0;
232} 232}
233 233
234 234
235/* 235/*
236 * Show a tree or a blob 236 * Show a tree or a blob
237 * rev: the commit pointing at the root tree object 237 * rev: the commit pointing at the root tree object
238 * path: path to tree or blob 238 * path: path to tree or blob
239 */ 239 */
240void cgit_print_tree(const char *rev, char *path) 240void cgit_print_tree(const char *rev, char *path)
241{ 241{
242 unsigned char sha1[20]; 242 unsigned char sha1[20];
243 struct commit *commit; 243 struct commit *commit;
244 const char *paths[] = {path, NULL}; 244 const char *paths[] = {path, NULL};
245 245
246 if (!rev) 246 if (!rev)
247 rev = ctx.qry.head; 247 rev = ctx.qry.head;
248 248
249 curr_rev = xstrdup(rev); 249 curr_rev = xstrdup(rev);
250 if (get_sha1(rev, sha1)) { 250 if (get_sha1(rev, sha1)) {
251 cgit_print_error(fmt("Invalid revision name: %s", rev)); 251 cgit_print_error(fmt("Invalid revision name: %s", rev));
252 return; 252 return;
253 } 253 }
254 commit = lookup_commit_reference(sha1); 254 commit = lookup_commit_reference(sha1);
255 if (!commit || parse_commit(commit)) { 255 if (!commit || parse_commit(commit)) {
256 cgit_print_error(fmt("Invalid commit reference: %s", rev)); 256 cgit_print_error(fmt("Invalid commit reference: %s", rev));
257 return; 257 return;
258 } 258 }
259 259
260 html("path: <a href='"); 260 html("path: <a href='");
261 html_attr(cgit_pageurl(ctx.qry.repo, "tree", fmt("h=%s", rev))); 261 html_attr(cgit_pageurl(ctx.qry.repo, "tree", fmt("h=%s", rev)));
262 html("'>root</a>"); 262 html("'>root</a>");
263 263
264 if (path == NULL) { 264 if (path == NULL) {
265 ls_tree(commit->tree->object.sha1, NULL); 265 ls_tree(commit->tree->object.sha1, NULL);
266 return; 266 return;
267 } 267 }
268 268
269 match_path = path; 269 match_path = path;
270 read_tree_recursive(commit->tree, NULL, 0, 0, paths, walk_tree, NULL); 270 read_tree_recursive(commit->tree, NULL, 0, 0, paths, walk_tree, NULL);
271 ls_tail(); 271 ls_tail();
272} 272}