author | Lars Hjemli <hjemli@gmail.com> | 2007-06-16 23:23:08 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2007-06-16 23:39:05 (UTC) |
commit | 44947bfcdc0d6e8c7d673bea0538cbf2a182f289 (patch) (unidiff) | |
tree | 3f65d6842738a8314ed72d5575a0b523061556b7 | |
parent | f91b9696a36008c245a3195800ba0c5fa3e890f9 (diff) | |
download | cgit-44947bfcdc0d6e8c7d673bea0538cbf2a182f289.zip cgit-44947bfcdc0d6e8c7d673bea0538cbf2a182f289.tar.gz cgit-44947bfcdc0d6e8c7d673bea0538cbf2a182f289.tar.bz2 |
Add and use cgit_tree_link()
This creates a new function used to generate links to 'tree' page and uses
the function everywhere a link to the 'tree' page is generated.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | cgit.h | 3 | ||||
-rw-r--r-- | ui-commit.c | 10 | ||||
-rw-r--r-- | ui-repolist.c | 35 | ||||
-rw-r--r-- | ui-shared.c | 64 | ||||
-rw-r--r-- | ui-tree.c | 33 |
5 files changed, 107 insertions, 38 deletions
@@ -180,47 +180,50 @@ extern void html_ntxt(int len, char *txt); | |||
180 | extern void html_attr(char *txt); | 180 | extern void html_attr(char *txt); |
181 | extern void html_hidden(char *name, char *value); | 181 | extern void html_hidden(char *name, char *value); |
182 | extern void html_link_open(char *url, char *title, char *class); | 182 | extern void html_link_open(char *url, char *title, char *class); |
183 | extern void html_link_close(void); | 183 | extern void html_link_close(void); |
184 | extern void html_filemode(unsigned short mode); | 184 | extern void html_filemode(unsigned short mode); |
185 | extern int html_include(const char *filename); | 185 | extern int html_include(const char *filename); |
186 | 186 | ||
187 | extern int cgit_read_config(const char *filename, configfn fn); | 187 | extern int cgit_read_config(const char *filename, configfn fn); |
188 | extern int cgit_parse_query(char *txt, configfn fn); | 188 | extern int cgit_parse_query(char *txt, configfn fn); |
189 | extern struct commitinfo *cgit_parse_commit(struct commit *commit); | 189 | extern struct commitinfo *cgit_parse_commit(struct commit *commit); |
190 | extern struct taginfo *cgit_parse_tag(struct tag *tag); | 190 | extern struct taginfo *cgit_parse_tag(struct tag *tag); |
191 | extern void cgit_parse_url(const char *url); | 191 | extern void cgit_parse_url(const char *url); |
192 | 192 | ||
193 | extern char *cache_safe_filename(const char *unsafe); | 193 | extern char *cache_safe_filename(const char *unsafe); |
194 | extern int cache_lock(struct cacheitem *item); | 194 | extern int cache_lock(struct cacheitem *item); |
195 | extern int cache_unlock(struct cacheitem *item); | 195 | extern int cache_unlock(struct cacheitem *item); |
196 | extern int cache_cancel_lock(struct cacheitem *item); | 196 | extern int cache_cancel_lock(struct cacheitem *item); |
197 | extern int cache_exist(struct cacheitem *item); | 197 | extern int cache_exist(struct cacheitem *item); |
198 | extern int cache_expired(struct cacheitem *item); | 198 | extern int cache_expired(struct cacheitem *item); |
199 | 199 | ||
200 | extern char *cgit_repourl(const char *reponame); | 200 | extern char *cgit_repourl(const char *reponame); |
201 | extern char *cgit_pageurl(const char *reponame, const char *pagename, | 201 | extern char *cgit_pageurl(const char *reponame, const char *pagename, |
202 | const char *query); | 202 | const char *query); |
203 | 203 | ||
204 | extern void cgit_tree_link(char *name, char *title, char *class, char *head, | ||
205 | char *rev, char *path); | ||
206 | |||
204 | extern void cgit_print_error(char *msg); | 207 | extern void cgit_print_error(char *msg); |
205 | extern void cgit_print_date(time_t secs, char *format); | 208 | extern void cgit_print_date(time_t secs, char *format); |
206 | extern void cgit_print_age(time_t t, time_t max_relative, char *format); | 209 | extern void cgit_print_age(time_t t, time_t max_relative, char *format); |
207 | extern void cgit_print_docstart(char *title, struct cacheitem *item); | 210 | extern void cgit_print_docstart(char *title, struct cacheitem *item); |
208 | extern void cgit_print_docend(); | 211 | extern void cgit_print_docend(); |
209 | extern void cgit_print_pageheader(char *title, int show_search); | 212 | extern void cgit_print_pageheader(char *title, int show_search); |
210 | extern void cgit_print_snapshot_start(const char *mimetype, | 213 | extern void cgit_print_snapshot_start(const char *mimetype, |
211 | const char *filename, | 214 | const char *filename, |
212 | struct cacheitem *item); | 215 | struct cacheitem *item); |
213 | 216 | ||
214 | extern void cgit_print_repolist(struct cacheitem *item); | 217 | extern void cgit_print_repolist(struct cacheitem *item); |
215 | extern void cgit_print_summary(); | 218 | extern void cgit_print_summary(); |
216 | extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *path, int pager); | 219 | extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *path, int pager); |
217 | extern void cgit_print_blob(struct cacheitem *item, const char *hex, char *path); | 220 | extern void cgit_print_blob(struct cacheitem *item, const char *hex, char *path); |
218 | extern void cgit_print_tree(const char *rev, char *path); | 221 | extern void cgit_print_tree(const char *rev, char *path); |
219 | extern void cgit_print_commit(const char *hex); | 222 | extern void cgit_print_commit(const char *hex); |
220 | extern void cgit_print_diff(const char *head, const char *old_hex, const char *new_hex, | 223 | extern void cgit_print_diff(const char *head, const char *old_hex, const char *new_hex, |
221 | char *path); | 224 | char *path); |
222 | extern void cgit_print_snapshot(struct cacheitem *item, const char *hex, | 225 | extern void cgit_print_snapshot(struct cacheitem *item, const char *hex, |
223 | const char *format, const char *prefix, | 226 | const char *format, const char *prefix, |
224 | const char *filename); | 227 | const char *filename); |
225 | 228 | ||
226 | #endif /* CGIT_H */ | 229 | #endif /* CGIT_H */ |
diff --git a/ui-commit.c b/ui-commit.c index ed5384d..885f870 100644 --- a/ui-commit.c +++ b/ui-commit.c | |||
@@ -132,80 +132,82 @@ void inspect_filepair(struct diff_filepair *pair) | |||
132 | items[files-1].status = pair->status; | 132 | items[files-1].status = pair->status; |
133 | hashcpy(items[files-1].old_sha1, pair->one->sha1); | 133 | hashcpy(items[files-1].old_sha1, pair->one->sha1); |
134 | hashcpy(items[files-1].new_sha1, pair->two->sha1); | 134 | hashcpy(items[files-1].new_sha1, pair->two->sha1); |
135 | items[files-1].old_mode = pair->one->mode; | 135 | items[files-1].old_mode = pair->one->mode; |
136 | items[files-1].new_mode = pair->two->mode; | 136 | items[files-1].new_mode = pair->two->mode; |
137 | items[files-1].old_path = xstrdup(pair->one->path); | 137 | items[files-1].old_path = xstrdup(pair->one->path); |
138 | items[files-1].new_path = xstrdup(pair->two->path); | 138 | items[files-1].new_path = xstrdup(pair->two->path); |
139 | items[files-1].added = lines_added; | 139 | items[files-1].added = lines_added; |
140 | items[files-1].removed = lines_removed; | 140 | items[files-1].removed = lines_removed; |
141 | if (lines_added + lines_removed > max_changes) | 141 | if (lines_added + lines_removed > max_changes) |
142 | max_changes = lines_added + lines_removed; | 142 | max_changes = lines_added + lines_removed; |
143 | total_adds += lines_added; | 143 | total_adds += lines_added; |
144 | total_rems += lines_removed; | 144 | total_rems += lines_removed; |
145 | } | 145 | } |
146 | 146 | ||
147 | 147 | ||
148 | void cgit_print_commit(const char *hex) | 148 | void cgit_print_commit(const char *hex) |
149 | { | 149 | { |
150 | struct commit *commit, *parent; | 150 | struct commit *commit, *parent; |
151 | struct commitinfo *info; | 151 | struct commitinfo *info; |
152 | struct commit_list *p; | 152 | struct commit_list *p; |
153 | unsigned char sha1[20]; | 153 | unsigned char sha1[20]; |
154 | char *query; | 154 | char *query; |
155 | char *filename; | 155 | char *filename; |
156 | char *tmp; | ||
156 | int i; | 157 | int i; |
157 | 158 | ||
158 | if (get_sha1(hex, sha1)) { | 159 | if (get_sha1(hex, sha1)) { |
159 | cgit_print_error(fmt("Bad object id: %s", hex)); | 160 | cgit_print_error(fmt("Bad object id: %s", hex)); |
160 | return; | 161 | return; |
161 | } | 162 | } |
162 | commit = lookup_commit_reference(sha1); | 163 | commit = lookup_commit_reference(sha1); |
163 | if (!commit) { | 164 | if (!commit) { |
164 | cgit_print_error(fmt("Bad commit reference: %s", hex)); | 165 | cgit_print_error(fmt("Bad commit reference: %s", hex)); |
165 | return; | 166 | return; |
166 | } | 167 | } |
167 | info = cgit_parse_commit(commit); | 168 | info = cgit_parse_commit(commit); |
168 | 169 | ||
169 | html("<table class='commit-info'>\n"); | 170 | html("<table class='commit-info'>\n"); |
170 | html("<tr><th>author</th><td>"); | 171 | html("<tr><th>author</th><td>"); |
171 | html_txt(info->author); | 172 | html_txt(info->author); |
172 | html(" "); | 173 | html(" "); |
173 | html_txt(info->author_email); | 174 | html_txt(info->author_email); |
174 | html("</td><td class='right'>"); | 175 | html("</td><td class='right'>"); |
175 | cgit_print_date(info->author_date, FMT_LONGDATE); | 176 | cgit_print_date(info->author_date, FMT_LONGDATE); |
176 | html("</td></tr>\n"); | 177 | html("</td></tr>\n"); |
177 | html("<tr><th>committer</th><td>"); | 178 | html("<tr><th>committer</th><td>"); |
178 | html_txt(info->committer); | 179 | html_txt(info->committer); |
179 | html(" "); | 180 | html(" "); |
180 | html_txt(info->committer_email); | 181 | html_txt(info->committer_email); |
181 | html("</td><td class='right'>"); | 182 | html("</td><td class='right'>"); |
182 | cgit_print_date(info->committer_date, FMT_LONGDATE); | 183 | cgit_print_date(info->committer_date, FMT_LONGDATE); |
183 | html("</td></tr>\n"); | 184 | html("</td></tr>\n"); |
184 | html("<tr><th>tree</th><td colspan='2' class='sha1'><a href='"); | 185 | html("<tr><th>tree</th><td colspan='2' class='sha1'>"); |
185 | query = fmt("h=%s", sha1_to_hex(commit->object.sha1)); | 186 | tmp = xstrdup(hex); |
186 | html_attr(cgit_pageurl(cgit_query_repo, "tree", query)); | 187 | cgit_tree_link(sha1_to_hex(commit->tree->object.sha1), NULL, NULL, |
187 | htmlf("'>%s</a></td></tr>\n", sha1_to_hex(commit->tree->object.sha1)); | 188 | cgit_query_head, tmp, NULL); |
189 | html("</td></tr>\n"); | ||
188 | for (p = commit->parents; p ; p = p->next) { | 190 | for (p = commit->parents; p ; p = p->next) { |
189 | parent = lookup_commit_reference(p->item->object.sha1); | 191 | parent = lookup_commit_reference(p->item->object.sha1); |
190 | if (!parent) { | 192 | if (!parent) { |
191 | html("<tr><td colspan='3'>"); | 193 | html("<tr><td colspan='3'>"); |
192 | cgit_print_error("Error reading parent commit"); | 194 | cgit_print_error("Error reading parent commit"); |
193 | html("</td></tr>"); | 195 | html("</td></tr>"); |
194 | continue; | 196 | continue; |
195 | } | 197 | } |
196 | html("<tr><th>parent</th>" | 198 | html("<tr><th>parent</th>" |
197 | "<td colspan='2' class='sha1'>" | 199 | "<td colspan='2' class='sha1'>" |
198 | "<a href='"); | 200 | "<a href='"); |
199 | query = fmt("h=%s", sha1_to_hex(p->item->object.sha1)); | 201 | query = fmt("h=%s", sha1_to_hex(p->item->object.sha1)); |
200 | html_attr(cgit_pageurl(cgit_query_repo, "commit", query)); | 202 | html_attr(cgit_pageurl(cgit_query_repo, "commit", query)); |
201 | htmlf("'>%s</a> (<a href='", | 203 | htmlf("'>%s</a> (<a href='", |
202 | sha1_to_hex(p->item->object.sha1)); | 204 | sha1_to_hex(p->item->object.sha1)); |
203 | query = fmt("id=%s&id2=%s", sha1_to_hex(parent->tree->object.sha1), | 205 | query = fmt("id=%s&id2=%s", sha1_to_hex(parent->tree->object.sha1), |
204 | sha1_to_hex(commit->tree->object.sha1)); | 206 | sha1_to_hex(commit->tree->object.sha1)); |
205 | html_attr(cgit_pageurl(cgit_query_repo, "diff", query)); | 207 | html_attr(cgit_pageurl(cgit_query_repo, "diff", query)); |
206 | html("'>diff</a>)</td></tr>"); | 208 | html("'>diff</a>)</td></tr>"); |
207 | } | 209 | } |
208 | if (cgit_repo->snapshots) { | 210 | if (cgit_repo->snapshots) { |
209 | htmlf("<tr><th>download</th><td colspan='2' class='sha1'><a href='"); | 211 | htmlf("<tr><th>download</th><td colspan='2' class='sha1'><a href='"); |
210 | filename = fmt("%s-%s.zip", cgit_query_repo, hex); | 212 | filename = fmt("%s-%s.zip", cgit_query_repo, hex); |
211 | html_attr(cgit_pageurl(cgit_query_repo, "snapshot", | 213 | html_attr(cgit_pageurl(cgit_query_repo, "snapshot", |
diff --git a/ui-repolist.c b/ui-repolist.c index e5c6c20..8ade91a 100644 --- a/ui-repolist.c +++ b/ui-repolist.c | |||
@@ -23,81 +23,78 @@ time_t read_agefile(char *path) | |||
23 | return strtoul(buf2, NULL, 10); | 23 | return strtoul(buf2, NULL, 10); |
24 | else | 24 | else |
25 | return 0; | 25 | return 0; |
26 | } | 26 | } |
27 | 27 | ||
28 | static void print_modtime(struct repoinfo *repo) | 28 | static void print_modtime(struct repoinfo *repo) |
29 | { | 29 | { |
30 | char *path; | 30 | char *path; |
31 | struct stat s; | 31 | struct stat s; |
32 | 32 | ||
33 | path = fmt("%s/%s", repo->path, cgit_agefile); | 33 | path = fmt("%s/%s", repo->path, cgit_agefile); |
34 | if (stat(path, &s) == 0) { | 34 | if (stat(path, &s) == 0) { |
35 | cgit_print_age(read_agefile(path), -1, NULL); | 35 | cgit_print_age(read_agefile(path), -1, NULL); |
36 | return; | 36 | return; |
37 | } | 37 | } |
38 | 38 | ||
39 | path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch); | 39 | path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch); |
40 | if (stat(path, &s) != 0) | 40 | if (stat(path, &s) != 0) |
41 | return; | 41 | return; |
42 | cgit_print_age(s.st_mtime, -1, NULL); | 42 | cgit_print_age(s.st_mtime, -1, NULL); |
43 | } | 43 | } |
44 | 44 | ||
45 | void cgit_print_repolist(struct cacheitem *item) | 45 | void cgit_print_repolist(struct cacheitem *item) |
46 | { | 46 | { |
47 | struct repoinfo *repo; | ||
48 | int i; | 47 | int i; |
49 | char *last_group = NULL; | 48 | char *last_group = NULL; |
50 | 49 | ||
51 | cgit_print_docstart(cgit_root_title, item); | 50 | cgit_print_docstart(cgit_root_title, item); |
52 | cgit_print_pageheader(cgit_root_title, 0); | 51 | cgit_print_pageheader(cgit_root_title, 0); |
53 | 52 | ||
54 | html("<table class='list nowrap'>"); | 53 | html("<table class='list nowrap'>"); |
55 | if (cgit_index_header) { | 54 | if (cgit_index_header) { |
56 | html("<tr class='nohover'><td colspan='5' class='include-block'>"); | 55 | html("<tr class='nohover'><td colspan='5' class='include-block'>"); |
57 | html_include(cgit_index_header); | 56 | html_include(cgit_index_header); |
58 | html("</td></tr>"); | 57 | html("</td></tr>"); |
59 | } | 58 | } |
60 | html("<tr class='nohover'>" | 59 | html("<tr class='nohover'>" |
61 | "<th class='left'>Name</th>" | 60 | "<th class='left'>Name</th>" |
62 | "<th class='left'>Description</th>" | 61 | "<th class='left'>Description</th>" |
63 | "<th class='left'>Owner</th>" | 62 | "<th class='left'>Owner</th>" |
64 | "<th class='left'>Idle</th>" | 63 | "<th class='left'>Idle</th>" |
65 | "<th>Links</th></tr>\n"); | 64 | "<th>Links</th></tr>\n"); |
66 | 65 | ||
67 | for (i=0; i<cgit_repolist.count; i++) { | 66 | for (i=0; i<cgit_repolist.count; i++) { |
68 | repo = &cgit_repolist.repos[i]; | 67 | cgit_repo = &cgit_repolist.repos[i]; |
69 | if ((last_group == NULL && repo->group != NULL) || | 68 | if ((last_group == NULL && cgit_repo->group != NULL) || |
70 | (last_group != NULL && repo->group == NULL) || | 69 | (last_group != NULL && cgit_repo->group == NULL) || |
71 | (last_group != NULL && repo->group!= NULL && | 70 | (last_group != NULL && cgit_repo->group != NULL && |
72 | strcmp(repo->group, last_group))) { | 71 | strcmp(cgit_repo->group, last_group))) { |
73 | html("<tr class='nohover'><td colspan='4' class='repogroup'>"); | 72 | html("<tr class='nohover'><td colspan='4' class='repogroup'>"); |
74 | html_txt(repo->group); | 73 | html_txt(cgit_repo->group); |
75 | html("</td></tr>"); | 74 | html("</td></tr>"); |
76 | last_group = repo->group; | 75 | last_group = cgit_repo->group; |
77 | } | 76 | } |
78 | htmlf("<tr><td class='%s'>", | 77 | htmlf("<tr><td class='%s'>", |
79 | repo->group ? "sublevel-repo" : "toplevel-repo"); | 78 | cgit_repo->group ? "sublevel-repo" : "toplevel-repo"); |
80 | html_link_open(cgit_repourl(repo->url), repo->desc, NULL); | 79 | html_link_open(cgit_repourl(cgit_repo->url), NULL, NULL); |
81 | html_txt(repo->name); | 80 | html_txt(cgit_repo->name); |
82 | html_link_close(); | 81 | html_link_close(); |
83 | html("</td><td>"); | 82 | html("</td><td>"); |
84 | html_ntxt(cgit_max_repodesc_len, repo->desc); | 83 | html_ntxt(cgit_max_repodesc_len, cgit_repo->desc); |
85 | html("</td><td>"); | 84 | html("</td><td>"); |
86 | html_txt(repo->owner); | 85 | html_txt(cgit_repo->owner); |
87 | html("</td><td>"); | 86 | html("</td><td>"); |
88 | print_modtime(repo); | 87 | print_modtime(cgit_repo); |
89 | html("</td><td>"); | 88 | html("</td><td>"); |
90 | html_link_open(cgit_repourl(repo->url), | 89 | html_link_open(cgit_repourl(cgit_repo->url), |
91 | "Summary", "button"); | 90 | "Summary", "button"); |
92 | html("S</a>"); | 91 | html("S</a>"); |
93 | html_link_open(cgit_pageurl(repo->name, "log", NULL), | 92 | html_link_open(cgit_pageurl(cgit_repo->name, "log", NULL), |
94 | "Log", "button"); | 93 | "Log", "button"); |
95 | html("L</a>"); | 94 | html("L</a>"); |
96 | html_link_open(cgit_pageurl(repo->name, "tree", NULL), | 95 | cgit_tree_link("F", "Files", "button", NULL, NULL, NULL); |
97 | "Files", "button"); | ||
98 | html("F</a>"); | ||
99 | html("</td></tr>\n"); | 96 | html("</td></tr>\n"); |
100 | } | 97 | } |
101 | html("</table>"); | 98 | html("</table>"); |
102 | cgit_print_docend(); | 99 | cgit_print_docend(); |
103 | } | 100 | } |
diff --git a/ui-shared.c b/ui-shared.c index aba93e8..9ab6409 100644 --- a/ui-shared.c +++ b/ui-shared.c | |||
@@ -66,48 +66,112 @@ char *cgit_pageurl(const char *reponame, const char *pagename, | |||
66 | pagename, query); | 66 | pagename, query); |
67 | else | 67 | else |
68 | return fmt("%s/%s/%s/", cgit_virtual_root, reponame, | 68 | return fmt("%s/%s/%s/", cgit_virtual_root, reponame, |
69 | pagename); | 69 | pagename); |
70 | } else { | 70 | } else { |
71 | if (query) | 71 | if (query) |
72 | return fmt("?r=%s&p=%s&%s", reponame, pagename, query); | 72 | return fmt("?r=%s&p=%s&%s", reponame, pagename, query); |
73 | else | 73 | else |
74 | return fmt("?r=%s&p=%s", reponame, pagename); | 74 | return fmt("?r=%s&p=%s", reponame, pagename); |
75 | } | 75 | } |
76 | } | 76 | } |
77 | 77 | ||
78 | char *cgit_currurl() | 78 | char *cgit_currurl() |
79 | { | 79 | { |
80 | if (!cgit_virtual_root) | 80 | if (!cgit_virtual_root) |
81 | return cgit_script_name; | 81 | return cgit_script_name; |
82 | else if (cgit_query_page) | 82 | else if (cgit_query_page) |
83 | return fmt("%s/%s/%s/", cgit_virtual_root, cgit_query_repo, cgit_query_page); | 83 | return fmt("%s/%s/%s/", cgit_virtual_root, cgit_query_repo, cgit_query_page); |
84 | else if (cgit_query_repo) | 84 | else if (cgit_query_repo) |
85 | return fmt("%s/%s/", cgit_virtual_root, cgit_query_repo); | 85 | return fmt("%s/%s/", cgit_virtual_root, cgit_query_repo); |
86 | else | 86 | else |
87 | return fmt("%s/", cgit_virtual_root); | 87 | return fmt("%s/", cgit_virtual_root); |
88 | } | 88 | } |
89 | 89 | ||
90 | static char *repolink(char *title, char *class, char *page, char *head, | ||
91 | char *path) | ||
92 | { | ||
93 | char *delim = "?"; | ||
94 | |||
95 | html("<a"); | ||
96 | if (title) { | ||
97 | html(" title='"); | ||
98 | html_attr(title); | ||
99 | html("'"); | ||
100 | } | ||
101 | if (class) { | ||
102 | html(" class='"); | ||
103 | html_attr(class); | ||
104 | html("'"); | ||
105 | } | ||
106 | html(" href='"); | ||
107 | if (cgit_virtual_root) { | ||
108 | html_attr(cgit_virtual_root); | ||
109 | if (cgit_virtual_root[strlen(cgit_virtual_root) - 1] != '/') | ||
110 | html("/"); | ||
111 | html_attr(cgit_repo->url); | ||
112 | if (cgit_repo->url[strlen(cgit_repo->url) - 1] != '/') | ||
113 | html("/"); | ||
114 | html(page); | ||
115 | html("/"); | ||
116 | if (path) | ||
117 | html_attr(path); | ||
118 | } else { | ||
119 | html(cgit_script_name); | ||
120 | html("?url="); | ||
121 | html_attr(cgit_repo->url); | ||
122 | if (cgit_repo->url[strlen(cgit_repo->url) - 1] != '/') | ||
123 | html("/"); | ||
124 | html(page); | ||
125 | html("/"); | ||
126 | if (path) | ||
127 | html_attr(path); | ||
128 | delim = "&"; | ||
129 | } | ||
130 | if (head && head != cgit_query_head) { | ||
131 | html(delim); | ||
132 | html("h="); | ||
133 | html_attr(head); | ||
134 | delim = "&"; | ||
135 | } | ||
136 | return fmt("%s", delim); | ||
137 | } | ||
138 | |||
139 | void cgit_tree_link(char *name, char *title, char *class, char *head, | ||
140 | char *rev, char *path) | ||
141 | { | ||
142 | char *delim; | ||
143 | |||
144 | delim = repolink(title, class, "tree", head, path); | ||
145 | if (rev && rev != cgit_query_head) { | ||
146 | html(delim); | ||
147 | html("id="); | ||
148 | html_attr(rev); | ||
149 | } | ||
150 | html("'>"); | ||
151 | html_txt(name); | ||
152 | html("</a>"); | ||
153 | } | ||
90 | 154 | ||
91 | void cgit_print_date(time_t secs, char *format) | 155 | void cgit_print_date(time_t secs, char *format) |
92 | { | 156 | { |
93 | char buf[64]; | 157 | char buf[64]; |
94 | struct tm *time; | 158 | struct tm *time; |
95 | 159 | ||
96 | time = gmtime(&secs); | 160 | time = gmtime(&secs); |
97 | strftime(buf, sizeof(buf)-1, format, time); | 161 | strftime(buf, sizeof(buf)-1, format, time); |
98 | html_txt(buf); | 162 | html_txt(buf); |
99 | } | 163 | } |
100 | 164 | ||
101 | void cgit_print_age(time_t t, time_t max_relative, char *format) | 165 | void cgit_print_age(time_t t, time_t max_relative, char *format) |
102 | { | 166 | { |
103 | time_t now, secs; | 167 | time_t now, secs; |
104 | 168 | ||
105 | time(&now); | 169 | time(&now); |
106 | secs = now - t; | 170 | secs = now - t; |
107 | 171 | ||
108 | if (secs > max_relative && max_relative >= 0) { | 172 | if (secs > max_relative && max_relative >= 0) { |
109 | cgit_print_date(t, format); | 173 | cgit_print_date(t, format); |
110 | return; | 174 | return; |
111 | } | 175 | } |
112 | 176 | ||
113 | if (secs < TM_HOUR * 2) { | 177 | if (secs < TM_HOUR * 2) { |
@@ -34,81 +34,86 @@ static void print_object(const unsigned char *sha1, char *path) | |||
34 | 34 | ||
35 | html("<table class='blob'>\n"); | 35 | html("<table class='blob'>\n"); |
36 | idx = 0; | 36 | idx = 0; |
37 | start = 0; | 37 | start = 0; |
38 | lineno = 0; | 38 | lineno = 0; |
39 | while(idx < size) { | 39 | while(idx < size) { |
40 | if (buf[idx] == '\n') { | 40 | if (buf[idx] == '\n') { |
41 | buf[idx] = '\0'; | 41 | buf[idx] = '\0'; |
42 | htmlf("<tr><td class='no'>%d</td><td class='txt'>", | 42 | htmlf("<tr><td class='no'>%d</td><td class='txt'>", |
43 | ++lineno); | 43 | ++lineno); |
44 | html_txt(buf + start); | 44 | html_txt(buf + start); |
45 | html("</td></tr>\n"); | 45 | html("</td></tr>\n"); |
46 | start = idx + 1; | 46 | start = idx + 1; |
47 | } | 47 | } |
48 | idx++; | 48 | idx++; |
49 | } | 49 | } |
50 | html("</table>\n"); | 50 | html("</table>\n"); |
51 | } | 51 | } |
52 | 52 | ||
53 | 53 | ||
54 | static int ls_item(const unsigned char *sha1, const char *base, int baselen, | 54 | static int ls_item(const unsigned char *sha1, const char *base, int baselen, |
55 | const char *pathname, unsigned int mode, int stage) | 55 | const char *pathname, unsigned int mode, int stage) |
56 | { | 56 | { |
57 | char *name; | 57 | char *name; |
58 | char *fullpath; | ||
58 | enum object_type type; | 59 | enum object_type type; |
59 | unsigned long size = 0; | 60 | unsigned long size = 0; |
60 | char *url, *qry; | 61 | char *url, *qry; |
61 | 62 | ||
62 | name = xstrdup(pathname); | 63 | name = xstrdup(pathname); |
64 | fullpath = fmt("%s%s%s", cgit_query_path ? cgit_query_path : "", | ||
65 | cgit_query_path ? "/" : "", name); | ||
66 | |||
63 | type = sha1_object_info(sha1, &size); | 67 | type = sha1_object_info(sha1, &size); |
64 | if (type == OBJ_BAD && !S_ISDIRLNK(mode)) { | 68 | if (type == OBJ_BAD && !S_ISDIRLNK(mode)) { |
65 | htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", | 69 | htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", |
66 | name, | 70 | name, |
67 | sha1_to_hex(sha1)); | 71 | sha1_to_hex(sha1)); |
68 | return 0; | 72 | return 0; |
69 | } | 73 | } |
70 | qry = fmt("h=%s&path=%s%s%s", curr_rev, | 74 | |
71 | cgit_query_path ? cgit_query_path : "", | ||
72 | cgit_query_path ? "/" : "", pathname); | ||
73 | url = cgit_pageurl(cgit_query_repo, "tree", qry); | ||
74 | html("<tr><td class='filemode'>"); | 75 | html("<tr><td class='filemode'>"); |
75 | html_filemode(mode); | 76 | html_filemode(mode); |
76 | html("</td><td "); | 77 | html("</td><td "); |
77 | if (S_ISDIRLNK(mode)) { | 78 | if (S_ISDIRLNK(mode)) { |
78 | htmlf("class='ls-mod'><a href='"); | 79 | htmlf("class='ls-mod'><a href='"); |
79 | html_attr(fmt(cgit_repo->module_link, | 80 | html_attr(fmt(cgit_repo->module_link, |
80 | name, | 81 | name, |
81 | sha1_to_hex(sha1))); | 82 | sha1_to_hex(sha1))); |
83 | html("'>"); | ||
84 | html_txt(name); | ||
85 | html("</a>"); | ||
82 | } else if (S_ISDIR(mode)) { | 86 | } else if (S_ISDIR(mode)) { |
83 | html("class='ls-dir'><a href='"); | 87 | html("class='ls-dir'>"); |
84 | html_attr(url); | 88 | cgit_tree_link(name, NULL, NULL, cgit_query_head, |
89 | curr_rev, fullpath); | ||
85 | } else { | 90 | } else { |
86 | html("class='ls-blob'><a href='"); | 91 | html("class='ls-blob'>"); |
87 | html_attr(url); | 92 | cgit_tree_link(name, NULL, NULL, cgit_query_head, |
93 | curr_rev, fullpath); | ||
88 | } | 94 | } |
89 | htmlf("'>%s</a></td>", name); | 95 | htmlf("</td><td class='filesize'>%li</td>", size); |
90 | htmlf("<td class='filesize'>%li</td>", size); | ||
91 | 96 | ||
92 | html("<td class='links'><a href='"); | 97 | html("<td class='links'><a href='"); |
93 | qry = fmt("h=%s&path=%s%s%s", curr_rev, | 98 | qry = fmt("h=%s&path=%s%s%s", curr_rev, |
94 | cgit_query_path ? cgit_query_path : "", | 99 | cgit_query_path ? cgit_query_path : "", |
95 | cgit_query_path ? "/" : "", pathname); | 100 | cgit_query_path ? "/" : "", pathname); |
96 | url = cgit_pageurl(cgit_query_repo, "log", qry); | 101 | url = cgit_pageurl(cgit_query_repo, "log", qry); |
97 | html_attr(url); | 102 | html_attr(url); |
98 | html("' class='button'>H</a></td>"); | 103 | html("' class='button'>H</a></td>"); |
99 | html("</tr>\n"); | 104 | html("</tr>\n"); |
100 | free(name); | 105 | free(name); |
101 | return 0; | 106 | return 0; |
102 | } | 107 | } |
103 | 108 | ||
104 | static void ls_head() | 109 | static void ls_head() |
105 | { | 110 | { |
106 | html("<table class='list'>\n"); | 111 | html("<table class='list'>\n"); |
107 | html("<tr class='nohover'>"); | 112 | html("<tr class='nohover'>"); |
108 | html("<th class='left'>Mode</th>"); | 113 | html("<th class='left'>Mode</th>"); |
109 | html("<th class='left'>Name</th>"); | 114 | html("<th class='left'>Name</th>"); |
110 | html("<th class='right'>Size</th>"); | 115 | html("<th class='right'>Size</th>"); |
111 | html("<th/>"); | 116 | html("<th/>"); |
112 | html("</tr>\n"); | 117 | html("</tr>\n"); |
113 | header = 1; | 118 | header = 1; |
114 | } | 119 | } |
@@ -129,53 +134,51 @@ static void ls_tree(const unsigned char *sha1, char *path) | |||
129 | if (!tree) { | 134 | if (!tree) { |
130 | cgit_print_error(fmt("Not a tree object: %s", | 135 | cgit_print_error(fmt("Not a tree object: %s", |
131 | sha1_to_hex(sha1))); | 136 | sha1_to_hex(sha1))); |
132 | return; | 137 | return; |
133 | } | 138 | } |
134 | 139 | ||
135 | ls_head(); | 140 | ls_head(); |
136 | read_tree_recursive(tree, "", 0, 1, NULL, ls_item); | 141 | read_tree_recursive(tree, "", 0, 1, NULL, ls_item); |
137 | ls_tail(); | 142 | ls_tail(); |
138 | } | 143 | } |
139 | 144 | ||
140 | 145 | ||
141 | static int walk_tree(const unsigned char *sha1, const char *base, int baselen, | 146 | static int walk_tree(const unsigned char *sha1, const char *base, int baselen, |
142 | const char *pathname, unsigned mode, int stage) | 147 | const char *pathname, unsigned mode, int stage) |
143 | { | 148 | { |
144 | static int state; | 149 | static int state; |
145 | static char buffer[PATH_MAX]; | 150 | static char buffer[PATH_MAX]; |
146 | char *url; | 151 | char *url; |
147 | 152 | ||
148 | if (state == 0) { | 153 | if (state == 0) { |
149 | memcpy(buffer, base, baselen); | 154 | memcpy(buffer, base, baselen); |
150 | strcpy(buffer+baselen, pathname); | 155 | strcpy(buffer+baselen, pathname); |
151 | url = cgit_pageurl(cgit_query_repo, "tree", | 156 | url = cgit_pageurl(cgit_query_repo, "tree", |
152 | fmt("h=%s&path=%s", curr_rev, buffer)); | 157 | fmt("h=%s&path=%s", curr_rev, buffer)); |
153 | htmlf(" / <a href='"); | 158 | html("/"); |
154 | html_attr(url); | 159 | cgit_tree_link(xstrdup(pathname), NULL, NULL, cgit_query_head, |
155 | html("'>"); | 160 | curr_rev, buffer); |
156 | html_txt(xstrdup(pathname)); | ||
157 | html("</a>"); | ||
158 | 161 | ||
159 | if (strcmp(match_path, buffer)) | 162 | if (strcmp(match_path, buffer)) |
160 | return READ_TREE_RECURSIVE; | 163 | return READ_TREE_RECURSIVE; |
161 | 164 | ||
162 | if (S_ISDIR(mode)) { | 165 | if (S_ISDIR(mode)) { |
163 | state = 1; | 166 | state = 1; |
164 | ls_head(); | 167 | ls_head(); |
165 | return READ_TREE_RECURSIVE; | 168 | return READ_TREE_RECURSIVE; |
166 | } else { | 169 | } else { |
167 | print_object(sha1, buffer); | 170 | print_object(sha1, buffer); |
168 | return 0; | 171 | return 0; |
169 | } | 172 | } |
170 | } | 173 | } |
171 | ls_item(sha1, base, baselen, pathname, mode, stage); | 174 | ls_item(sha1, base, baselen, pathname, mode, stage); |
172 | return 0; | 175 | return 0; |
173 | } | 176 | } |
174 | 177 | ||
175 | 178 | ||
176 | /* | 179 | /* |
177 | * Show a tree or a blob | 180 | * Show a tree or a blob |
178 | * rev: the commit pointing at the root tree object | 181 | * rev: the commit pointing at the root tree object |
179 | * path: path to tree or blob | 182 | * path: path to tree or blob |
180 | */ | 183 | */ |
181 | void cgit_print_tree(const char *rev, char *path) | 184 | void cgit_print_tree(const char *rev, char *path) |