-rw-r--r-- | cgit.c | 1 | ||||
-rw-r--r-- | cgit.h | 32 | ||||
-rw-r--r-- | ui-blob.c | 1 | ||||
-rw-r--r-- | ui-commit.c | 1 | ||||
-rw-r--r-- | ui-diff.c | 1 | ||||
-rw-r--r-- | ui-log.c | 1 | ||||
-rw-r--r-- | ui-patch.c | 1 | ||||
-rw-r--r-- | ui-refs.c | 1 | ||||
-rw-r--r-- | ui-repolist.c | 1 | ||||
-rw-r--r-- | ui-shared.h | 36 | ||||
-rw-r--r-- | ui-snapshot.c | 1 | ||||
-rw-r--r-- | ui-tag.c | 1 | ||||
-rw-r--r-- | ui-tree.c | 1 |
13 files changed, 47 insertions, 32 deletions
@@ -1,138 +1,139 @@ | |||
1 | /* cgit.c: cgi for the git scm | 1 | /* cgit.c: cgi for the git scm |
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 "cgit.h" | 9 | #include "cgit.h" |
10 | #include "cmd.h" | 10 | #include "cmd.h" |
11 | #include "ui-shared.h" | ||
11 | 12 | ||
12 | static int cgit_prepare_cache(struct cacheitem *item) | 13 | static int cgit_prepare_cache(struct cacheitem *item) |
13 | { | 14 | { |
14 | if (!ctx.repo && ctx.qry.repo) { | 15 | if (!ctx.repo && ctx.qry.repo) { |
15 | ctx.page.title = fmt("%s - %s", ctx.cfg.root_title, | 16 | ctx.page.title = fmt("%s - %s", ctx.cfg.root_title, |
16 | "Bad request"); | 17 | "Bad request"); |
17 | cgit_print_http_headers(&ctx); | 18 | cgit_print_http_headers(&ctx); |
18 | cgit_print_docstart(&ctx); | 19 | cgit_print_docstart(&ctx); |
19 | cgit_print_pageheader(&ctx); | 20 | cgit_print_pageheader(&ctx); |
20 | cgit_print_error(fmt("Unknown repo: %s", ctx.qry.repo)); | 21 | cgit_print_error(fmt("Unknown repo: %s", ctx.qry.repo)); |
21 | cgit_print_docend(); | 22 | cgit_print_docend(); |
22 | return 0; | 23 | return 0; |
23 | } | 24 | } |
24 | 25 | ||
25 | if (!ctx.repo) { | 26 | if (!ctx.repo) { |
26 | item->name = xstrdup(fmt("%s/index.html", ctx.cfg.cache_root)); | 27 | item->name = xstrdup(fmt("%s/index.html", ctx.cfg.cache_root)); |
27 | item->ttl = ctx.cfg.cache_root_ttl; | 28 | item->ttl = ctx.cfg.cache_root_ttl; |
28 | return 1; | 29 | return 1; |
29 | } | 30 | } |
30 | 31 | ||
31 | if (!cgit_cmd) { | 32 | if (!cgit_cmd) { |
32 | item->name = xstrdup(fmt("%s/%s/index.%s.html", ctx.cfg.cache_root, | 33 | item->name = xstrdup(fmt("%s/%s/index.%s.html", ctx.cfg.cache_root, |
33 | cache_safe_filename(ctx.repo->url), | 34 | cache_safe_filename(ctx.repo->url), |
34 | cache_safe_filename(ctx.qry.raw))); | 35 | cache_safe_filename(ctx.qry.raw))); |
35 | item->ttl = ctx.cfg.cache_repo_ttl; | 36 | item->ttl = ctx.cfg.cache_repo_ttl; |
36 | } else { | 37 | } else { |
37 | item->name = xstrdup(fmt("%s/%s/%s/%s.html", ctx.cfg.cache_root, | 38 | item->name = xstrdup(fmt("%s/%s/%s/%s.html", ctx.cfg.cache_root, |
38 | cache_safe_filename(ctx.repo->url), | 39 | cache_safe_filename(ctx.repo->url), |
39 | ctx.qry.page, | 40 | ctx.qry.page, |
40 | cache_safe_filename(ctx.qry.raw))); | 41 | cache_safe_filename(ctx.qry.raw))); |
41 | if (ctx.qry.has_symref) | 42 | if (ctx.qry.has_symref) |
42 | item->ttl = ctx.cfg.cache_dynamic_ttl; | 43 | item->ttl = ctx.cfg.cache_dynamic_ttl; |
43 | else if (ctx.qry.has_sha1) | 44 | else if (ctx.qry.has_sha1) |
44 | item->ttl = ctx.cfg.cache_static_ttl; | 45 | item->ttl = ctx.cfg.cache_static_ttl; |
45 | else | 46 | else |
46 | item->ttl = ctx.cfg.cache_repo_ttl; | 47 | item->ttl = ctx.cfg.cache_repo_ttl; |
47 | } | 48 | } |
48 | return 1; | 49 | return 1; |
49 | } | 50 | } |
50 | 51 | ||
51 | struct refmatch { | 52 | struct refmatch { |
52 | char *req_ref; | 53 | char *req_ref; |
53 | char *first_ref; | 54 | char *first_ref; |
54 | int match; | 55 | int match; |
55 | }; | 56 | }; |
56 | 57 | ||
57 | int find_current_ref(const char *refname, const unsigned char *sha1, | 58 | int find_current_ref(const char *refname, const unsigned char *sha1, |
58 | int flags, void *cb_data) | 59 | int flags, void *cb_data) |
59 | { | 60 | { |
60 | struct refmatch *info; | 61 | struct refmatch *info; |
61 | 62 | ||
62 | info = (struct refmatch *)cb_data; | 63 | info = (struct refmatch *)cb_data; |
63 | if (!strcmp(refname, info->req_ref)) | 64 | if (!strcmp(refname, info->req_ref)) |
64 | info->match = 1; | 65 | info->match = 1; |
65 | if (!info->first_ref) | 66 | if (!info->first_ref) |
66 | info->first_ref = xstrdup(refname); | 67 | info->first_ref = xstrdup(refname); |
67 | return info->match; | 68 | return info->match; |
68 | } | 69 | } |
69 | 70 | ||
70 | char *find_default_branch(struct cgit_repo *repo) | 71 | char *find_default_branch(struct cgit_repo *repo) |
71 | { | 72 | { |
72 | struct refmatch info; | 73 | struct refmatch info; |
73 | 74 | ||
74 | info.req_ref = repo->defbranch; | 75 | info.req_ref = repo->defbranch; |
75 | info.first_ref = NULL; | 76 | info.first_ref = NULL; |
76 | info.match = 0; | 77 | info.match = 0; |
77 | for_each_branch_ref(find_current_ref, &info); | 78 | for_each_branch_ref(find_current_ref, &info); |
78 | if (info.match) | 79 | if (info.match) |
79 | return info.req_ref; | 80 | return info.req_ref; |
80 | else | 81 | else |
81 | return info.first_ref; | 82 | return info.first_ref; |
82 | } | 83 | } |
83 | 84 | ||
84 | static int prepare_repo_cmd(struct cgit_context *ctx) | 85 | static int prepare_repo_cmd(struct cgit_context *ctx) |
85 | { | 86 | { |
86 | char *tmp; | 87 | char *tmp; |
87 | unsigned char sha1[20]; | 88 | unsigned char sha1[20]; |
88 | int nongit = 0; | 89 | int nongit = 0; |
89 | 90 | ||
90 | setenv("GIT_DIR", ctx->repo->path, 1); | 91 | setenv("GIT_DIR", ctx->repo->path, 1); |
91 | setup_git_directory_gently(&nongit); | 92 | setup_git_directory_gently(&nongit); |
92 | if (nongit) { | 93 | if (nongit) { |
93 | ctx->page.title = fmt("%s - %s", ctx->cfg.root_title, | 94 | ctx->page.title = fmt("%s - %s", ctx->cfg.root_title, |
94 | "config error"); | 95 | "config error"); |
95 | tmp = fmt("Not a git repository: '%s'", ctx->repo->path); | 96 | tmp = fmt("Not a git repository: '%s'", ctx->repo->path); |
96 | ctx->repo = NULL; | 97 | ctx->repo = NULL; |
97 | cgit_print_http_headers(ctx); | 98 | cgit_print_http_headers(ctx); |
98 | cgit_print_docstart(ctx); | 99 | cgit_print_docstart(ctx); |
99 | cgit_print_pageheader(ctx); | 100 | cgit_print_pageheader(ctx); |
100 | cgit_print_error(tmp); | 101 | cgit_print_error(tmp); |
101 | cgit_print_docend(); | 102 | cgit_print_docend(); |
102 | return 1; | 103 | return 1; |
103 | } | 104 | } |
104 | ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc); | 105 | ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc); |
105 | 106 | ||
106 | if (!ctx->qry.head) { | 107 | if (!ctx->qry.head) { |
107 | ctx->qry.head = xstrdup(find_default_branch(ctx->repo)); | 108 | ctx->qry.head = xstrdup(find_default_branch(ctx->repo)); |
108 | ctx->repo->defbranch = ctx->qry.head; | 109 | ctx->repo->defbranch = ctx->qry.head; |
109 | } | 110 | } |
110 | 111 | ||
111 | if (!ctx->qry.head) { | 112 | if (!ctx->qry.head) { |
112 | cgit_print_http_headers(ctx); | 113 | cgit_print_http_headers(ctx); |
113 | cgit_print_docstart(ctx); | 114 | cgit_print_docstart(ctx); |
114 | cgit_print_pageheader(ctx); | 115 | cgit_print_pageheader(ctx); |
115 | cgit_print_error("Repository seems to be empty"); | 116 | cgit_print_error("Repository seems to be empty"); |
116 | cgit_print_docend(); | 117 | cgit_print_docend(); |
117 | return 1; | 118 | return 1; |
118 | } | 119 | } |
119 | 120 | ||
120 | if (get_sha1(ctx->qry.head, sha1)) { | 121 | if (get_sha1(ctx->qry.head, sha1)) { |
121 | tmp = xstrdup(ctx->qry.head); | 122 | tmp = xstrdup(ctx->qry.head); |
122 | ctx->qry.head = ctx->repo->defbranch; | 123 | ctx->qry.head = ctx->repo->defbranch; |
123 | cgit_print_http_headers(ctx); | 124 | cgit_print_http_headers(ctx); |
124 | cgit_print_docstart(ctx); | 125 | cgit_print_docstart(ctx); |
125 | cgit_print_pageheader(ctx); | 126 | cgit_print_pageheader(ctx); |
126 | cgit_print_error(fmt("Invalid branch: %s", tmp)); | 127 | cgit_print_error(fmt("Invalid branch: %s", tmp)); |
127 | cgit_print_docend(); | 128 | cgit_print_docend(); |
128 | return 1; | 129 | return 1; |
129 | } | 130 | } |
130 | return 0; | 131 | return 0; |
131 | } | 132 | } |
132 | 133 | ||
133 | static void process_request(struct cgit_context *ctx) | 134 | static void process_request(struct cgit_context *ctx) |
134 | { | 135 | { |
135 | struct cgit_cmd *cmd; | 136 | struct cgit_cmd *cmd; |
136 | 137 | ||
137 | cmd = cgit_get_cmd(ctx); | 138 | cmd = cgit_get_cmd(ctx); |
138 | if (!cmd) { | 139 | if (!cmd) { |
@@ -112,165 +112,133 @@ struct reflist { | |||
112 | 112 | ||
113 | struct cgit_query { | 113 | struct cgit_query { |
114 | int has_symref; | 114 | int has_symref; |
115 | int has_sha1; | 115 | int has_sha1; |
116 | char *raw; | 116 | char *raw; |
117 | char *repo; | 117 | char *repo; |
118 | char *page; | 118 | char *page; |
119 | char *search; | 119 | char *search; |
120 | char *grep; | 120 | char *grep; |
121 | char *head; | 121 | char *head; |
122 | char *sha1; | 122 | char *sha1; |
123 | char *sha2; | 123 | char *sha2; |
124 | char *path; | 124 | char *path; |
125 | char *name; | 125 | char *name; |
126 | int ofs; | 126 | int ofs; |
127 | }; | 127 | }; |
128 | 128 | ||
129 | struct cgit_config { | 129 | struct cgit_config { |
130 | char *agefile; | 130 | char *agefile; |
131 | char *cache_root; | 131 | char *cache_root; |
132 | char *clone_prefix; | 132 | char *clone_prefix; |
133 | char *css; | 133 | char *css; |
134 | char *index_header; | 134 | char *index_header; |
135 | char *index_info; | 135 | char *index_info; |
136 | char *logo; | 136 | char *logo; |
137 | char *logo_link; | 137 | char *logo_link; |
138 | char *module_link; | 138 | char *module_link; |
139 | char *repo_group; | 139 | char *repo_group; |
140 | char *robots; | 140 | char *robots; |
141 | char *root_title; | 141 | char *root_title; |
142 | char *script_name; | 142 | char *script_name; |
143 | char *virtual_root; | 143 | char *virtual_root; |
144 | int cache_dynamic_ttl; | 144 | int cache_dynamic_ttl; |
145 | int cache_max_create_time; | 145 | int cache_max_create_time; |
146 | int cache_repo_ttl; | 146 | int cache_repo_ttl; |
147 | int cache_root_ttl; | 147 | int cache_root_ttl; |
148 | int cache_static_ttl; | 148 | int cache_static_ttl; |
149 | int enable_index_links; | 149 | int enable_index_links; |
150 | int enable_log_filecount; | 150 | int enable_log_filecount; |
151 | int enable_log_linecount; | 151 | int enable_log_linecount; |
152 | int max_commit_count; | 152 | int max_commit_count; |
153 | int max_lock_attempts; | 153 | int max_lock_attempts; |
154 | int max_msg_len; | 154 | int max_msg_len; |
155 | int max_repodesc_len; | 155 | int max_repodesc_len; |
156 | int nocache; | 156 | int nocache; |
157 | int renamelimit; | 157 | int renamelimit; |
158 | int snapshots; | 158 | int snapshots; |
159 | int summary_branches; | 159 | int summary_branches; |
160 | int summary_log; | 160 | int summary_log; |
161 | int summary_tags; | 161 | int summary_tags; |
162 | }; | 162 | }; |
163 | 163 | ||
164 | struct cgit_page { | 164 | struct cgit_page { |
165 | time_t modified; | 165 | time_t modified; |
166 | time_t expires; | 166 | time_t expires; |
167 | char *mimetype; | 167 | char *mimetype; |
168 | char *charset; | 168 | char *charset; |
169 | char *filename; | 169 | char *filename; |
170 | char *title; | 170 | char *title; |
171 | }; | 171 | }; |
172 | 172 | ||
173 | struct cgit_context { | 173 | struct cgit_context { |
174 | struct cgit_query qry; | 174 | struct cgit_query qry; |
175 | struct cgit_config cfg; | 175 | struct cgit_config cfg; |
176 | struct cgit_repo *repo; | 176 | struct cgit_repo *repo; |
177 | struct cgit_page page; | 177 | struct cgit_page page; |
178 | }; | 178 | }; |
179 | 179 | ||
180 | struct cgit_snapshot_format { | 180 | struct cgit_snapshot_format { |
181 | const char *suffix; | 181 | const char *suffix; |
182 | const char *mimetype; | 182 | const char *mimetype; |
183 | write_archive_fn_t write_func; | 183 | write_archive_fn_t write_func; |
184 | int bit; | 184 | int bit; |
185 | }; | 185 | }; |
186 | 186 | ||
187 | extern const char *cgit_version; | 187 | extern const char *cgit_version; |
188 | 188 | ||
189 | extern struct cgit_repolist cgit_repolist; | 189 | extern struct cgit_repolist cgit_repolist; |
190 | extern struct cgit_context ctx; | 190 | extern struct cgit_context ctx; |
191 | extern const struct cgit_snapshot_format cgit_snapshot_formats[]; | 191 | extern const struct cgit_snapshot_format cgit_snapshot_formats[]; |
192 | extern int cgit_cmd; | 192 | extern int cgit_cmd; |
193 | 193 | ||
194 | extern void cgit_prepare_context(struct cgit_context *ctx); | 194 | extern void cgit_prepare_context(struct cgit_context *ctx); |
195 | extern struct cgit_repo *cgit_get_repoinfo(const char *url); | 195 | extern struct cgit_repo *cgit_get_repoinfo(const char *url); |
196 | extern void cgit_global_config_cb(const char *name, const char *value); | 196 | extern void cgit_global_config_cb(const char *name, const char *value); |
197 | extern void cgit_repo_config_cb(const char *name, const char *value); | 197 | extern void cgit_repo_config_cb(const char *name, const char *value); |
198 | extern void cgit_querystring_cb(const char *name, const char *value); | 198 | extern void cgit_querystring_cb(const char *name, const char *value); |
199 | 199 | ||
200 | extern int chk_zero(int result, char *msg); | 200 | extern int chk_zero(int result, char *msg); |
201 | extern int chk_positive(int result, char *msg); | 201 | extern int chk_positive(int result, char *msg); |
202 | extern int chk_non_negative(int result, char *msg); | 202 | extern int chk_non_negative(int result, char *msg); |
203 | 203 | ||
204 | extern int hextoint(char c); | 204 | extern int hextoint(char c); |
205 | extern char *trim_end(const char *str, char c); | 205 | extern char *trim_end(const char *str, char c); |
206 | extern char *strlpart(char *txt, int maxlen); | 206 | extern char *strlpart(char *txt, int maxlen); |
207 | extern char *strrpart(char *txt, int maxlen); | 207 | extern char *strrpart(char *txt, int maxlen); |
208 | 208 | ||
209 | extern void cgit_add_ref(struct reflist *list, struct refinfo *ref); | 209 | extern void cgit_add_ref(struct reflist *list, struct refinfo *ref); |
210 | extern int cgit_refs_cb(const char *refname, const unsigned char *sha1, | 210 | extern int cgit_refs_cb(const char *refname, const unsigned char *sha1, |
211 | int flags, void *cb_data); | 211 | int flags, void *cb_data); |
212 | 212 | ||
213 | extern void *cgit_free_commitinfo(struct commitinfo *info); | 213 | extern void *cgit_free_commitinfo(struct commitinfo *info); |
214 | 214 | ||
215 | extern int cgit_diff_files(const unsigned char *old_sha1, | 215 | extern int cgit_diff_files(const unsigned char *old_sha1, |
216 | const unsigned char *new_sha1, | 216 | const unsigned char *new_sha1, |
217 | linediff_fn fn); | 217 | linediff_fn fn); |
218 | 218 | ||
219 | extern void cgit_diff_tree(const unsigned char *old_sha1, | 219 | extern void cgit_diff_tree(const unsigned char *old_sha1, |
220 | const unsigned char *new_sha1, | 220 | const unsigned char *new_sha1, |
221 | filepair_fn fn, const char *prefix); | 221 | filepair_fn fn, const char *prefix); |
222 | 222 | ||
223 | extern void cgit_diff_commit(struct commit *commit, filepair_fn fn); | 223 | extern void cgit_diff_commit(struct commit *commit, filepair_fn fn); |
224 | 224 | ||
225 | extern char *fmt(const char *format,...); | 225 | extern char *fmt(const char *format,...); |
226 | 226 | ||
227 | extern int cgit_read_config(const char *filename, configfn fn); | 227 | extern int cgit_read_config(const char *filename, configfn fn); |
228 | extern int cgit_parse_query(char *txt, configfn fn); | 228 | extern int cgit_parse_query(char *txt, configfn fn); |
229 | extern struct commitinfo *cgit_parse_commit(struct commit *commit); | 229 | extern struct commitinfo *cgit_parse_commit(struct commit *commit); |
230 | extern struct taginfo *cgit_parse_tag(struct tag *tag); | 230 | extern struct taginfo *cgit_parse_tag(struct tag *tag); |
231 | extern void cgit_parse_url(const char *url); | 231 | extern void cgit_parse_url(const char *url); |
232 | 232 | ||
233 | extern char *cache_safe_filename(const char *unsafe); | 233 | extern char *cache_safe_filename(const char *unsafe); |
234 | extern int cache_lock(struct cacheitem *item); | 234 | extern int cache_lock(struct cacheitem *item); |
235 | extern int cache_unlock(struct cacheitem *item); | 235 | extern int cache_unlock(struct cacheitem *item); |
236 | extern int cache_cancel_lock(struct cacheitem *item); | 236 | extern int cache_cancel_lock(struct cacheitem *item); |
237 | extern int cache_exist(struct cacheitem *item); | 237 | extern int cache_exist(struct cacheitem *item); |
238 | extern int cache_expired(struct cacheitem *item); | 238 | extern int cache_expired(struct cacheitem *item); |
239 | 239 | ||
240 | extern char *cgit_repourl(const char *reponame); | ||
241 | extern char *cgit_fileurl(const char *reponame, const char *pagename, | ||
242 | const char *filename, const char *query); | ||
243 | extern char *cgit_pageurl(const char *reponame, const char *pagename, | ||
244 | const char *query); | ||
245 | |||
246 | extern const char *cgit_repobasename(const char *reponame); | 240 | extern const char *cgit_repobasename(const char *reponame); |
247 | 241 | ||
248 | extern void cgit_tree_link(char *name, char *title, char *class, char *head, | ||
249 | char *rev, char *path); | ||
250 | extern void cgit_log_link(char *name, char *title, char *class, char *head, | ||
251 | char *rev, char *path, int ofs, char *grep, | ||
252 | char *pattern); | ||
253 | extern void cgit_commit_link(char *name, char *title, char *class, char *head, | ||
254 | char *rev); | ||
255 | extern void cgit_refs_link(char *name, char *title, char *class, char *head, | ||
256 | char *rev, char *path); | ||
257 | extern void cgit_snapshot_link(char *name, char *title, char *class, | ||
258 | char *head, char *rev, char *archivename); | ||
259 | extern void cgit_diff_link(char *name, char *title, char *class, char *head, | ||
260 | char *new_rev, char *old_rev, char *path); | ||
261 | |||
262 | extern void cgit_object_link(struct object *obj); | ||
263 | |||
264 | extern void cgit_print_error(char *msg); | ||
265 | extern void cgit_print_date(time_t secs, char *format); | ||
266 | extern void cgit_print_age(time_t t, time_t max_relative, char *format); | ||
267 | extern void cgit_print_http_headers(struct cgit_context *ctx); | ||
268 | extern void cgit_print_docstart(struct cgit_context *ctx); | ||
269 | extern void cgit_print_docend(); | ||
270 | extern void cgit_print_pageheader(struct cgit_context *ctx); | ||
271 | extern void cgit_print_filemode(unsigned short mode); | ||
272 | extern void cgit_print_snapshot_links(const char *repo, const char *head, | ||
273 | const char *hex, int snapshots); | ||
274 | extern int cgit_parse_snapshots_mask(const char *str); | 242 | extern int cgit_parse_snapshots_mask(const char *str); |
275 | 243 | ||
276 | #endif /* CGIT_H */ | 244 | #endif /* CGIT_H */ |
@@ -1,42 +1,43 @@ | |||
1 | /* ui-blob.c: show blob content | 1 | /* ui-blob.c: show blob content |
2 | * | 2 | * |
3 | * Copyright (C) 2008 Lars Hjemli | 3 | * Copyright (C) 2008 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 "cgit.h" | 9 | #include "cgit.h" |
10 | #include "html.h" | 10 | #include "html.h" |
11 | #include "ui-shared.h" | ||
11 | 12 | ||
12 | void cgit_print_blob(const char *hex, char *path) | 13 | void cgit_print_blob(const char *hex, char *path) |
13 | { | 14 | { |
14 | 15 | ||
15 | unsigned char sha1[20]; | 16 | unsigned char sha1[20]; |
16 | enum object_type type; | 17 | enum object_type type; |
17 | unsigned char *buf; | 18 | unsigned char *buf; |
18 | unsigned long size; | 19 | unsigned long size; |
19 | 20 | ||
20 | if (get_sha1_hex(hex, sha1)){ | 21 | if (get_sha1_hex(hex, sha1)){ |
21 | cgit_print_error(fmt("Bad hex value: %s", hex)); | 22 | cgit_print_error(fmt("Bad hex value: %s", hex)); |
22 | return; | 23 | return; |
23 | } | 24 | } |
24 | 25 | ||
25 | type = sha1_object_info(sha1, &size); | 26 | type = sha1_object_info(sha1, &size); |
26 | if (type == OBJ_BAD) { | 27 | if (type == OBJ_BAD) { |
27 | cgit_print_error(fmt("Bad object name: %s", hex)); | 28 | cgit_print_error(fmt("Bad object name: %s", hex)); |
28 | return; | 29 | return; |
29 | } | 30 | } |
30 | 31 | ||
31 | buf = read_sha1_file(sha1, &type, &size); | 32 | buf = read_sha1_file(sha1, &type, &size); |
32 | if (!buf) { | 33 | if (!buf) { |
33 | cgit_print_error(fmt("Error reading object %s", hex)); | 34 | cgit_print_error(fmt("Error reading object %s", hex)); |
34 | return; | 35 | return; |
35 | } | 36 | } |
36 | 37 | ||
37 | buf[size] = '\0'; | 38 | buf[size] = '\0'; |
38 | ctx.page.mimetype = "text/plain"; | 39 | ctx.page.mimetype = "text/plain"; |
39 | ctx.page.filename = path; | 40 | ctx.page.filename = path; |
40 | cgit_print_http_headers(&ctx); | 41 | cgit_print_http_headers(&ctx); |
41 | write(htmlfd, buf, size); | 42 | write(htmlfd, buf, size); |
42 | } | 43 | } |
diff --git a/ui-commit.c b/ui-commit.c index ed25824..8019e36 100644 --- a/ui-commit.c +++ b/ui-commit.c | |||
@@ -1,138 +1,139 @@ | |||
1 | /* ui-commit.c: generate commit view | 1 | /* ui-commit.c: generate commit view |
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 "cgit.h" | 9 | #include "cgit.h" |
10 | #include "html.h" | 10 | #include "html.h" |
11 | #include "ui-shared.h" | ||
11 | 12 | ||
12 | static int files, slots; | 13 | static int files, slots; |
13 | static int total_adds, total_rems, max_changes; | 14 | static int total_adds, total_rems, max_changes; |
14 | static int lines_added, lines_removed; | 15 | static int lines_added, lines_removed; |
15 | static char *curr_rev; | 16 | static char *curr_rev; |
16 | 17 | ||
17 | static struct fileinfo { | 18 | static struct fileinfo { |
18 | char status; | 19 | char status; |
19 | unsigned char old_sha1[20]; | 20 | unsigned char old_sha1[20]; |
20 | unsigned char new_sha1[20]; | 21 | unsigned char new_sha1[20]; |
21 | unsigned short old_mode; | 22 | unsigned short old_mode; |
22 | unsigned short new_mode; | 23 | unsigned short new_mode; |
23 | char *old_path; | 24 | char *old_path; |
24 | char *new_path; | 25 | char *new_path; |
25 | unsigned int added; | 26 | unsigned int added; |
26 | unsigned int removed; | 27 | unsigned int removed; |
27 | } *items; | 28 | } *items; |
28 | 29 | ||
29 | 30 | ||
30 | void print_fileinfo(struct fileinfo *info) | 31 | void print_fileinfo(struct fileinfo *info) |
31 | { | 32 | { |
32 | char *class; | 33 | char *class; |
33 | 34 | ||
34 | switch (info->status) { | 35 | switch (info->status) { |
35 | case DIFF_STATUS_ADDED: | 36 | case DIFF_STATUS_ADDED: |
36 | class = "add"; | 37 | class = "add"; |
37 | break; | 38 | break; |
38 | case DIFF_STATUS_COPIED: | 39 | case DIFF_STATUS_COPIED: |
39 | class = "cpy"; | 40 | class = "cpy"; |
40 | break; | 41 | break; |
41 | case DIFF_STATUS_DELETED: | 42 | case DIFF_STATUS_DELETED: |
42 | class = "del"; | 43 | class = "del"; |
43 | break; | 44 | break; |
44 | case DIFF_STATUS_MODIFIED: | 45 | case DIFF_STATUS_MODIFIED: |
45 | class = "upd"; | 46 | class = "upd"; |
46 | break; | 47 | break; |
47 | case DIFF_STATUS_RENAMED: | 48 | case DIFF_STATUS_RENAMED: |
48 | class = "mov"; | 49 | class = "mov"; |
49 | break; | 50 | break; |
50 | case DIFF_STATUS_TYPE_CHANGED: | 51 | case DIFF_STATUS_TYPE_CHANGED: |
51 | class = "typ"; | 52 | class = "typ"; |
52 | break; | 53 | break; |
53 | case DIFF_STATUS_UNKNOWN: | 54 | case DIFF_STATUS_UNKNOWN: |
54 | class = "unk"; | 55 | class = "unk"; |
55 | break; | 56 | break; |
56 | case DIFF_STATUS_UNMERGED: | 57 | case DIFF_STATUS_UNMERGED: |
57 | class = "stg"; | 58 | class = "stg"; |
58 | break; | 59 | break; |
59 | default: | 60 | default: |
60 | die("bug: unhandled diff status %c", info->status); | 61 | die("bug: unhandled diff status %c", info->status); |
61 | } | 62 | } |
62 | 63 | ||
63 | html("<tr>"); | 64 | html("<tr>"); |
64 | htmlf("<td class='mode'>"); | 65 | htmlf("<td class='mode'>"); |
65 | if (is_null_sha1(info->new_sha1)) { | 66 | if (is_null_sha1(info->new_sha1)) { |
66 | cgit_print_filemode(info->old_mode); | 67 | cgit_print_filemode(info->old_mode); |
67 | } else { | 68 | } else { |
68 | cgit_print_filemode(info->new_mode); | 69 | cgit_print_filemode(info->new_mode); |
69 | } | 70 | } |
70 | 71 | ||
71 | if (info->old_mode != info->new_mode && | 72 | if (info->old_mode != info->new_mode && |
72 | !is_null_sha1(info->old_sha1) && | 73 | !is_null_sha1(info->old_sha1) && |
73 | !is_null_sha1(info->new_sha1)) { | 74 | !is_null_sha1(info->new_sha1)) { |
74 | html("<span class='modechange'>["); | 75 | html("<span class='modechange'>["); |
75 | cgit_print_filemode(info->old_mode); | 76 | cgit_print_filemode(info->old_mode); |
76 | html("]</span>"); | 77 | html("]</span>"); |
77 | } | 78 | } |
78 | htmlf("</td><td class='%s'>", class); | 79 | htmlf("</td><td class='%s'>", class); |
79 | cgit_diff_link(info->new_path, NULL, NULL, ctx.qry.head, curr_rev, | 80 | cgit_diff_link(info->new_path, NULL, NULL, ctx.qry.head, curr_rev, |
80 | NULL, info->new_path); | 81 | NULL, info->new_path); |
81 | if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED) | 82 | if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED) |
82 | htmlf(" (%s from %s)", | 83 | htmlf(" (%s from %s)", |
83 | info->status == DIFF_STATUS_COPIED ? "copied" : "renamed", | 84 | info->status == DIFF_STATUS_COPIED ? "copied" : "renamed", |
84 | info->old_path); | 85 | info->old_path); |
85 | html("</td><td class='right'>"); | 86 | html("</td><td class='right'>"); |
86 | htmlf("%d", info->added + info->removed); | 87 | htmlf("%d", info->added + info->removed); |
87 | html("</td><td class='graph'>"); | 88 | html("</td><td class='graph'>"); |
88 | htmlf("<table summary='file diffstat' width='%d%%'><tr>", (max_changes > 100 ? 100 : max_changes)); | 89 | htmlf("<table summary='file diffstat' width='%d%%'><tr>", (max_changes > 100 ? 100 : max_changes)); |
89 | htmlf("<td class='add' style='width: %.1f%%;'/>", | 90 | htmlf("<td class='add' style='width: %.1f%%;'/>", |
90 | info->added * 100.0 / max_changes); | 91 | info->added * 100.0 / max_changes); |
91 | htmlf("<td class='rem' style='width: %.1f%%;'/>", | 92 | htmlf("<td class='rem' style='width: %.1f%%;'/>", |
92 | info->removed * 100.0 / max_changes); | 93 | info->removed * 100.0 / max_changes); |
93 | htmlf("<td class='none' style='width: %.1f%%;'/>", | 94 | htmlf("<td class='none' style='width: %.1f%%;'/>", |
94 | (max_changes - info->removed - info->added) * 100.0 / max_changes); | 95 | (max_changes - info->removed - info->added) * 100.0 / max_changes); |
95 | html("</tr></table></td></tr>\n"); | 96 | html("</tr></table></td></tr>\n"); |
96 | } | 97 | } |
97 | 98 | ||
98 | void cgit_count_diff_lines(char *line, int len) | 99 | void cgit_count_diff_lines(char *line, int len) |
99 | { | 100 | { |
100 | if (line && (len > 0)) { | 101 | if (line && (len > 0)) { |
101 | if (line[0] == '+') | 102 | if (line[0] == '+') |
102 | lines_added++; | 103 | lines_added++; |
103 | else if (line[0] == '-') | 104 | else if (line[0] == '-') |
104 | lines_removed++; | 105 | lines_removed++; |
105 | } | 106 | } |
106 | } | 107 | } |
107 | 108 | ||
108 | void inspect_filepair(struct diff_filepair *pair) | 109 | void inspect_filepair(struct diff_filepair *pair) |
109 | { | 110 | { |
110 | files++; | 111 | files++; |
111 | lines_added = 0; | 112 | lines_added = 0; |
112 | lines_removed = 0; | 113 | lines_removed = 0; |
113 | cgit_diff_files(pair->one->sha1, pair->two->sha1, cgit_count_diff_lines); | 114 | cgit_diff_files(pair->one->sha1, pair->two->sha1, cgit_count_diff_lines); |
114 | if (files >= slots) { | 115 | if (files >= slots) { |
115 | if (slots == 0) | 116 | if (slots == 0) |
116 | slots = 4; | 117 | slots = 4; |
117 | else | 118 | else |
118 | slots = slots * 2; | 119 | slots = slots * 2; |
119 | items = xrealloc(items, slots * sizeof(struct fileinfo)); | 120 | items = xrealloc(items, slots * sizeof(struct fileinfo)); |
120 | } | 121 | } |
121 | items[files-1].status = pair->status; | 122 | items[files-1].status = pair->status; |
122 | hashcpy(items[files-1].old_sha1, pair->one->sha1); | 123 | hashcpy(items[files-1].old_sha1, pair->one->sha1); |
123 | hashcpy(items[files-1].new_sha1, pair->two->sha1); | 124 | hashcpy(items[files-1].new_sha1, pair->two->sha1); |
124 | items[files-1].old_mode = pair->one->mode; | 125 | items[files-1].old_mode = pair->one->mode; |
125 | items[files-1].new_mode = pair->two->mode; | 126 | items[files-1].new_mode = pair->two->mode; |
126 | items[files-1].old_path = xstrdup(pair->one->path); | 127 | items[files-1].old_path = xstrdup(pair->one->path); |
127 | items[files-1].new_path = xstrdup(pair->two->path); | 128 | items[files-1].new_path = xstrdup(pair->two->path); |
128 | items[files-1].added = lines_added; | 129 | items[files-1].added = lines_added; |
129 | items[files-1].removed = lines_removed; | 130 | items[files-1].removed = lines_removed; |
130 | if (lines_added + lines_removed > max_changes) | 131 | if (lines_added + lines_removed > max_changes) |
131 | max_changes = lines_added + lines_removed; | 132 | max_changes = lines_added + lines_removed; |
132 | total_adds += lines_added; | 133 | total_adds += lines_added; |
133 | total_rems += lines_removed; | 134 | total_rems += lines_removed; |
134 | } | 135 | } |
135 | 136 | ||
136 | 137 | ||
137 | void cgit_print_commit(char *hex) | 138 | void cgit_print_commit(char *hex) |
138 | { | 139 | { |
@@ -1,138 +1,139 @@ | |||
1 | /* ui-diff.c: show diff between two blobs | 1 | /* ui-diff.c: show diff between two blobs |
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 "cgit.h" | 9 | #include "cgit.h" |
10 | #include "html.h" | 10 | #include "html.h" |
11 | #include "ui-shared.h" | ||
11 | 12 | ||
12 | unsigned char old_rev_sha1[20]; | 13 | unsigned char old_rev_sha1[20]; |
13 | unsigned char new_rev_sha1[20]; | 14 | unsigned char new_rev_sha1[20]; |
14 | 15 | ||
15 | /* | 16 | /* |
16 | * print a single line returned from xdiff | 17 | * print a single line returned from xdiff |
17 | */ | 18 | */ |
18 | static void print_line(char *line, int len) | 19 | static void print_line(char *line, int len) |
19 | { | 20 | { |
20 | char *class = "ctx"; | 21 | char *class = "ctx"; |
21 | char c = line[len-1]; | 22 | char c = line[len-1]; |
22 | 23 | ||
23 | if (line[0] == '+') | 24 | if (line[0] == '+') |
24 | class = "add"; | 25 | class = "add"; |
25 | else if (line[0] == '-') | 26 | else if (line[0] == '-') |
26 | class = "del"; | 27 | class = "del"; |
27 | else if (line[0] == '@') | 28 | else if (line[0] == '@') |
28 | class = "hunk"; | 29 | class = "hunk"; |
29 | 30 | ||
30 | htmlf("<div class='%s'>", class); | 31 | htmlf("<div class='%s'>", class); |
31 | line[len-1] = '\0'; | 32 | line[len-1] = '\0'; |
32 | html_txt(line); | 33 | html_txt(line); |
33 | html("</div>"); | 34 | html("</div>"); |
34 | line[len-1] = c; | 35 | line[len-1] = c; |
35 | } | 36 | } |
36 | 37 | ||
37 | static void header(unsigned char *sha1, char *path1, int mode1, | 38 | static void header(unsigned char *sha1, char *path1, int mode1, |
38 | unsigned char *sha2, char *path2, int mode2) | 39 | unsigned char *sha2, char *path2, int mode2) |
39 | { | 40 | { |
40 | char *abbrev1, *abbrev2; | 41 | char *abbrev1, *abbrev2; |
41 | int subproject; | 42 | int subproject; |
42 | 43 | ||
43 | subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2)); | 44 | subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2)); |
44 | html("<div class='head'>"); | 45 | html("<div class='head'>"); |
45 | html("diff --git a/"); | 46 | html("diff --git a/"); |
46 | html_txt(path1); | 47 | html_txt(path1); |
47 | html(" b/"); | 48 | html(" b/"); |
48 | html_txt(path2); | 49 | html_txt(path2); |
49 | 50 | ||
50 | if (is_null_sha1(sha1)) | 51 | if (is_null_sha1(sha1)) |
51 | path1 = "dev/null"; | 52 | path1 = "dev/null"; |
52 | if (is_null_sha1(sha2)) | 53 | if (is_null_sha1(sha2)) |
53 | path2 = "dev/null"; | 54 | path2 = "dev/null"; |
54 | 55 | ||
55 | if (mode1 == 0) | 56 | if (mode1 == 0) |
56 | htmlf("<br/>new file mode %.6o", mode2); | 57 | htmlf("<br/>new file mode %.6o", mode2); |
57 | 58 | ||
58 | if (mode2 == 0) | 59 | if (mode2 == 0) |
59 | htmlf("<br/>deleted file mode %.6o", mode1); | 60 | htmlf("<br/>deleted file mode %.6o", mode1); |
60 | 61 | ||
61 | if (!subproject) { | 62 | if (!subproject) { |
62 | abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); | 63 | abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); |
63 | abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); | 64 | abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); |
64 | htmlf("<br/>index %s..%s", abbrev1, abbrev2); | 65 | htmlf("<br/>index %s..%s", abbrev1, abbrev2); |
65 | free(abbrev1); | 66 | free(abbrev1); |
66 | free(abbrev2); | 67 | free(abbrev2); |
67 | if (mode1 != 0 && mode2 != 0) { | 68 | if (mode1 != 0 && mode2 != 0) { |
68 | htmlf(" %.6o", mode1); | 69 | htmlf(" %.6o", mode1); |
69 | if (mode2 != mode1) | 70 | if (mode2 != mode1) |
70 | htmlf("..%.6o", mode2); | 71 | htmlf("..%.6o", mode2); |
71 | } | 72 | } |
72 | html("<br/>--- a/"); | 73 | html("<br/>--- a/"); |
73 | if (mode1 != 0) | 74 | if (mode1 != 0) |
74 | cgit_tree_link(path1, NULL, NULL, ctx.qry.head, | 75 | cgit_tree_link(path1, NULL, NULL, ctx.qry.head, |
75 | sha1_to_hex(old_rev_sha1), path1); | 76 | sha1_to_hex(old_rev_sha1), path1); |
76 | else | 77 | else |
77 | html_txt(path1); | 78 | html_txt(path1); |
78 | html("<br/>+++ b/"); | 79 | html("<br/>+++ b/"); |
79 | if (mode2 != 0) | 80 | if (mode2 != 0) |
80 | cgit_tree_link(path2, NULL, NULL, ctx.qry.head, | 81 | cgit_tree_link(path2, NULL, NULL, ctx.qry.head, |
81 | sha1_to_hex(new_rev_sha1), path2); | 82 | sha1_to_hex(new_rev_sha1), path2); |
82 | else | 83 | else |
83 | html_txt(path2); | 84 | html_txt(path2); |
84 | } | 85 | } |
85 | html("</div>"); | 86 | html("</div>"); |
86 | } | 87 | } |
87 | 88 | ||
88 | static void filepair_cb(struct diff_filepair *pair) | 89 | static void filepair_cb(struct diff_filepair *pair) |
89 | { | 90 | { |
90 | header(pair->one->sha1, pair->one->path, pair->one->mode, | 91 | header(pair->one->sha1, pair->one->path, pair->one->mode, |
91 | pair->two->sha1, pair->two->path, pair->two->mode); | 92 | pair->two->sha1, pair->two->path, pair->two->mode); |
92 | if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) { | 93 | if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) { |
93 | if (S_ISGITLINK(pair->one->mode)) | 94 | if (S_ISGITLINK(pair->one->mode)) |
94 | print_line(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52); | 95 | print_line(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52); |
95 | if (S_ISGITLINK(pair->two->mode)) | 96 | if (S_ISGITLINK(pair->two->mode)) |
96 | print_line(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52); | 97 | print_line(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52); |
97 | return; | 98 | return; |
98 | } | 99 | } |
99 | if (cgit_diff_files(pair->one->sha1, pair->two->sha1, print_line)) | 100 | if (cgit_diff_files(pair->one->sha1, pair->two->sha1, print_line)) |
100 | cgit_print_error("Error running diff"); | 101 | cgit_print_error("Error running diff"); |
101 | } | 102 | } |
102 | 103 | ||
103 | void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefix) | 104 | void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefix) |
104 | { | 105 | { |
105 | enum object_type type; | 106 | enum object_type type; |
106 | unsigned long size; | 107 | unsigned long size; |
107 | struct commit *commit, *commit2; | 108 | struct commit *commit, *commit2; |
108 | 109 | ||
109 | if (!new_rev) | 110 | if (!new_rev) |
110 | new_rev = ctx.qry.head; | 111 | new_rev = ctx.qry.head; |
111 | get_sha1(new_rev, new_rev_sha1); | 112 | get_sha1(new_rev, new_rev_sha1); |
112 | type = sha1_object_info(new_rev_sha1, &size); | 113 | type = sha1_object_info(new_rev_sha1, &size); |
113 | if (type == OBJ_BAD) { | 114 | if (type == OBJ_BAD) { |
114 | cgit_print_error(fmt("Bad object name: %s", new_rev)); | 115 | cgit_print_error(fmt("Bad object name: %s", new_rev)); |
115 | return; | 116 | return; |
116 | } | 117 | } |
117 | if (type != OBJ_COMMIT) { | 118 | if (type != OBJ_COMMIT) { |
118 | cgit_print_error(fmt("Unhandled object type: %s", | 119 | cgit_print_error(fmt("Unhandled object type: %s", |
119 | typename(type))); | 120 | typename(type))); |
120 | return; | 121 | return; |
121 | } | 122 | } |
122 | 123 | ||
123 | commit = lookup_commit_reference(new_rev_sha1); | 124 | commit = lookup_commit_reference(new_rev_sha1); |
124 | if (!commit || parse_commit(commit)) | 125 | if (!commit || parse_commit(commit)) |
125 | cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(new_rev_sha1))); | 126 | cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(new_rev_sha1))); |
126 | 127 | ||
127 | if (old_rev) | 128 | if (old_rev) |
128 | get_sha1(old_rev, old_rev_sha1); | 129 | get_sha1(old_rev, old_rev_sha1); |
129 | else if (commit->parents && commit->parents->item) | 130 | else if (commit->parents && commit->parents->item) |
130 | hashcpy(old_rev_sha1, commit->parents->item->object.sha1); | 131 | hashcpy(old_rev_sha1, commit->parents->item->object.sha1); |
131 | else | 132 | else |
132 | hashclr(old_rev_sha1); | 133 | hashclr(old_rev_sha1); |
133 | 134 | ||
134 | if (!is_null_sha1(old_rev_sha1)) { | 135 | if (!is_null_sha1(old_rev_sha1)) { |
135 | type = sha1_object_info(old_rev_sha1, &size); | 136 | type = sha1_object_info(old_rev_sha1, &size); |
136 | if (type == OBJ_BAD) { | 137 | if (type == OBJ_BAD) { |
137 | cgit_print_error(fmt("Bad object name: %s", sha1_to_hex(old_rev_sha1))); | 138 | cgit_print_error(fmt("Bad object name: %s", sha1_to_hex(old_rev_sha1))); |
138 | return; | 139 | return; |
@@ -1,138 +1,139 @@ | |||
1 | /* ui-log.c: functions for log output | 1 | /* ui-log.c: functions for log 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 "cgit.h" | 9 | #include "cgit.h" |
10 | #include "html.h" | 10 | #include "html.h" |
11 | #include "ui-shared.h" | ||
11 | 12 | ||
12 | int files, add_lines, rem_lines; | 13 | int files, add_lines, rem_lines; |
13 | 14 | ||
14 | void count_lines(char *line, int size) | 15 | void count_lines(char *line, int size) |
15 | { | 16 | { |
16 | if (size <= 0) | 17 | if (size <= 0) |
17 | return; | 18 | return; |
18 | 19 | ||
19 | if (line[0] == '+') | 20 | if (line[0] == '+') |
20 | add_lines++; | 21 | add_lines++; |
21 | 22 | ||
22 | else if (line[0] == '-') | 23 | else if (line[0] == '-') |
23 | rem_lines++; | 24 | rem_lines++; |
24 | } | 25 | } |
25 | 26 | ||
26 | void inspect_files(struct diff_filepair *pair) | 27 | void inspect_files(struct diff_filepair *pair) |
27 | { | 28 | { |
28 | files++; | 29 | files++; |
29 | if (ctx.repo->enable_log_linecount) | 30 | if (ctx.repo->enable_log_linecount) |
30 | cgit_diff_files(pair->one->sha1, pair->two->sha1, count_lines); | 31 | cgit_diff_files(pair->one->sha1, pair->two->sha1, count_lines); |
31 | } | 32 | } |
32 | 33 | ||
33 | void print_commit(struct commit *commit) | 34 | void print_commit(struct commit *commit) |
34 | { | 35 | { |
35 | struct commitinfo *info; | 36 | struct commitinfo *info; |
36 | 37 | ||
37 | info = cgit_parse_commit(commit); | 38 | info = cgit_parse_commit(commit); |
38 | html("<tr><td>"); | 39 | html("<tr><td>"); |
39 | cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE); | 40 | cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE); |
40 | html("</td><td>"); | 41 | html("</td><td>"); |
41 | cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head, | 42 | cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head, |
42 | sha1_to_hex(commit->object.sha1)); | 43 | sha1_to_hex(commit->object.sha1)); |
43 | if (ctx.repo->enable_log_filecount) { | 44 | if (ctx.repo->enable_log_filecount) { |
44 | files = 0; | 45 | files = 0; |
45 | add_lines = 0; | 46 | add_lines = 0; |
46 | rem_lines = 0; | 47 | rem_lines = 0; |
47 | cgit_diff_commit(commit, inspect_files); | 48 | cgit_diff_commit(commit, inspect_files); |
48 | html("</td><td class='right'>"); | 49 | html("</td><td class='right'>"); |
49 | htmlf("%d", files); | 50 | htmlf("%d", files); |
50 | if (ctx.repo->enable_log_linecount) { | 51 | if (ctx.repo->enable_log_linecount) { |
51 | html("</td><td class='right'>"); | 52 | html("</td><td class='right'>"); |
52 | htmlf("-%d/+%d", rem_lines, add_lines); | 53 | htmlf("-%d/+%d", rem_lines, add_lines); |
53 | } | 54 | } |
54 | } | 55 | } |
55 | html("</td><td>"); | 56 | html("</td><td>"); |
56 | html_txt(info->author); | 57 | html_txt(info->author); |
57 | html("</td></tr>\n"); | 58 | html("</td></tr>\n"); |
58 | cgit_free_commitinfo(info); | 59 | cgit_free_commitinfo(info); |
59 | } | 60 | } |
60 | 61 | ||
61 | 62 | ||
62 | void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern, char *path, int pager) | 63 | void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern, char *path, int pager) |
63 | { | 64 | { |
64 | struct rev_info rev; | 65 | struct rev_info rev; |
65 | struct commit *commit; | 66 | struct commit *commit; |
66 | const char *argv[] = {NULL, tip, NULL, NULL, NULL}; | 67 | const char *argv[] = {NULL, tip, NULL, NULL, NULL}; |
67 | int argc = 2; | 68 | int argc = 2; |
68 | int i; | 69 | int i; |
69 | 70 | ||
70 | if (!tip) | 71 | if (!tip) |
71 | argv[1] = ctx.qry.head; | 72 | argv[1] = ctx.qry.head; |
72 | 73 | ||
73 | if (grep && pattern && (!strcmp(grep, "grep") || | 74 | if (grep && pattern && (!strcmp(grep, "grep") || |
74 | !strcmp(grep, "author") || | 75 | !strcmp(grep, "author") || |
75 | !strcmp(grep, "committer"))) | 76 | !strcmp(grep, "committer"))) |
76 | argv[argc++] = fmt("--%s=%s", grep, pattern); | 77 | argv[argc++] = fmt("--%s=%s", grep, pattern); |
77 | 78 | ||
78 | if (path) { | 79 | if (path) { |
79 | argv[argc++] = "--"; | 80 | argv[argc++] = "--"; |
80 | argv[argc++] = path; | 81 | argv[argc++] = path; |
81 | } | 82 | } |
82 | init_revisions(&rev, NULL); | 83 | init_revisions(&rev, NULL); |
83 | rev.abbrev = DEFAULT_ABBREV; | 84 | rev.abbrev = DEFAULT_ABBREV; |
84 | rev.commit_format = CMIT_FMT_DEFAULT; | 85 | rev.commit_format = CMIT_FMT_DEFAULT; |
85 | rev.verbose_header = 1; | 86 | rev.verbose_header = 1; |
86 | rev.show_root_diff = 0; | 87 | rev.show_root_diff = 0; |
87 | setup_revisions(argc, argv, &rev, NULL); | 88 | setup_revisions(argc, argv, &rev, NULL); |
88 | if (rev.grep_filter) { | 89 | if (rev.grep_filter) { |
89 | rev.grep_filter->regflags |= REG_ICASE; | 90 | rev.grep_filter->regflags |= REG_ICASE; |
90 | compile_grep_patterns(rev.grep_filter); | 91 | compile_grep_patterns(rev.grep_filter); |
91 | } | 92 | } |
92 | prepare_revision_walk(&rev); | 93 | prepare_revision_walk(&rev); |
93 | 94 | ||
94 | html("<table summary='log' class='list nowrap'>"); | 95 | html("<table summary='log' class='list nowrap'>"); |
95 | html("<tr class='nohover'><th class='left'>Age</th>" | 96 | html("<tr class='nohover'><th class='left'>Age</th>" |
96 | "<th class='left'>Message</th>"); | 97 | "<th class='left'>Message</th>"); |
97 | 98 | ||
98 | if (ctx.repo->enable_log_filecount) { | 99 | if (ctx.repo->enable_log_filecount) { |
99 | html("<th class='right'>Files</th>"); | 100 | html("<th class='right'>Files</th>"); |
100 | if (ctx.repo->enable_log_linecount) | 101 | if (ctx.repo->enable_log_linecount) |
101 | html("<th class='right'>Lines</th>"); | 102 | html("<th class='right'>Lines</th>"); |
102 | } | 103 | } |
103 | html("<th class='left'>Author</th></tr>\n"); | 104 | html("<th class='left'>Author</th></tr>\n"); |
104 | 105 | ||
105 | if (ofs<0) | 106 | if (ofs<0) |
106 | ofs = 0; | 107 | ofs = 0; |
107 | 108 | ||
108 | for (i = 0; i < ofs && (commit = get_revision(&rev)) != NULL; i++) { | 109 | for (i = 0; i < ofs && (commit = get_revision(&rev)) != NULL; i++) { |
109 | free(commit->buffer); | 110 | free(commit->buffer); |
110 | commit->buffer = NULL; | 111 | commit->buffer = NULL; |
111 | free_commit_list(commit->parents); | 112 | free_commit_list(commit->parents); |
112 | commit->parents = NULL; | 113 | commit->parents = NULL; |
113 | } | 114 | } |
114 | 115 | ||
115 | for (i = 0; i < cnt && (commit = get_revision(&rev)) != NULL; i++) { | 116 | for (i = 0; i < cnt && (commit = get_revision(&rev)) != NULL; i++) { |
116 | print_commit(commit); | 117 | print_commit(commit); |
117 | free(commit->buffer); | 118 | free(commit->buffer); |
118 | commit->buffer = NULL; | 119 | commit->buffer = NULL; |
119 | free_commit_list(commit->parents); | 120 | free_commit_list(commit->parents); |
120 | commit->parents = NULL; | 121 | commit->parents = NULL; |
121 | } | 122 | } |
122 | html("</table>\n"); | 123 | html("</table>\n"); |
123 | 124 | ||
124 | if (pager) { | 125 | if (pager) { |
125 | html("<div class='pager'>"); | 126 | html("<div class='pager'>"); |
126 | if (ofs > 0) { | 127 | if (ofs > 0) { |
127 | cgit_log_link("[prev]", NULL, NULL, ctx.qry.head, | 128 | cgit_log_link("[prev]", NULL, NULL, ctx.qry.head, |
128 | ctx.qry.sha1, ctx.qry.path, | 129 | ctx.qry.sha1, ctx.qry.path, |
129 | ofs - cnt, ctx.qry.grep, | 130 | ofs - cnt, ctx.qry.grep, |
130 | ctx.qry.search); | 131 | ctx.qry.search); |
131 | html(" "); | 132 | html(" "); |
132 | } | 133 | } |
133 | if ((commit = get_revision(&rev)) != NULL) { | 134 | if ((commit = get_revision(&rev)) != NULL) { |
134 | cgit_log_link("[next]", NULL, NULL, ctx.qry.head, | 135 | cgit_log_link("[next]", NULL, NULL, ctx.qry.head, |
135 | ctx.qry.sha1, ctx.qry.path, | 136 | ctx.qry.sha1, ctx.qry.path, |
136 | ofs + cnt, ctx.qry.grep, | 137 | ofs + cnt, ctx.qry.grep, |
137 | ctx.qry.search); | 138 | ctx.qry.search); |
138 | } | 139 | } |
@@ -1,113 +1,114 @@ | |||
1 | /* ui-patch.c: generate patch view | 1 | /* ui-patch.c: generate patch view |
2 | * | 2 | * |
3 | * Copyright (C) 2007 Lars Hjemli | 3 | * Copyright (C) 2007 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 "cgit.h" | 9 | #include "cgit.h" |
10 | #include "html.h" | 10 | #include "html.h" |
11 | #include "ui-shared.h" | ||
11 | 12 | ||
12 | static void print_line(char *line, int len) | 13 | static void print_line(char *line, int len) |
13 | { | 14 | { |
14 | char c = line[len-1]; | 15 | char c = line[len-1]; |
15 | 16 | ||
16 | line[len-1] = '\0'; | 17 | line[len-1] = '\0'; |
17 | htmlf("%s\n", line); | 18 | htmlf("%s\n", line); |
18 | line[len-1] = c; | 19 | line[len-1] = c; |
19 | } | 20 | } |
20 | 21 | ||
21 | static void header(unsigned char *sha1, char *path1, int mode1, | 22 | static void header(unsigned char *sha1, char *path1, int mode1, |
22 | unsigned char *sha2, char *path2, int mode2) | 23 | unsigned char *sha2, char *path2, int mode2) |
23 | { | 24 | { |
24 | char *abbrev1, *abbrev2; | 25 | char *abbrev1, *abbrev2; |
25 | int subproject; | 26 | int subproject; |
26 | 27 | ||
27 | subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2)); | 28 | subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2)); |
28 | htmlf("diff --git a/%s b/%s\n", path1, path2); | 29 | htmlf("diff --git a/%s b/%s\n", path1, path2); |
29 | 30 | ||
30 | if (is_null_sha1(sha1)) | 31 | if (is_null_sha1(sha1)) |
31 | path1 = "dev/null"; | 32 | path1 = "dev/null"; |
32 | if (is_null_sha1(sha2)) | 33 | if (is_null_sha1(sha2)) |
33 | path2 = "dev/null"; | 34 | path2 = "dev/null"; |
34 | 35 | ||
35 | if (mode1 == 0) | 36 | if (mode1 == 0) |
36 | htmlf("new file mode %.6o\n", mode2); | 37 | htmlf("new file mode %.6o\n", mode2); |
37 | 38 | ||
38 | if (mode2 == 0) | 39 | if (mode2 == 0) |
39 | htmlf("deleted file mode %.6o\n", mode1); | 40 | htmlf("deleted file mode %.6o\n", mode1); |
40 | 41 | ||
41 | if (!subproject) { | 42 | if (!subproject) { |
42 | abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); | 43 | abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); |
43 | abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); | 44 | abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); |
44 | htmlf("index %s..%s", abbrev1, abbrev2); | 45 | htmlf("index %s..%s", abbrev1, abbrev2); |
45 | free(abbrev1); | 46 | free(abbrev1); |
46 | free(abbrev2); | 47 | free(abbrev2); |
47 | if (mode1 != 0 && mode2 != 0) { | 48 | if (mode1 != 0 && mode2 != 0) { |
48 | htmlf(" %.6o", mode1); | 49 | htmlf(" %.6o", mode1); |
49 | if (mode2 != mode1) | 50 | if (mode2 != mode1) |
50 | htmlf("..%.6o", mode2); | 51 | htmlf("..%.6o", mode2); |
51 | } | 52 | } |
52 | htmlf("\n--- a/%s\n", path1); | 53 | htmlf("\n--- a/%s\n", path1); |
53 | htmlf("+++ b/%s\n", path2); | 54 | htmlf("+++ b/%s\n", path2); |
54 | } | 55 | } |
55 | } | 56 | } |
56 | 57 | ||
57 | static void filepair_cb(struct diff_filepair *pair) | 58 | static void filepair_cb(struct diff_filepair *pair) |
58 | { | 59 | { |
59 | header(pair->one->sha1, pair->one->path, pair->one->mode, | 60 | header(pair->one->sha1, pair->one->path, pair->one->mode, |
60 | pair->two->sha1, pair->two->path, pair->two->mode); | 61 | pair->two->sha1, pair->two->path, pair->two->mode); |
61 | if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) { | 62 | if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) { |
62 | if (S_ISGITLINK(pair->one->mode)) | 63 | if (S_ISGITLINK(pair->one->mode)) |
63 | print_line(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52); | 64 | print_line(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52); |
64 | if (S_ISGITLINK(pair->two->mode)) | 65 | if (S_ISGITLINK(pair->two->mode)) |
65 | print_line(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52); | 66 | print_line(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52); |
66 | return; | 67 | return; |
67 | } | 68 | } |
68 | if (cgit_diff_files(pair->one->sha1, pair->two->sha1, print_line)) | 69 | if (cgit_diff_files(pair->one->sha1, pair->two->sha1, print_line)) |
69 | html("Error running diff"); | 70 | html("Error running diff"); |
70 | } | 71 | } |
71 | 72 | ||
72 | void cgit_print_patch(char *hex) | 73 | void cgit_print_patch(char *hex) |
73 | { | 74 | { |
74 | struct commit *commit; | 75 | struct commit *commit; |
75 | struct commitinfo *info; | 76 | struct commitinfo *info; |
76 | unsigned char sha1[20], old_sha1[20]; | 77 | unsigned char sha1[20], old_sha1[20]; |
77 | char *patchname; | 78 | char *patchname; |
78 | 79 | ||
79 | if (!hex) | 80 | if (!hex) |
80 | hex = ctx.qry.head; | 81 | hex = ctx.qry.head; |
81 | 82 | ||
82 | if (get_sha1(hex, sha1)) { | 83 | if (get_sha1(hex, sha1)) { |
83 | cgit_print_error(fmt("Bad object id: %s", hex)); | 84 | cgit_print_error(fmt("Bad object id: %s", hex)); |
84 | return; | 85 | return; |
85 | } | 86 | } |
86 | commit = lookup_commit_reference(sha1); | 87 | commit = lookup_commit_reference(sha1); |
87 | if (!commit) { | 88 | if (!commit) { |
88 | cgit_print_error(fmt("Bad commit reference: %s", hex)); | 89 | cgit_print_error(fmt("Bad commit reference: %s", hex)); |
89 | return; | 90 | return; |
90 | } | 91 | } |
91 | info = cgit_parse_commit(commit); | 92 | info = cgit_parse_commit(commit); |
92 | hashcpy(old_sha1, commit->parents->item->object.sha1); | 93 | hashcpy(old_sha1, commit->parents->item->object.sha1); |
93 | 94 | ||
94 | patchname = fmt("%s.patch", sha1_to_hex(sha1)); | 95 | patchname = fmt("%s.patch", sha1_to_hex(sha1)); |
95 | ctx.page.mimetype = "text/plain"; | 96 | ctx.page.mimetype = "text/plain"; |
96 | ctx.page.filename = patchname; | 97 | ctx.page.filename = patchname; |
97 | cgit_print_http_headers(&ctx); | 98 | cgit_print_http_headers(&ctx); |
98 | htmlf("From %s Mon Sep 17 00:00:00 2001\n", sha1_to_hex(sha1)); | 99 | htmlf("From %s Mon Sep 17 00:00:00 2001\n", sha1_to_hex(sha1)); |
99 | htmlf("From: %s%s\n", info->author, info->author_email); | 100 | htmlf("From: %s%s\n", info->author, info->author_email); |
100 | html("Date: "); | 101 | html("Date: "); |
101 | cgit_print_date(info->author_date, "%a, %d %b %Y %H:%M:%S %z%n"); | 102 | cgit_print_date(info->author_date, "%a, %d %b %Y %H:%M:%S %z%n"); |
102 | htmlf("Subject: %s\n\n", info->subject); | 103 | htmlf("Subject: %s\n\n", info->subject); |
103 | if (info->msg && *info->msg) { | 104 | if (info->msg && *info->msg) { |
104 | htmlf("%s", info->msg); | 105 | htmlf("%s", info->msg); |
105 | if (info->msg[strlen(info->msg) - 1] != '\n') | 106 | if (info->msg[strlen(info->msg) - 1] != '\n') |
106 | html("\n"); | 107 | html("\n"); |
107 | } | 108 | } |
108 | html("---\n"); | 109 | html("---\n"); |
109 | cgit_diff_tree(old_sha1, sha1, filepair_cb, NULL); | 110 | cgit_diff_tree(old_sha1, sha1, filepair_cb, NULL); |
110 | html("--\n"); | 111 | html("--\n"); |
111 | htmlf("cgit %s\n", CGIT_VERSION); | 112 | htmlf("cgit %s\n", CGIT_VERSION); |
112 | cgit_free_commitinfo(info); | 113 | cgit_free_commitinfo(info); |
113 | } | 114 | } |
@@ -1,138 +1,139 @@ | |||
1 | /* ui-refs.c: browse symbolic refs | 1 | /* ui-refs.c: browse symbolic refs |
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 "cgit.h" | 9 | #include "cgit.h" |
10 | #include "html.h" | 10 | #include "html.h" |
11 | #include "ui-shared.h" | ||
11 | 12 | ||
12 | static int header; | 13 | static int header; |
13 | 14 | ||
14 | static int cmp_age(int age1, int age2) | 15 | static int cmp_age(int age1, int age2) |
15 | { | 16 | { |
16 | if (age1 != 0 && age2 != 0) | 17 | if (age1 != 0 && age2 != 0) |
17 | return age2 - age1; | 18 | return age2 - age1; |
18 | 19 | ||
19 | if (age1 == 0 && age2 == 0) | 20 | if (age1 == 0 && age2 == 0) |
20 | return 0; | 21 | return 0; |
21 | 22 | ||
22 | if (age1 == 0) | 23 | if (age1 == 0) |
23 | return +1; | 24 | return +1; |
24 | 25 | ||
25 | return -1; | 26 | return -1; |
26 | } | 27 | } |
27 | 28 | ||
28 | static int cmp_ref_name(const void *a, const void *b) | 29 | static int cmp_ref_name(const void *a, const void *b) |
29 | { | 30 | { |
30 | struct refinfo *r1 = *(struct refinfo **)a; | 31 | struct refinfo *r1 = *(struct refinfo **)a; |
31 | struct refinfo *r2 = *(struct refinfo **)b; | 32 | struct refinfo *r2 = *(struct refinfo **)b; |
32 | 33 | ||
33 | return strcmp(r1->refname, r2->refname); | 34 | return strcmp(r1->refname, r2->refname); |
34 | } | 35 | } |
35 | 36 | ||
36 | static int cmp_branch_age(const void *a, const void *b) | 37 | static int cmp_branch_age(const void *a, const void *b) |
37 | { | 38 | { |
38 | struct refinfo *r1 = *(struct refinfo **)a; | 39 | struct refinfo *r1 = *(struct refinfo **)a; |
39 | struct refinfo *r2 = *(struct refinfo **)b; | 40 | struct refinfo *r2 = *(struct refinfo **)b; |
40 | 41 | ||
41 | return cmp_age(r1->commit->committer_date, r2->commit->committer_date); | 42 | return cmp_age(r1->commit->committer_date, r2->commit->committer_date); |
42 | } | 43 | } |
43 | 44 | ||
44 | static int cmp_tag_age(const void *a, const void *b) | 45 | static int cmp_tag_age(const void *a, const void *b) |
45 | { | 46 | { |
46 | struct refinfo *r1 = *(struct refinfo **)a; | 47 | struct refinfo *r1 = *(struct refinfo **)a; |
47 | struct refinfo *r2 = *(struct refinfo **)b; | 48 | struct refinfo *r2 = *(struct refinfo **)b; |
48 | 49 | ||
49 | return cmp_age(r1->tag->tagger_date, r2->tag->tagger_date); | 50 | return cmp_age(r1->tag->tagger_date, r2->tag->tagger_date); |
50 | } | 51 | } |
51 | 52 | ||
52 | static int print_branch(struct refinfo *ref) | 53 | static int print_branch(struct refinfo *ref) |
53 | { | 54 | { |
54 | struct commitinfo *info = ref->commit; | 55 | struct commitinfo *info = ref->commit; |
55 | char *name = (char *)ref->refname; | 56 | char *name = (char *)ref->refname; |
56 | 57 | ||
57 | if (!info) | 58 | if (!info) |
58 | return 1; | 59 | return 1; |
59 | html("<tr><td>"); | 60 | html("<tr><td>"); |
60 | cgit_log_link(name, NULL, NULL, name, NULL, NULL, 0, NULL, NULL); | 61 | cgit_log_link(name, NULL, NULL, name, NULL, NULL, 0, NULL, NULL); |
61 | html("</td><td>"); | 62 | html("</td><td>"); |
62 | 63 | ||
63 | if (ref->object->type == OBJ_COMMIT) { | 64 | if (ref->object->type == OBJ_COMMIT) { |
64 | cgit_print_age(info->commit->date, -1, NULL); | 65 | cgit_print_age(info->commit->date, -1, NULL); |
65 | html("</td><td>"); | 66 | html("</td><td>"); |
66 | html_txt(info->author); | 67 | html_txt(info->author); |
67 | html("</td><td>"); | 68 | html("</td><td>"); |
68 | cgit_commit_link(info->subject, NULL, NULL, name, NULL); | 69 | cgit_commit_link(info->subject, NULL, NULL, name, NULL); |
69 | } else { | 70 | } else { |
70 | html("</td><td></td><td>"); | 71 | html("</td><td></td><td>"); |
71 | cgit_object_link(ref->object); | 72 | cgit_object_link(ref->object); |
72 | } | 73 | } |
73 | html("</td></tr>\n"); | 74 | html("</td></tr>\n"); |
74 | return 0; | 75 | return 0; |
75 | } | 76 | } |
76 | 77 | ||
77 | static void print_tag_header() | 78 | static void print_tag_header() |
78 | { | 79 | { |
79 | html("<tr class='nohover'><th class='left'>Tag</th>" | 80 | html("<tr class='nohover'><th class='left'>Tag</th>" |
80 | "<th class='left'>Age</th>" | 81 | "<th class='left'>Age</th>" |
81 | "<th class='left'>Author</th>" | 82 | "<th class='left'>Author</th>" |
82 | "<th class='left'>Reference</th></tr>\n"); | 83 | "<th class='left'>Reference</th></tr>\n"); |
83 | header = 1; | 84 | header = 1; |
84 | } | 85 | } |
85 | 86 | ||
86 | static int print_tag(struct refinfo *ref) | 87 | static int print_tag(struct refinfo *ref) |
87 | { | 88 | { |
88 | struct tag *tag; | 89 | struct tag *tag; |
89 | struct taginfo *info; | 90 | struct taginfo *info; |
90 | char *url, *name = (char *)ref->refname; | 91 | char *url, *name = (char *)ref->refname; |
91 | 92 | ||
92 | if (ref->object->type == OBJ_TAG) { | 93 | if (ref->object->type == OBJ_TAG) { |
93 | tag = (struct tag *)ref->object; | 94 | tag = (struct tag *)ref->object; |
94 | info = ref->tag; | 95 | info = ref->tag; |
95 | if (!tag || !info) | 96 | if (!tag || !info) |
96 | return 1; | 97 | return 1; |
97 | html("<tr><td>"); | 98 | html("<tr><td>"); |
98 | url = cgit_pageurl(ctx.qry.repo, "tag", | 99 | url = cgit_pageurl(ctx.qry.repo, "tag", |
99 | fmt("id=%s", name)); | 100 | fmt("id=%s", name)); |
100 | html_link_open(url, NULL, NULL); | 101 | html_link_open(url, NULL, NULL); |
101 | html_txt(name); | 102 | html_txt(name); |
102 | html_link_close(); | 103 | html_link_close(); |
103 | html("</td><td>"); | 104 | html("</td><td>"); |
104 | if (info->tagger_date > 0) | 105 | if (info->tagger_date > 0) |
105 | cgit_print_age(info->tagger_date, -1, NULL); | 106 | cgit_print_age(info->tagger_date, -1, NULL); |
106 | html("</td><td>"); | 107 | html("</td><td>"); |
107 | if (info->tagger) | 108 | if (info->tagger) |
108 | html(info->tagger); | 109 | html(info->tagger); |
109 | html("</td><td>"); | 110 | html("</td><td>"); |
110 | cgit_object_link(tag->tagged); | 111 | cgit_object_link(tag->tagged); |
111 | html("</td></tr>\n"); | 112 | html("</td></tr>\n"); |
112 | } else { | 113 | } else { |
113 | if (!header) | 114 | if (!header) |
114 | print_tag_header(); | 115 | print_tag_header(); |
115 | html("<tr><td>"); | 116 | html("<tr><td>"); |
116 | html_txt(name); | 117 | html_txt(name); |
117 | html("</td><td colspan='2'/><td>"); | 118 | html("</td><td colspan='2'/><td>"); |
118 | cgit_object_link(ref->object); | 119 | cgit_object_link(ref->object); |
119 | html("</td></tr>\n"); | 120 | html("</td></tr>\n"); |
120 | } | 121 | } |
121 | return 0; | 122 | return 0; |
122 | } | 123 | } |
123 | 124 | ||
124 | static void print_refs_link(char *path) | 125 | static void print_refs_link(char *path) |
125 | { | 126 | { |
126 | html("<tr class='nohover'><td colspan='4'>"); | 127 | html("<tr class='nohover'><td colspan='4'>"); |
127 | cgit_refs_link("[...]", NULL, NULL, ctx.qry.head, NULL, path); | 128 | cgit_refs_link("[...]", NULL, NULL, ctx.qry.head, NULL, path); |
128 | html("</td></tr>"); | 129 | html("</td></tr>"); |
129 | } | 130 | } |
130 | 131 | ||
131 | void cgit_print_branches(int maxcount) | 132 | void cgit_print_branches(int maxcount) |
132 | { | 133 | { |
133 | struct reflist list; | 134 | struct reflist list; |
134 | int i; | 135 | int i; |
135 | 136 | ||
136 | html("<tr class='nohover'><th class='left'>Branch</th>" | 137 | html("<tr class='nohover'><th class='left'>Branch</th>" |
137 | "<th class='left'>Idle</th>" | 138 | "<th class='left'>Idle</th>" |
138 | "<th class='left'>Author</th>" | 139 | "<th class='left'>Author</th>" |
diff --git a/ui-repolist.c b/ui-repolist.c index ad9b1bc..eeeaf3d 100644 --- a/ui-repolist.c +++ b/ui-repolist.c | |||
@@ -1,113 +1,114 @@ | |||
1 | /* ui-repolist.c: functions for generating the repolist page | 1 | /* ui-repolist.c: functions for generating the repolist page |
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 <time.h> | 9 | #include <time.h> |
10 | 10 | ||
11 | #include "cgit.h" | 11 | #include "cgit.h" |
12 | #include "html.h" | 12 | #include "html.h" |
13 | #include "ui-shared.h" | ||
13 | 14 | ||
14 | time_t read_agefile(char *path) | 15 | time_t read_agefile(char *path) |
15 | { | 16 | { |
16 | FILE *f; | 17 | FILE *f; |
17 | static char buf[64], buf2[64]; | 18 | static char buf[64], buf2[64]; |
18 | 19 | ||
19 | if (!(f = fopen(path, "r"))) | 20 | if (!(f = fopen(path, "r"))) |
20 | return -1; | 21 | return -1; |
21 | fgets(buf, sizeof(buf), f); | 22 | fgets(buf, sizeof(buf), f); |
22 | fclose(f); | 23 | fclose(f); |
23 | if (parse_date(buf, buf2, sizeof(buf2))) | 24 | if (parse_date(buf, buf2, sizeof(buf2))) |
24 | return strtoul(buf2, NULL, 10); | 25 | return strtoul(buf2, NULL, 10); |
25 | else | 26 | else |
26 | return 0; | 27 | return 0; |
27 | } | 28 | } |
28 | 29 | ||
29 | static void print_modtime(struct cgit_repo *repo) | 30 | static void print_modtime(struct cgit_repo *repo) |
30 | { | 31 | { |
31 | char *path; | 32 | char *path; |
32 | struct stat s; | 33 | struct stat s; |
33 | 34 | ||
34 | path = fmt("%s/%s", repo->path, ctx.cfg.agefile); | 35 | path = fmt("%s/%s", repo->path, ctx.cfg.agefile); |
35 | if (stat(path, &s) == 0) { | 36 | if (stat(path, &s) == 0) { |
36 | cgit_print_age(read_agefile(path), -1, NULL); | 37 | cgit_print_age(read_agefile(path), -1, NULL); |
37 | return; | 38 | return; |
38 | } | 39 | } |
39 | 40 | ||
40 | path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch); | 41 | path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch); |
41 | if (stat(path, &s) != 0) | 42 | if (stat(path, &s) != 0) |
42 | return; | 43 | return; |
43 | cgit_print_age(s.st_mtime, -1, NULL); | 44 | cgit_print_age(s.st_mtime, -1, NULL); |
44 | } | 45 | } |
45 | 46 | ||
46 | void cgit_print_repolist() | 47 | void cgit_print_repolist() |
47 | { | 48 | { |
48 | int i, columns = 4; | 49 | int i, columns = 4; |
49 | char *last_group = NULL; | 50 | char *last_group = NULL; |
50 | 51 | ||
51 | if (ctx.cfg.enable_index_links) | 52 | if (ctx.cfg.enable_index_links) |
52 | columns++; | 53 | columns++; |
53 | 54 | ||
54 | ctx.page.title = ctx.cfg.root_title; | 55 | ctx.page.title = ctx.cfg.root_title; |
55 | cgit_print_http_headers(&ctx); | 56 | cgit_print_http_headers(&ctx); |
56 | cgit_print_docstart(&ctx); | 57 | cgit_print_docstart(&ctx); |
57 | cgit_print_pageheader(&ctx); | 58 | cgit_print_pageheader(&ctx); |
58 | 59 | ||
59 | html("<table summary='repository list' class='list nowrap'>"); | 60 | html("<table summary='repository list' class='list nowrap'>"); |
60 | if (ctx.cfg.index_header) { | 61 | if (ctx.cfg.index_header) { |
61 | htmlf("<tr class='nohover'><td colspan='%d' class='include-block'>", | 62 | htmlf("<tr class='nohover'><td colspan='%d' class='include-block'>", |
62 | columns); | 63 | columns); |
63 | html_include(ctx.cfg.index_header); | 64 | html_include(ctx.cfg.index_header); |
64 | html("</td></tr>"); | 65 | html("</td></tr>"); |
65 | } | 66 | } |
66 | html("<tr class='nohover'>" | 67 | html("<tr class='nohover'>" |
67 | "<th class='left'>Name</th>" | 68 | "<th class='left'>Name</th>" |
68 | "<th class='left'>Description</th>" | 69 | "<th class='left'>Description</th>" |
69 | "<th class='left'>Owner</th>" | 70 | "<th class='left'>Owner</th>" |
70 | "<th class='left'>Idle</th>"); | 71 | "<th class='left'>Idle</th>"); |
71 | if (ctx.cfg.enable_index_links) | 72 | if (ctx.cfg.enable_index_links) |
72 | html("<th>Links</th>"); | 73 | html("<th>Links</th>"); |
73 | html("</tr>\n"); | 74 | html("</tr>\n"); |
74 | 75 | ||
75 | for (i=0; i<cgit_repolist.count; i++) { | 76 | for (i=0; i<cgit_repolist.count; i++) { |
76 | ctx.repo = &cgit_repolist.repos[i]; | 77 | ctx.repo = &cgit_repolist.repos[i]; |
77 | if ((last_group == NULL && ctx.repo->group != NULL) || | 78 | if ((last_group == NULL && ctx.repo->group != NULL) || |
78 | (last_group != NULL && ctx.repo->group == NULL) || | 79 | (last_group != NULL && ctx.repo->group == NULL) || |
79 | (last_group != NULL && ctx.repo->group != NULL && | 80 | (last_group != NULL && ctx.repo->group != NULL && |
80 | strcmp(ctx.repo->group, last_group))) { | 81 | strcmp(ctx.repo->group, last_group))) { |
81 | htmlf("<tr class='nohover'><td colspan='%d' class='repogroup'>", | 82 | htmlf("<tr class='nohover'><td colspan='%d' class='repogroup'>", |
82 | columns); | 83 | columns); |
83 | html_txt(ctx.repo->group); | 84 | html_txt(ctx.repo->group); |
84 | html("</td></tr>"); | 85 | html("</td></tr>"); |
85 | last_group = ctx.repo->group; | 86 | last_group = ctx.repo->group; |
86 | } | 87 | } |
87 | htmlf("<tr><td class='%s'>", | 88 | htmlf("<tr><td class='%s'>", |
88 | ctx.repo->group ? "sublevel-repo" : "toplevel-repo"); | 89 | ctx.repo->group ? "sublevel-repo" : "toplevel-repo"); |
89 | html_link_open(cgit_repourl(ctx.repo->url), NULL, NULL); | 90 | html_link_open(cgit_repourl(ctx.repo->url), NULL, NULL); |
90 | html_txt(ctx.repo->name); | 91 | html_txt(ctx.repo->name); |
91 | html_link_close(); | 92 | html_link_close(); |
92 | html("</td><td>"); | 93 | html("</td><td>"); |
93 | html_ntxt(ctx.cfg.max_repodesc_len, ctx.repo->desc); | 94 | html_ntxt(ctx.cfg.max_repodesc_len, ctx.repo->desc); |
94 | html("</td><td>"); | 95 | html("</td><td>"); |
95 | html_txt(ctx.repo->owner); | 96 | html_txt(ctx.repo->owner); |
96 | html("</td><td>"); | 97 | html("</td><td>"); |
97 | print_modtime(ctx.repo); | 98 | print_modtime(ctx.repo); |
98 | html("</td>"); | 99 | html("</td>"); |
99 | if (ctx.cfg.enable_index_links) { | 100 | if (ctx.cfg.enable_index_links) { |
100 | html("<td>"); | 101 | html("<td>"); |
101 | html_link_open(cgit_repourl(ctx.repo->url), | 102 | html_link_open(cgit_repourl(ctx.repo->url), |
102 | NULL, "button"); | 103 | NULL, "button"); |
103 | html("summary</a>"); | 104 | html("summary</a>"); |
104 | cgit_log_link("log", NULL, "button", NULL, NULL, NULL, | 105 | cgit_log_link("log", NULL, "button", NULL, NULL, NULL, |
105 | 0, NULL, NULL); | 106 | 0, NULL, NULL); |
106 | cgit_tree_link("tree", NULL, "button", NULL, NULL, NULL); | 107 | cgit_tree_link("tree", NULL, "button", NULL, NULL, NULL); |
107 | html("</td>"); | 108 | html("</td>"); |
108 | } | 109 | } |
109 | html("</tr>\n"); | 110 | html("</tr>\n"); |
110 | } | 111 | } |
111 | html("</table>"); | 112 | html("</table>"); |
112 | cgit_print_docend(); | 113 | cgit_print_docend(); |
113 | } | 114 | } |
diff --git a/ui-shared.h b/ui-shared.h new file mode 100644 index 0000000..94de884 --- a/dev/null +++ b/ui-shared.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef UI_SHARED_H | ||
2 | #define UI_SHARED_H | ||
3 | |||
4 | extern char *cgit_repourl(const char *reponame); | ||
5 | extern char *cgit_fileurl(const char *reponame, const char *pagename, | ||
6 | const char *filename, const char *query); | ||
7 | extern char *cgit_pageurl(const char *reponame, const char *pagename, | ||
8 | const char *query); | ||
9 | |||
10 | extern void cgit_tree_link(char *name, char *title, char *class, char *head, | ||
11 | char *rev, char *path); | ||
12 | extern void cgit_log_link(char *name, char *title, char *class, char *head, | ||
13 | char *rev, char *path, int ofs, char *grep, | ||
14 | char *pattern); | ||
15 | extern void cgit_commit_link(char *name, char *title, char *class, char *head, | ||
16 | char *rev); | ||
17 | extern void cgit_refs_link(char *name, char *title, char *class, char *head, | ||
18 | char *rev, char *path); | ||
19 | extern void cgit_snapshot_link(char *name, char *title, char *class, | ||
20 | char *head, char *rev, char *archivename); | ||
21 | extern void cgit_diff_link(char *name, char *title, char *class, char *head, | ||
22 | char *new_rev, char *old_rev, char *path); | ||
23 | extern void cgit_object_link(struct object *obj); | ||
24 | |||
25 | extern void cgit_print_error(char *msg); | ||
26 | extern void cgit_print_date(time_t secs, char *format); | ||
27 | extern void cgit_print_age(time_t t, time_t max_relative, char *format); | ||
28 | extern void cgit_print_http_headers(struct cgit_context *ctx); | ||
29 | extern void cgit_print_docstart(struct cgit_context *ctx); | ||
30 | extern void cgit_print_docend(); | ||
31 | extern void cgit_print_pageheader(struct cgit_context *ctx); | ||
32 | extern void cgit_print_filemode(unsigned short mode); | ||
33 | extern void cgit_print_snapshot_links(const char *repo, const char *head, | ||
34 | const char *hex, int snapshots); | ||
35 | |||
36 | #endif /* UI_SHARED_H */ | ||
diff --git a/ui-snapshot.c b/ui-snapshot.c index 512fcd2..966a140 100644 --- a/ui-snapshot.c +++ b/ui-snapshot.c | |||
@@ -1,113 +1,114 @@ | |||
1 | /* ui-snapshot.c: generate snapshot of a commit | 1 | /* ui-snapshot.c: generate snapshot of a commit |
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 "cgit.h" | 9 | #include "cgit.h" |
10 | #include "html.h" | 10 | #include "html.h" |
11 | #include "ui-shared.h" | ||
11 | 12 | ||
12 | static int write_compressed_tar_archive(struct archiver_args *args,const char *filter) | 13 | static int write_compressed_tar_archive(struct archiver_args *args,const char *filter) |
13 | { | 14 | { |
14 | int rw[2]; | 15 | int rw[2]; |
15 | pid_t gzpid; | 16 | pid_t gzpid; |
16 | int stdout2; | 17 | int stdout2; |
17 | int status; | 18 | int status; |
18 | int rv; | 19 | int rv; |
19 | 20 | ||
20 | stdout2 = chk_non_negative(dup(STDIN_FILENO), "Preserving STDOUT before compressing"); | 21 | stdout2 = chk_non_negative(dup(STDIN_FILENO), "Preserving STDOUT before compressing"); |
21 | chk_zero(pipe(rw), "Opening pipe from compressor subprocess"); | 22 | chk_zero(pipe(rw), "Opening pipe from compressor subprocess"); |
22 | gzpid = chk_non_negative(fork(), "Forking compressor subprocess"); | 23 | gzpid = chk_non_negative(fork(), "Forking compressor subprocess"); |
23 | if(gzpid==0) { | 24 | if(gzpid==0) { |
24 | /* child */ | 25 | /* child */ |
25 | chk_zero(close(rw[1]), "Closing write end of pipe in child"); | 26 | chk_zero(close(rw[1]), "Closing write end of pipe in child"); |
26 | chk_zero(close(STDIN_FILENO), "Closing STDIN"); | 27 | chk_zero(close(STDIN_FILENO), "Closing STDIN"); |
27 | chk_non_negative(dup2(rw[0],STDIN_FILENO), "Redirecting compressor input to stdin"); | 28 | chk_non_negative(dup2(rw[0],STDIN_FILENO), "Redirecting compressor input to stdin"); |
28 | execlp(filter,filter,NULL); | 29 | execlp(filter,filter,NULL); |
29 | _exit(-1); | 30 | _exit(-1); |
30 | } | 31 | } |
31 | /* parent */ | 32 | /* parent */ |
32 | chk_zero(close(rw[0]), "Closing read end of pipe"); | 33 | chk_zero(close(rw[0]), "Closing read end of pipe"); |
33 | chk_non_negative(dup2(rw[1],STDOUT_FILENO), "Redirecting output to compressor"); | 34 | chk_non_negative(dup2(rw[1],STDOUT_FILENO), "Redirecting output to compressor"); |
34 | 35 | ||
35 | rv = write_tar_archive(args); | 36 | rv = write_tar_archive(args); |
36 | 37 | ||
37 | chk_zero(close(STDOUT_FILENO), "Closing STDOUT redirected to compressor"); | 38 | chk_zero(close(STDOUT_FILENO), "Closing STDOUT redirected to compressor"); |
38 | chk_non_negative(dup2(stdout2,STDOUT_FILENO), "Restoring uncompressed STDOUT"); | 39 | chk_non_negative(dup2(stdout2,STDOUT_FILENO), "Restoring uncompressed STDOUT"); |
39 | chk_zero(close(stdout2), "Closing uncompressed STDOUT"); | 40 | chk_zero(close(stdout2), "Closing uncompressed STDOUT"); |
40 | chk_zero(close(rw[1]), "Closing write end of pipe in parent"); | 41 | chk_zero(close(rw[1]), "Closing write end of pipe in parent"); |
41 | chk_positive(waitpid(gzpid,&status,0), "Waiting on compressor process"); | 42 | chk_positive(waitpid(gzpid,&status,0), "Waiting on compressor process"); |
42 | if(! ( WIFEXITED(status) && WEXITSTATUS(status)==0 ) ) | 43 | if(! ( WIFEXITED(status) && WEXITSTATUS(status)==0 ) ) |
43 | cgit_print_error("Failed to compress archive"); | 44 | cgit_print_error("Failed to compress archive"); |
44 | 45 | ||
45 | return rv; | 46 | return rv; |
46 | } | 47 | } |
47 | 48 | ||
48 | static int write_tar_gzip_archive(struct archiver_args *args) | 49 | static int write_tar_gzip_archive(struct archiver_args *args) |
49 | { | 50 | { |
50 | return write_compressed_tar_archive(args,"gzip"); | 51 | return write_compressed_tar_archive(args,"gzip"); |
51 | } | 52 | } |
52 | 53 | ||
53 | static int write_tar_bzip2_archive(struct archiver_args *args) | 54 | static int write_tar_bzip2_archive(struct archiver_args *args) |
54 | { | 55 | { |
55 | return write_compressed_tar_archive(args,"bzip2"); | 56 | return write_compressed_tar_archive(args,"bzip2"); |
56 | } | 57 | } |
57 | 58 | ||
58 | const struct cgit_snapshot_format cgit_snapshot_formats[] = { | 59 | const struct cgit_snapshot_format cgit_snapshot_formats[] = { |
59 | { ".zip", "application/x-zip", write_zip_archive, 0x1 }, | 60 | { ".zip", "application/x-zip", write_zip_archive, 0x1 }, |
60 | { ".tar.gz", "application/x-tar", write_tar_gzip_archive, 0x2 }, | 61 | { ".tar.gz", "application/x-tar", write_tar_gzip_archive, 0x2 }, |
61 | { ".tar.bz2", "application/x-tar", write_tar_bzip2_archive, 0x4 }, | 62 | { ".tar.bz2", "application/x-tar", write_tar_bzip2_archive, 0x4 }, |
62 | { ".tar", "application/x-tar", write_tar_archive, 0x8 }, | 63 | { ".tar", "application/x-tar", write_tar_archive, 0x8 }, |
63 | {} | 64 | {} |
64 | }; | 65 | }; |
65 | 66 | ||
66 | static int make_snapshot(const struct cgit_snapshot_format *format, | 67 | static int make_snapshot(const struct cgit_snapshot_format *format, |
67 | const char *hex, const char *prefix, | 68 | const char *hex, const char *prefix, |
68 | const char *filename) | 69 | const char *filename) |
69 | { | 70 | { |
70 | struct archiver_args args; | 71 | struct archiver_args args; |
71 | struct commit *commit; | 72 | struct commit *commit; |
72 | unsigned char sha1[20]; | 73 | unsigned char sha1[20]; |
73 | 74 | ||
74 | if(get_sha1(hex, sha1)) { | 75 | if(get_sha1(hex, sha1)) { |
75 | cgit_print_error(fmt("Bad object id: %s", hex)); | 76 | cgit_print_error(fmt("Bad object id: %s", hex)); |
76 | return 1; | 77 | return 1; |
77 | } | 78 | } |
78 | commit = lookup_commit_reference(sha1); | 79 | commit = lookup_commit_reference(sha1); |
79 | if(!commit) { | 80 | if(!commit) { |
80 | cgit_print_error(fmt("Not a commit reference: %s", hex)); | 81 | cgit_print_error(fmt("Not a commit reference: %s", hex)); |
81 | return 1; | 82 | return 1; |
82 | } | 83 | } |
83 | memset(&args, 0, sizeof(args)); | 84 | memset(&args, 0, sizeof(args)); |
84 | args.base = fmt("%s/", prefix); | 85 | args.base = fmt("%s/", prefix); |
85 | args.tree = commit->tree; | 86 | args.tree = commit->tree; |
86 | args.time = commit->date; | 87 | args.time = commit->date; |
87 | ctx.page.mimetype = xstrdup(format->mimetype); | 88 | ctx.page.mimetype = xstrdup(format->mimetype); |
88 | ctx.page.filename = xstrdup(filename); | 89 | ctx.page.filename = xstrdup(filename); |
89 | cgit_print_http_headers(&ctx); | 90 | cgit_print_http_headers(&ctx); |
90 | format->write_func(&args); | 91 | format->write_func(&args); |
91 | return 0; | 92 | return 0; |
92 | } | 93 | } |
93 | 94 | ||
94 | void cgit_print_snapshot(const char *head, const char *hex, const char *prefix, | 95 | void cgit_print_snapshot(const char *head, const char *hex, const char *prefix, |
95 | const char *filename, int snapshots) | 96 | const char *filename, int snapshots) |
96 | { | 97 | { |
97 | const struct cgit_snapshot_format* f; | 98 | const struct cgit_snapshot_format* f; |
98 | int sl, fnl; | 99 | int sl, fnl; |
99 | 100 | ||
100 | fnl = strlen(filename); | 101 | fnl = strlen(filename); |
101 | if (!hex) | 102 | if (!hex) |
102 | hex = head; | 103 | hex = head; |
103 | for (f = cgit_snapshot_formats; f->suffix; f++) { | 104 | for (f = cgit_snapshot_formats; f->suffix; f++) { |
104 | if (!(snapshots & f->bit)) | 105 | if (!(snapshots & f->bit)) |
105 | continue; | 106 | continue; |
106 | sl = strlen(f->suffix); | 107 | sl = strlen(f->suffix); |
107 | if(fnl < sl || strcmp(&filename[fnl-sl], f->suffix)) | 108 | if(fnl < sl || strcmp(&filename[fnl-sl], f->suffix)) |
108 | continue; | 109 | continue; |
109 | make_snapshot(f, hex, prefix, filename); | 110 | make_snapshot(f, hex, prefix, filename); |
110 | return; | 111 | return; |
111 | } | 112 | } |
112 | cgit_print_error(fmt("Unsupported snapshot format: %s", filename)); | 113 | cgit_print_error(fmt("Unsupported snapshot format: %s", filename)); |
113 | } | 114 | } |
@@ -1,74 +1,75 @@ | |||
1 | /* ui-tag.c: display a tag | 1 | /* ui-tag.c: display a tag |
2 | * | 2 | * |
3 | * Copyright (C) 2007 Lars Hjemli | 3 | * Copyright (C) 2007 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 "cgit.h" | 9 | #include "cgit.h" |
10 | #include "html.h" | 10 | #include "html.h" |
11 | #include "ui-shared.h" | ||
11 | 12 | ||
12 | static void print_tag_content(char *buf) | 13 | static void print_tag_content(char *buf) |
13 | { | 14 | { |
14 | char *p; | 15 | char *p; |
15 | 16 | ||
16 | if (!buf) | 17 | if (!buf) |
17 | return; | 18 | return; |
18 | 19 | ||
19 | html("<div class='commit-subject'>"); | 20 | html("<div class='commit-subject'>"); |
20 | p = strchr(buf, '\n'); | 21 | p = strchr(buf, '\n'); |
21 | if (p) | 22 | if (p) |
22 | *p = '\0'; | 23 | *p = '\0'; |
23 | html_txt(buf); | 24 | html_txt(buf); |
24 | html("</div>"); | 25 | html("</div>"); |
25 | if (p) { | 26 | if (p) { |
26 | html("<div class='commit-msg'>"); | 27 | html("<div class='commit-msg'>"); |
27 | html_txt(++p); | 28 | html_txt(++p); |
28 | html("</div>"); | 29 | html("</div>"); |
29 | } | 30 | } |
30 | } | 31 | } |
31 | 32 | ||
32 | void cgit_print_tag(char *revname) | 33 | void cgit_print_tag(char *revname) |
33 | { | 34 | { |
34 | unsigned char sha1[20]; | 35 | unsigned char sha1[20]; |
35 | struct object *obj; | 36 | struct object *obj; |
36 | struct tag *tag; | 37 | struct tag *tag; |
37 | struct taginfo *info; | 38 | struct taginfo *info; |
38 | 39 | ||
39 | if (get_sha1(revname, sha1)) { | 40 | if (get_sha1(revname, sha1)) { |
40 | cgit_print_error(fmt("Bad tag reference: %s", revname)); | 41 | cgit_print_error(fmt("Bad tag reference: %s", revname)); |
41 | return; | 42 | return; |
42 | } | 43 | } |
43 | obj = parse_object(sha1); | 44 | obj = parse_object(sha1); |
44 | if (!obj) { | 45 | if (!obj) { |
45 | cgit_print_error(fmt("Bad object id: %s", sha1_to_hex(sha1))); | 46 | cgit_print_error(fmt("Bad object id: %s", sha1_to_hex(sha1))); |
46 | return; | 47 | return; |
47 | } | 48 | } |
48 | if (obj->type == OBJ_TAG) { | 49 | if (obj->type == OBJ_TAG) { |
49 | tag = lookup_tag(sha1); | 50 | tag = lookup_tag(sha1); |
50 | if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) { | 51 | if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) { |
51 | cgit_print_error(fmt("Bad tag object: %s", revname)); | 52 | cgit_print_error(fmt("Bad tag object: %s", revname)); |
52 | return; | 53 | return; |
53 | } | 54 | } |
54 | html("<table class='commit-info'>\n"); | 55 | html("<table class='commit-info'>\n"); |
55 | htmlf("<tr><td>Tag name</td><td>%s (%s)</td></tr>\n", | 56 | htmlf("<tr><td>Tag name</td><td>%s (%s)</td></tr>\n", |
56 | revname, sha1_to_hex(sha1)); | 57 | revname, sha1_to_hex(sha1)); |
57 | if (info->tagger_date > 0) { | 58 | if (info->tagger_date > 0) { |
58 | html("<tr><td>Tag date</td><td>"); | 59 | html("<tr><td>Tag date</td><td>"); |
59 | cgit_print_date(info->tagger_date, FMT_LONGDATE); | 60 | cgit_print_date(info->tagger_date, FMT_LONGDATE); |
60 | html("</td></tr>\n"); | 61 | html("</td></tr>\n"); |
61 | } | 62 | } |
62 | if (info->tagger) { | 63 | if (info->tagger) { |
63 | html("<tr><td>Tagged by</td><td>"); | 64 | html("<tr><td>Tagged by</td><td>"); |
64 | html_txt(info->tagger); | 65 | html_txt(info->tagger); |
65 | html("</td></tr>\n"); | 66 | html("</td></tr>\n"); |
66 | } | 67 | } |
67 | html("<tr><td>Tagged object</td><td>"); | 68 | html("<tr><td>Tagged object</td><td>"); |
68 | cgit_object_link(tag->tagged); | 69 | cgit_object_link(tag->tagged); |
69 | html("</td></tr>\n"); | 70 | html("</td></tr>\n"); |
70 | html("</table>\n"); | 71 | html("</table>\n"); |
71 | print_tag_content(info->msg); | 72 | print_tag_content(info->msg); |
72 | } | 73 | } |
73 | return; | 74 | return; |
74 | } | 75 | } |
@@ -1,138 +1,139 @@ | |||
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 "cgit.h" | 9 | #include "cgit.h" |
10 | #include "html.h" | 10 | #include "html.h" |
11 | #include "ui-shared.h" | ||
11 | 12 | ||
12 | char *curr_rev; | 13 | char *curr_rev; |
13 | char *match_path; | 14 | char *match_path; |
14 | int header = 0; | 15 | int header = 0; |
15 | 16 | ||
16 | static void print_object(const unsigned char *sha1, char *path) | 17 | static void print_object(const unsigned char *sha1, char *path) |
17 | { | 18 | { |
18 | enum object_type type; | 19 | enum object_type type; |
19 | char *buf; | 20 | char *buf; |
20 | unsigned long size, lineno, start, idx; | 21 | unsigned long size, lineno, start, idx; |
21 | const char *linefmt = "<tr><td class='no'><a id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a></td><td class='txt'>"; | 22 | const char *linefmt = "<tr><td class='no'><a id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a></td><td class='txt'>"; |
22 | 23 | ||
23 | type = sha1_object_info(sha1, &size); | 24 | type = sha1_object_info(sha1, &size); |
24 | if (type == OBJ_BAD) { | 25 | if (type == OBJ_BAD) { |
25 | cgit_print_error(fmt("Bad object name: %s", | 26 | cgit_print_error(fmt("Bad object name: %s", |
26 | sha1_to_hex(sha1))); | 27 | sha1_to_hex(sha1))); |
27 | return; | 28 | return; |
28 | } | 29 | } |
29 | 30 | ||
30 | buf = read_sha1_file(sha1, &type, &size); | 31 | buf = read_sha1_file(sha1, &type, &size); |
31 | if (!buf) { | 32 | if (!buf) { |
32 | cgit_print_error(fmt("Error reading object %s", | 33 | cgit_print_error(fmt("Error reading object %s", |
33 | sha1_to_hex(sha1))); | 34 | sha1_to_hex(sha1))); |
34 | return; | 35 | return; |
35 | } | 36 | } |
36 | 37 | ||
37 | html(" blob: <a href='"); | 38 | html(" blob: <a href='"); |
38 | html_attr(cgit_pageurl(ctx.qry.repo, "blob", fmt("id=%s", sha1_to_hex(sha1)))); | 39 | html_attr(cgit_pageurl(ctx.qry.repo, "blob", fmt("id=%s", sha1_to_hex(sha1)))); |
39 | htmlf("'>%s</a>",sha1_to_hex(sha1)); | 40 | htmlf("'>%s</a>",sha1_to_hex(sha1)); |
40 | 41 | ||
41 | html("<table summary='blob content' class='blob'>\n"); | 42 | html("<table summary='blob content' class='blob'>\n"); |
42 | idx = 0; | 43 | idx = 0; |
43 | start = 0; | 44 | start = 0; |
44 | lineno = 0; | 45 | lineno = 0; |
45 | while(idx < size) { | 46 | while(idx < size) { |
46 | if (buf[idx] == '\n') { | 47 | if (buf[idx] == '\n') { |
47 | buf[idx] = '\0'; | 48 | buf[idx] = '\0'; |
48 | htmlf(linefmt, ++lineno); | 49 | htmlf(linefmt, ++lineno); |
49 | html_txt(buf + start); | 50 | html_txt(buf + start); |
50 | html("</td></tr>\n"); | 51 | html("</td></tr>\n"); |
51 | start = idx + 1; | 52 | start = idx + 1; |
52 | } | 53 | } |
53 | idx++; | 54 | idx++; |
54 | } | 55 | } |
55 | htmlf(linefmt, ++lineno); | 56 | htmlf(linefmt, ++lineno); |
56 | html_txt(buf + start); | 57 | html_txt(buf + start); |
57 | html("</td></tr>\n"); | 58 | html("</td></tr>\n"); |
58 | html("</table>\n"); | 59 | html("</table>\n"); |
59 | } | 60 | } |
60 | 61 | ||
61 | 62 | ||
62 | static int ls_item(const unsigned char *sha1, const char *base, int baselen, | 63 | static int ls_item(const unsigned char *sha1, const char *base, int baselen, |
63 | const char *pathname, unsigned int mode, int stage) | 64 | const char *pathname, unsigned int mode, int stage) |
64 | { | 65 | { |
65 | char *name; | 66 | char *name; |
66 | char *fullpath; | 67 | char *fullpath; |
67 | enum object_type type; | 68 | enum object_type type; |
68 | unsigned long size = 0; | 69 | unsigned long size = 0; |
69 | 70 | ||
70 | name = xstrdup(pathname); | 71 | name = xstrdup(pathname); |
71 | fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", | 72 | fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", |
72 | ctx.qry.path ? "/" : "", name); | 73 | ctx.qry.path ? "/" : "", name); |
73 | 74 | ||
74 | type = sha1_object_info(sha1, &size); | 75 | type = sha1_object_info(sha1, &size); |
75 | if (type == OBJ_BAD && !S_ISGITLINK(mode)) { | 76 | if (type == OBJ_BAD && !S_ISGITLINK(mode)) { |
76 | htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", | 77 | htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", |
77 | name, | 78 | name, |
78 | sha1_to_hex(sha1)); | 79 | sha1_to_hex(sha1)); |
79 | return 0; | 80 | return 0; |
80 | } | 81 | } |
81 | 82 | ||
82 | html("<tr><td class='ls-mode'>"); | 83 | html("<tr><td class='ls-mode'>"); |
83 | cgit_print_filemode(mode); | 84 | cgit_print_filemode(mode); |
84 | html("</td><td>"); | 85 | html("</td><td>"); |
85 | if (S_ISGITLINK(mode)) { | 86 | if (S_ISGITLINK(mode)) { |
86 | htmlf("<a class='ls-mod' href='"); | 87 | htmlf("<a class='ls-mod' href='"); |
87 | html_attr(fmt(ctx.repo->module_link, | 88 | html_attr(fmt(ctx.repo->module_link, |
88 | name, | 89 | name, |
89 | sha1_to_hex(sha1))); | 90 | sha1_to_hex(sha1))); |
90 | html("'>"); | 91 | html("'>"); |
91 | html_txt(name); | 92 | html_txt(name); |
92 | html("</a>"); | 93 | html("</a>"); |
93 | } else if (S_ISDIR(mode)) { | 94 | } else if (S_ISDIR(mode)) { |
94 | cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, | 95 | cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, |
95 | curr_rev, fullpath); | 96 | curr_rev, fullpath); |
96 | } else { | 97 | } else { |
97 | cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head, | 98 | cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head, |
98 | curr_rev, fullpath); | 99 | curr_rev, fullpath); |
99 | } | 100 | } |
100 | htmlf("</td><td class='ls-size'>%li</td>", size); | 101 | htmlf("</td><td class='ls-size'>%li</td>", size); |
101 | 102 | ||
102 | html("<td>"); | 103 | html("<td>"); |
103 | cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, | 104 | cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, |
104 | fullpath, 0, NULL, NULL); | 105 | fullpath, 0, NULL, NULL); |
105 | html("</td></tr>\n"); | 106 | html("</td></tr>\n"); |
106 | free(name); | 107 | free(name); |
107 | return 0; | 108 | return 0; |
108 | } | 109 | } |
109 | 110 | ||
110 | static void ls_head() | 111 | static void ls_head() |
111 | { | 112 | { |
112 | html("<table summary='tree listing' class='list'>\n"); | 113 | html("<table summary='tree listing' class='list'>\n"); |
113 | html("<tr class='nohover'>"); | 114 | html("<tr class='nohover'>"); |
114 | html("<th class='left'>Mode</th>"); | 115 | html("<th class='left'>Mode</th>"); |
115 | html("<th class='left'>Name</th>"); | 116 | html("<th class='left'>Name</th>"); |
116 | html("<th class='right'>Size</th>"); | 117 | html("<th class='right'>Size</th>"); |
117 | html("<th/>"); | 118 | html("<th/>"); |
118 | html("</tr>\n"); | 119 | html("</tr>\n"); |
119 | header = 1; | 120 | header = 1; |
120 | } | 121 | } |
121 | 122 | ||
122 | static void ls_tail() | 123 | static void ls_tail() |
123 | { | 124 | { |
124 | if (!header) | 125 | if (!header) |
125 | return; | 126 | return; |
126 | html("</table>\n"); | 127 | html("</table>\n"); |
127 | header = 0; | 128 | header = 0; |
128 | } | 129 | } |
129 | 130 | ||
130 | static void ls_tree(const unsigned char *sha1, char *path) | 131 | static void ls_tree(const unsigned char *sha1, char *path) |
131 | { | 132 | { |
132 | struct tree *tree; | 133 | struct tree *tree; |
133 | 134 | ||
134 | tree = parse_tree_indirect(sha1); | 135 | tree = parse_tree_indirect(sha1); |
135 | if (!tree) { | 136 | if (!tree) { |
136 | cgit_print_error(fmt("Not a tree object: %s", | 137 | cgit_print_error(fmt("Not a tree object: %s", |
137 | sha1_to_hex(sha1))); | 138 | sha1_to_hex(sha1))); |
138 | return; | 139 | return; |