summaryrefslogtreecommitdiffabout
path: root/ui-tree.c
authorLars Hjemli <hjemli@gmail.com>2009-07-31 14:55:27 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2009-07-31 15:41:21 (UTC)
commit46b7abed99e957008c01c02cf612aa526ba92f04 (patch) (unidiff)
tree2cdbfe5281c2ffa645def488d53db0a8b82842f4 /ui-tree.c
parent18dfbdc099c1398016427b6fa7f1a1facb363998 (diff)
downloadcgit-46b7abed99e957008c01c02cf612aa526ba92f04.zip
cgit-46b7abed99e957008c01c02cf612aa526ba92f04.tar.gz
cgit-46b7abed99e957008c01c02cf612aa526ba92f04.tar.bz2
ui-tree: add support for source-filter option
This new option is used to specify an external command which will be executed when displaying blob content in the tree view. Blob content will be written to STDIN of the filter and STDOUT from the filter will be included verbatim in the html output from cgit. The file name of the blob will be passed as the only argument to the filter command. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'ui-tree.c') (more/less context) (ignore whitespace changes)
-rw-r--r--ui-tree.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/ui-tree.c b/ui-tree.c
index 553dbaa..816e121 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -1,120 +1,130 @@
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(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) {
26 html("<tr><td class='lines'><pre><code>");
27 ctx.cfg.source_filter->argv[1] = xstrdup(name);
28 cgit_open_filter(ctx.cfg.source_filter);
29 write(STDOUT_FILENO, buf, size);
30 cgit_close_filter(ctx.cfg.source_filter);
31 html("</code></pre></td></tr></table>\n");
32 return;
33 }
34
25 html("<tr><td class='linenumbers'><pre>"); 35 html("<tr><td class='linenumbers'><pre>");
26 idx = 0; 36 idx = 0;
27 lineno = 0; 37 lineno = 0;
28 38
29 if (size) { 39 if (size) {
30 htmlf(numberfmt, ++lineno); 40 htmlf(numberfmt, ++lineno);
31 while(idx < size - 1) { // skip absolute last newline 41 while(idx < size - 1) { // skip absolute last newline
32 if (buf[idx] == '\n') 42 if (buf[idx] == '\n')
33 htmlf(numberfmt, ++lineno); 43 htmlf(numberfmt, ++lineno);
34 idx++; 44 idx++;
35 } 45 }
36 } 46 }
37 html("</pre></td>\n"); 47 html("</pre></td>\n");
38 html("<td class='lines'><pre><code>"); 48 html("<td class='lines'><pre><code>");
39 html_txt(buf); 49 html_txt(buf);
40 html("</code></pre></td></tr></table>\n"); 50 html("</code></pre></td></tr></table>\n");
41} 51}
42 52
43#define ROWLEN 32 53#define ROWLEN 32
44 54
45static void print_binary_buffer(char *buf, unsigned long size) 55static void print_binary_buffer(char *buf, unsigned long size)
46{ 56{
47 unsigned long ofs, idx; 57 unsigned long ofs, idx;
48 static char ascii[ROWLEN + 1]; 58 static char ascii[ROWLEN + 1];
49 59
50 html("<table summary='blob content' class='bin-blob'>\n"); 60 html("<table summary='blob content' class='bin-blob'>\n");
51 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>");
52 for (ofs = 0; ofs < size; ofs += ROWLEN, buf += ROWLEN) { 62 for (ofs = 0; ofs < size; ofs += ROWLEN, buf += ROWLEN) {
53 htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs); 63 htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs);
54 for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) 64 for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++)
55 htmlf("%*s%02x", 65 htmlf("%*s%02x",
56 idx == 16 ? 4 : 1, "", 66 idx == 16 ? 4 : 1, "",
57 buf[idx] & 0xff); 67 buf[idx] & 0xff);
58 html(" </td><td class='hex'>"); 68 html(" </td><td class='hex'>");
59 for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) 69 for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++)
60 ascii[idx] = isgraph(buf[idx]) ? buf[idx] : '.'; 70 ascii[idx] = isgraph(buf[idx]) ? buf[idx] : '.';
61 ascii[idx] = '\0'; 71 ascii[idx] = '\0';
62 html_txt(ascii); 72 html_txt(ascii);
63 html("</td></tr>\n"); 73 html("</td></tr>\n");
64 } 74 }
65 html("</table>\n"); 75 html("</table>\n");
66} 76}
67 77
68static void print_object(const unsigned char *sha1, char *path) 78static void print_object(const unsigned char *sha1, char *path, const char *basename)
69{ 79{
70 enum object_type type; 80 enum object_type type;
71 char *buf; 81 char *buf;
72 unsigned long size; 82 unsigned long size;
73 83
74 type = sha1_object_info(sha1, &size); 84 type = sha1_object_info(sha1, &size);
75 if (type == OBJ_BAD) { 85 if (type == OBJ_BAD) {
76 cgit_print_error(fmt("Bad object name: %s", 86 cgit_print_error(fmt("Bad object name: %s",
77 sha1_to_hex(sha1))); 87 sha1_to_hex(sha1)));
78 return; 88 return;
79 } 89 }
80 90
81 buf = read_sha1_file(sha1, &type, &size); 91 buf = read_sha1_file(sha1, &type, &size);
82 if (!buf) { 92 if (!buf) {
83 cgit_print_error(fmt("Error reading object %s", 93 cgit_print_error(fmt("Error reading object %s",
84 sha1_to_hex(sha1))); 94 sha1_to_hex(sha1)));
85 return; 95 return;
86 } 96 }
87 97
88 html(" ("); 98 html(" (");
89 cgit_plain_link("plain", NULL, NULL, ctx.qry.head, 99 cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
90 curr_rev, path); 100 curr_rev, path);
91 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1)); 101 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1));
92 102
93 if (buffer_is_binary(buf, size)) 103 if (buffer_is_binary(buf, size))
94 print_binary_buffer(buf, size); 104 print_binary_buffer(buf, size);
95 else 105 else
96 print_text_buffer(buf, size); 106 print_text_buffer(basename, buf, size);
97} 107}
98 108
99 109
100static 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,
101 const char *pathname, unsigned int mode, int stage, 111 const char *pathname, unsigned int mode, int stage,
102 void *cbdata) 112 void *cbdata)
103{ 113{
104 char *name; 114 char *name;
105 char *fullpath; 115 char *fullpath;
106 enum object_type type; 116 enum object_type type;
107 unsigned long size = 0; 117 unsigned long size = 0;
108 118
109 name = xstrdup(pathname); 119 name = xstrdup(pathname);
110 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", 120 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "",
111 ctx.qry.path ? "/" : "", name); 121 ctx.qry.path ? "/" : "", name);
112 122
113 if (!S_ISGITLINK(mode)) { 123 if (!S_ISGITLINK(mode)) {
114 type = sha1_object_info(sha1, &size); 124 type = sha1_object_info(sha1, &size);
115 if (type == OBJ_BAD) { 125 if (type == OBJ_BAD) {
116 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", 126 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>",
117 name, 127 name,
118 sha1_to_hex(sha1)); 128 sha1_to_hex(sha1));
119 return 0; 129 return 0;
120 } 130 }
@@ -192,49 +202,49 @@ static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
192 const char *pathname, unsigned mode, int stage, 202 const char *pathname, unsigned mode, int stage,
193 void *cbdata) 203 void *cbdata)
194{ 204{
195 static int state; 205 static int state;
196 static char buffer[PATH_MAX]; 206 static char buffer[PATH_MAX];
197 char *url; 207 char *url;
198 208
199 if (state == 0) { 209 if (state == 0) {
200 memcpy(buffer, base, baselen); 210 memcpy(buffer, base, baselen);
201 strcpy(buffer+baselen, pathname); 211 strcpy(buffer+baselen, pathname);
202 url = cgit_pageurl(ctx.qry.repo, "tree", 212 url = cgit_pageurl(ctx.qry.repo, "tree",
203 fmt("h=%s&amp;path=%s", curr_rev, buffer)); 213 fmt("h=%s&amp;path=%s", curr_rev, buffer));
204 html("/"); 214 html("/");
205 cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head, 215 cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head,
206 curr_rev, buffer); 216 curr_rev, buffer);
207 217
208 if (strcmp(match_path, buffer)) 218 if (strcmp(match_path, buffer))
209 return READ_TREE_RECURSIVE; 219 return READ_TREE_RECURSIVE;
210 220
211 if (S_ISDIR(mode)) { 221 if (S_ISDIR(mode)) {
212 state = 1; 222 state = 1;
213 ls_head(); 223 ls_head();
214 return READ_TREE_RECURSIVE; 224 return READ_TREE_RECURSIVE;
215 } else { 225 } else {
216 print_object(sha1, buffer); 226 print_object(sha1, buffer, pathname);
217 return 0; 227 return 0;
218 } 228 }
219 } 229 }
220 ls_item(sha1, base, baselen, pathname, mode, stage, NULL); 230 ls_item(sha1, base, baselen, pathname, mode, stage, NULL);
221 return 0; 231 return 0;
222} 232}
223 233
224 234
225/* 235/*
226 * Show a tree or a blob 236 * Show a tree or a blob
227 * rev: the commit pointing at the root tree object 237 * rev: the commit pointing at the root tree object
228 * path: path to tree or blob 238 * path: path to tree or blob
229 */ 239 */
230void cgit_print_tree(const char *rev, char *path) 240void cgit_print_tree(const char *rev, char *path)
231{ 241{
232 unsigned char sha1[20]; 242 unsigned char sha1[20];
233 struct commit *commit; 243 struct commit *commit;
234 const char *paths[] = {path, NULL}; 244 const char *paths[] = {path, NULL};
235 245
236 if (!rev) 246 if (!rev)
237 rev = ctx.qry.head; 247 rev = ctx.qry.head;
238 248
239 curr_rev = xstrdup(rev); 249 curr_rev = xstrdup(rev);
240 if (get_sha1(rev, sha1)) { 250 if (get_sha1(rev, sha1)) {