summaryrefslogtreecommitdiffabout
path: root/ui-tree.c
Unidiff
Diffstat (limited to 'ui-tree.c') (more/less context) (show whitespace changes)
-rw-r--r--ui-tree.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/ui-tree.c b/ui-tree.c
index 2a8625c..c26ba4c 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -17,192 +17,195 @@ int header = 0;
17static void print_object(const unsigned char *sha1, char *path) 17static void print_object(const unsigned char *sha1, char *path)
18{ 18{
19 enum object_type type; 19 enum object_type type;
20 char *buf; 20 char *buf;
21 unsigned long size, lineno, idx; 21 unsigned long size, lineno, idx;
22 const char *numberfmt = "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n"; 22 const char *numberfmt = "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n";
23 23
24 type = sha1_object_info(sha1, &size); 24 type = sha1_object_info(sha1, &size);
25 if (type == OBJ_BAD) { 25 if (type == OBJ_BAD) {
26 cgit_print_error(fmt("Bad object name: %s", 26 cgit_print_error(fmt("Bad object name: %s",
27 sha1_to_hex(sha1))); 27 sha1_to_hex(sha1)));
28 return; 28 return;
29 } 29 }
30 30
31 buf = read_sha1_file(sha1, &type, &size); 31 buf = read_sha1_file(sha1, &type, &size);
32 if (!buf) { 32 if (!buf) {
33 cgit_print_error(fmt("Error reading object %s", 33 cgit_print_error(fmt("Error reading object %s",
34 sha1_to_hex(sha1))); 34 sha1_to_hex(sha1)));
35 return; 35 return;
36 } 36 }
37 37
38 html(" ("); 38 html(" (");
39 cgit_plain_link("plain", NULL, NULL, ctx.qry.head, 39 cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
40 curr_rev, path); 40 curr_rev, path);
41 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1)); 41 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1));
42 42
43 html("<table summary='blob content' class='blob'>\n"); 43 html("<table summary='blob content' class='blob'>\n");
44 html("<tr>\n"); 44 html("<tr>\n");
45 45
46 html("<td class='linenumbers'><pre>"); 46 html("<td class='linenumbers'><pre>");
47 idx = 0; 47 idx = 0;
48 lineno = 0; 48 lineno = 0;
49 htmlf(numberfmt, ++lineno); 49 htmlf(numberfmt, ++lineno);
50 while(idx < size - 1) { // skip absolute last newline 50 while(idx < size - 1) { // skip absolute last newline
51 if (buf[idx] == '\n') { 51 if (buf[idx] == '\n') {
52 htmlf(numberfmt, ++lineno); 52 htmlf(numberfmt, ++lineno);
53 } 53 }
54 idx++; 54 idx++;
55 } 55 }
56 html("</pre></td>\n"); 56 html("</pre></td>\n");
57 57
58 html("<td class='lines'><pre><code>"); 58 html("<td class='lines'><pre><code>");
59 html_txt(buf); 59 html_txt(buf);
60 html("</code></pre></td>\n"); 60 html("</code></pre></td>\n");
61 61
62 html("</tr>\n"); 62 html("</tr>\n");
63 html("</table>\n"); 63 html("</table>\n");
64} 64}
65 65
66 66
67static int ls_item(const unsigned char *sha1, const char *base, int baselen, 67static int ls_item(const unsigned char *sha1, const char *base, int baselen,
68 const char *pathname, unsigned int mode, int stage, 68 const char *pathname, unsigned int mode, int stage,
69 void *cbdata) 69 void *cbdata)
70{ 70{
71 char *name; 71 char *name;
72 char *fullpath; 72 char *fullpath;
73 enum object_type type; 73 enum object_type type;
74 unsigned long size = 0; 74 unsigned long size = 0;
75 75
76 name = xstrdup(pathname); 76 name = xstrdup(pathname);
77 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", 77 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "",
78 ctx.qry.path ? "/" : "", name); 78 ctx.qry.path ? "/" : "", name);
79 79
80 if (!S_ISGITLINK(mode)) { 80 if (!S_ISGITLINK(mode)) {
81 type = sha1_object_info(sha1, &size); 81 type = sha1_object_info(sha1, &size);
82 if (type == OBJ_BAD) { 82 if (type == OBJ_BAD) {
83 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", 83 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>",
84 name, 84 name,
85 sha1_to_hex(sha1)); 85 sha1_to_hex(sha1));
86 return 0; 86 return 0;
87 } 87 }
88 } 88 }
89 89
90 html("<tr><td class='ls-mode'>"); 90 html("<tr><td class='ls-mode'>");
91 cgit_print_filemode(mode); 91 cgit_print_filemode(mode);
92 html("</td><td>"); 92 html("</td><td>");
93 if (S_ISGITLINK(mode)) { 93 if (S_ISGITLINK(mode)) {
94 htmlf("<a class='ls-mod' href='"); 94 htmlf("<a class='ls-mod' href='");
95 html_attr(fmt(ctx.repo->module_link, 95 html_attr(fmt(ctx.repo->module_link,
96 name, 96 name,
97 sha1_to_hex(sha1))); 97 sha1_to_hex(sha1)));
98 html("'>"); 98 html("'>");
99 html_txt(name); 99 html_txt(name);
100 html("</a>"); 100 html("</a>");
101 } else if (S_ISDIR(mode)) { 101 } else if (S_ISDIR(mode)) {
102 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, 102 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head,
103 curr_rev, fullpath); 103 curr_rev, fullpath);
104 } else { 104 } else {
105 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head, 105 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head,
106 curr_rev, fullpath); 106 curr_rev, fullpath);
107 } 107 }
108 htmlf("</td><td class='ls-size'>%li</td>", size); 108 htmlf("</td><td class='ls-size'>%li</td>", size);
109 109
110 html("<td>"); 110 html("<td>");
111 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, 111 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev,
112 fullpath, 0, NULL, NULL, ctx.qry.showmsg); 112 fullpath, 0, NULL, NULL, ctx.qry.showmsg);
113 if (ctx.repo->max_stats)
114 cgit_stats_link("stats", NULL, "button", ctx.qry.head,
115 fullpath);
113 html("</td></tr>\n"); 116 html("</td></tr>\n");
114 free(name); 117 free(name);
115 return 0; 118 return 0;
116} 119}
117 120
118static void ls_head() 121static void ls_head()
119{ 122{
120 html("<table summary='tree listing' class='list'>\n"); 123 html("<table summary='tree listing' class='list'>\n");
121 html("<tr class='nohover'>"); 124 html("<tr class='nohover'>");
122 html("<th class='left'>Mode</th>"); 125 html("<th class='left'>Mode</th>");
123 html("<th class='left'>Name</th>"); 126 html("<th class='left'>Name</th>");
124 html("<th class='right'>Size</th>"); 127 html("<th class='right'>Size</th>");
125 html("<th/>"); 128 html("<th/>");
126 html("</tr>\n"); 129 html("</tr>\n");
127 header = 1; 130 header = 1;
128} 131}
129 132
130static void ls_tail() 133static void ls_tail()
131{ 134{
132 if (!header) 135 if (!header)
133 return; 136 return;
134 html("</table>\n"); 137 html("</table>\n");
135 header = 0; 138 header = 0;
136} 139}
137 140
138static void ls_tree(const unsigned char *sha1, char *path) 141static void ls_tree(const unsigned char *sha1, char *path)
139{ 142{
140 struct tree *tree; 143 struct tree *tree;
141 144
142 tree = parse_tree_indirect(sha1); 145 tree = parse_tree_indirect(sha1);
143 if (!tree) { 146 if (!tree) {
144 cgit_print_error(fmt("Not a tree object: %s", 147 cgit_print_error(fmt("Not a tree object: %s",
145 sha1_to_hex(sha1))); 148 sha1_to_hex(sha1)));
146 return; 149 return;
147 } 150 }
148 151
149 ls_head(); 152 ls_head();
150 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL); 153 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL);
151 ls_tail(); 154 ls_tail();
152} 155}
153 156
154 157
155static int walk_tree(const unsigned char *sha1, const char *base, int baselen, 158static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
156 const char *pathname, unsigned mode, int stage, 159 const char *pathname, unsigned mode, int stage,
157 void *cbdata) 160 void *cbdata)
158{ 161{
159 static int state; 162 static int state;
160 static char buffer[PATH_MAX]; 163 static char buffer[PATH_MAX];
161 char *url; 164 char *url;
162 165
163 if (state == 0) { 166 if (state == 0) {
164 memcpy(buffer, base, baselen); 167 memcpy(buffer, base, baselen);
165 strcpy(buffer+baselen, pathname); 168 strcpy(buffer+baselen, pathname);
166 url = cgit_pageurl(ctx.qry.repo, "tree", 169 url = cgit_pageurl(ctx.qry.repo, "tree",
167 fmt("h=%s&amp;path=%s", curr_rev, buffer)); 170 fmt("h=%s&amp;path=%s", curr_rev, buffer));
168 html("/"); 171 html("/");
169 cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head, 172 cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head,
170 curr_rev, buffer); 173 curr_rev, buffer);
171 174
172 if (strcmp(match_path, buffer)) 175 if (strcmp(match_path, buffer))
173 return READ_TREE_RECURSIVE; 176 return READ_TREE_RECURSIVE;
174 177
175 if (S_ISDIR(mode)) { 178 if (S_ISDIR(mode)) {
176 state = 1; 179 state = 1;
177 ls_head(); 180 ls_head();
178 return READ_TREE_RECURSIVE; 181 return READ_TREE_RECURSIVE;
179 } else { 182 } else {
180 print_object(sha1, buffer); 183 print_object(sha1, buffer);
181 return 0; 184 return 0;
182 } 185 }
183 } 186 }
184 ls_item(sha1, base, baselen, pathname, mode, stage, NULL); 187 ls_item(sha1, base, baselen, pathname, mode, stage, NULL);
185 return 0; 188 return 0;
186} 189}
187 190
188 191
189/* 192/*
190 * Show a tree or a blob 193 * Show a tree or a blob
191 * rev: the commit pointing at the root tree object 194 * rev: the commit pointing at the root tree object
192 * path: path to tree or blob 195 * path: path to tree or blob
193 */ 196 */
194void cgit_print_tree(const char *rev, char *path) 197void cgit_print_tree(const char *rev, char *path)
195{ 198{
196 unsigned char sha1[20]; 199 unsigned char sha1[20];
197 struct commit *commit; 200 struct commit *commit;
198 const char *paths[] = {path, NULL}; 201 const char *paths[] = {path, NULL};
199 202
200 if (!rev) 203 if (!rev)
201 rev = ctx.qry.head; 204 rev = ctx.qry.head;
202 205
203 curr_rev = xstrdup(rev); 206 curr_rev = xstrdup(rev);
204 if (get_sha1(rev, sha1)) { 207 if (get_sha1(rev, sha1)) {
205 cgit_print_error(fmt("Invalid revision name: %s", rev)); 208 cgit_print_error(fmt("Invalid revision name: %s", rev));
206 return; 209 return;
207 } 210 }
208 commit = lookup_commit_reference(sha1); 211 commit = lookup_commit_reference(sha1);