summaryrefslogtreecommitdiffabout
path: root/ui-tree.c
Unidiff
Diffstat (limited to 'ui-tree.c') (more/less context) (ignore whitespace changes)
-rw-r--r--ui-tree.c71
1 files changed, 48 insertions, 23 deletions
diff --git a/ui-tree.c b/ui-tree.c
index c26ba4c..a37a4e5 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -1,159 +1,184 @@
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 "cgit.h" 10#include "cgit.h"
10#include "html.h" 11#include "html.h"
11#include "ui-shared.h" 12#include "ui-shared.h"
12 13
13char *curr_rev; 14char *curr_rev;
14char *match_path; 15char *match_path;
15int header = 0; 16int header = 0;
16 17
18static void print_text_buffer(char *buf, unsigned long size)
19{
20 unsigned long lineno, idx;
21 const char *numberfmt =
22 "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n";
23
24 html("<table summary='blob content' class='blob'>\n");
25 html("<tr><td class='linenumbers'><pre>");
26 idx = 0;
27 lineno = 0;
28 htmlf(numberfmt, ++lineno);
29 while(idx < size - 1) { // skip absolute last newline
30 if (buf[idx] == '\n')
31 htmlf(numberfmt, ++lineno);
32 idx++;
33 }
34 html("</pre></td>\n");
35 html("<td class='lines'><pre><code>");
36 html_txt(buf);
37 html("</code></pre></td></tr></table>\n");
38}
39
40static void print_binary_buffer(char *buf, unsigned long size)
41{
42 unsigned long ofs, idx;
43
44 html("<table summary='blob content' class='bin-blob'>\n");
45 html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>");
46 for (ofs = 0; ofs < size; ofs += 32, buf += 32) {
47 htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs);
48 for (idx = 0; idx < 32 && ofs + idx < size; idx++)
49 htmlf("%*s%02x",
50 idx == 16 ? 4 : 1, "",
51 buf[idx] & 0xff);
52 html(" </td><td class='hex'>");
53 for (idx = 0; idx < 32 && ofs + idx < size; idx++)
54 htmlf("%c", isgraph(buf[idx]) ? buf[idx] : '.');
55 html("</td></tr>\n");
56 }
57 html("</table>\n");
58}
59
17static void print_object(const unsigned char *sha1, char *path) 60static void print_object(const unsigned char *sha1, char *path)
18{ 61{
19 enum object_type type; 62 enum object_type type;
20 char *buf; 63 char *buf;
21 unsigned long size, lineno, idx; 64 unsigned long size;
22 const char *numberfmt = "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n";
23 65
24 type = sha1_object_info(sha1, &size); 66 type = sha1_object_info(sha1, &size);
25 if (type == OBJ_BAD) { 67 if (type == OBJ_BAD) {
26 cgit_print_error(fmt("Bad object name: %s", 68 cgit_print_error(fmt("Bad object name: %s",
27 sha1_to_hex(sha1))); 69 sha1_to_hex(sha1)));
28 return; 70 return;
29 } 71 }
30 72
31 buf = read_sha1_file(sha1, &type, &size); 73 buf = read_sha1_file(sha1, &type, &size);
32 if (!buf) { 74 if (!buf) {
33 cgit_print_error(fmt("Error reading object %s", 75 cgit_print_error(fmt("Error reading object %s",
34 sha1_to_hex(sha1))); 76 sha1_to_hex(sha1)));
35 return; 77 return;
36 } 78 }
37 79
38 html(" ("); 80 html(" (");
39 cgit_plain_link("plain", NULL, NULL, ctx.qry.head, 81 cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
40 curr_rev, path); 82 curr_rev, path);
41 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1)); 83 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1));
42 84
43 html("<table summary='blob content' class='blob'>\n"); 85 if (buffer_is_binary(buf, size))
44 html("<tr>\n"); 86 print_binary_buffer(buf, size);
45 87 else
46 html("<td class='linenumbers'><pre>"); 88 print_text_buffer(buf, size);
47 idx = 0;
48 lineno = 0;
49 htmlf(numberfmt, ++lineno);
50 while(idx < size - 1) { // skip absolute last newline
51 if (buf[idx] == '\n') {
52 htmlf(numberfmt, ++lineno);
53 }
54 idx++;
55 }
56 html("</pre></td>\n");
57
58 html("<td class='lines'><pre><code>");
59 html_txt(buf);
60 html("</code></pre></td>\n");
61
62 html("</tr>\n");
63 html("</table>\n");
64} 89}
65 90
66 91
67static int ls_item(const unsigned char *sha1, const char *base, int baselen, 92static int ls_item(const unsigned char *sha1, const char *base, int baselen,
68 const char *pathname, unsigned int mode, int stage, 93 const char *pathname, unsigned int mode, int stage,
69 void *cbdata) 94 void *cbdata)
70{ 95{
71 char *name; 96 char *name;
72 char *fullpath; 97 char *fullpath;
73 enum object_type type; 98 enum object_type type;
74 unsigned long size = 0; 99 unsigned long size = 0;
75 100
76 name = xstrdup(pathname); 101 name = xstrdup(pathname);
77 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", 102 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "",
78 ctx.qry.path ? "/" : "", name); 103 ctx.qry.path ? "/" : "", name);
79 104
80 if (!S_ISGITLINK(mode)) { 105 if (!S_ISGITLINK(mode)) {
81 type = sha1_object_info(sha1, &size); 106 type = sha1_object_info(sha1, &size);
82 if (type == OBJ_BAD) { 107 if (type == OBJ_BAD) {
83 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", 108 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>",
84 name, 109 name,
85 sha1_to_hex(sha1)); 110 sha1_to_hex(sha1));
86 return 0; 111 return 0;
87 } 112 }
88 } 113 }
89 114
90 html("<tr><td class='ls-mode'>"); 115 html("<tr><td class='ls-mode'>");
91 cgit_print_filemode(mode); 116 cgit_print_filemode(mode);
92 html("</td><td>"); 117 html("</td><td>");
93 if (S_ISGITLINK(mode)) { 118 if (S_ISGITLINK(mode)) {
94 htmlf("<a class='ls-mod' href='"); 119 htmlf("<a class='ls-mod' href='");
95 html_attr(fmt(ctx.repo->module_link, 120 html_attr(fmt(ctx.repo->module_link,
96 name, 121 name,
97 sha1_to_hex(sha1))); 122 sha1_to_hex(sha1)));
98 html("'>"); 123 html("'>");
99 html_txt(name); 124 html_txt(name);
100 html("</a>"); 125 html("</a>");
101 } else if (S_ISDIR(mode)) { 126 } else if (S_ISDIR(mode)) {
102 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, 127 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head,
103 curr_rev, fullpath); 128 curr_rev, fullpath);
104 } else { 129 } else {
105 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head, 130 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head,
106 curr_rev, fullpath); 131 curr_rev, fullpath);
107 } 132 }
108 htmlf("</td><td class='ls-size'>%li</td>", size); 133 htmlf("</td><td class='ls-size'>%li</td>", size);
109 134
110 html("<td>"); 135 html("<td>");
111 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, 136 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev,
112 fullpath, 0, NULL, NULL, ctx.qry.showmsg); 137 fullpath, 0, NULL, NULL, ctx.qry.showmsg);
113 if (ctx.repo->max_stats) 138 if (ctx.repo->max_stats)
114 cgit_stats_link("stats", NULL, "button", ctx.qry.head, 139 cgit_stats_link("stats", NULL, "button", ctx.qry.head,
115 fullpath); 140 fullpath);
116 html("</td></tr>\n"); 141 html("</td></tr>\n");
117 free(name); 142 free(name);
118 return 0; 143 return 0;
119} 144}
120 145
121static void ls_head() 146static void ls_head()
122{ 147{
123 html("<table summary='tree listing' class='list'>\n"); 148 html("<table summary='tree listing' class='list'>\n");
124 html("<tr class='nohover'>"); 149 html("<tr class='nohover'>");
125 html("<th class='left'>Mode</th>"); 150 html("<th class='left'>Mode</th>");
126 html("<th class='left'>Name</th>"); 151 html("<th class='left'>Name</th>");
127 html("<th class='right'>Size</th>"); 152 html("<th class='right'>Size</th>");
128 html("<th/>"); 153 html("<th/>");
129 html("</tr>\n"); 154 html("</tr>\n");
130 header = 1; 155 header = 1;
131} 156}
132 157
133static void ls_tail() 158static void ls_tail()
134{ 159{
135 if (!header) 160 if (!header)
136 return; 161 return;
137 html("</table>\n"); 162 html("</table>\n");
138 header = 0; 163 header = 0;
139} 164}
140 165
141static void ls_tree(const unsigned char *sha1, char *path) 166static void ls_tree(const unsigned char *sha1, char *path)
142{ 167{
143 struct tree *tree; 168 struct tree *tree;
144 169
145 tree = parse_tree_indirect(sha1); 170 tree = parse_tree_indirect(sha1);
146 if (!tree) { 171 if (!tree) {
147 cgit_print_error(fmt("Not a tree object: %s", 172 cgit_print_error(fmt("Not a tree object: %s",
148 sha1_to_hex(sha1))); 173 sha1_to_hex(sha1)));
149 return; 174 return;
150 } 175 }
151 176
152 ls_head(); 177 ls_head();
153 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL); 178 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL);
154 ls_tail(); 179 ls_tail();
155} 180}
156 181
157 182
158static int walk_tree(const unsigned char *sha1, const char *base, int baselen, 183static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
159 const char *pathname, unsigned mode, int stage, 184 const char *pathname, unsigned mode, int stage,