summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2009-07-31 14:55:27 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2009-07-31 15:41:21 (UTC)
commit46b7abed99e957008c01c02cf612aa526ba92f04 (patch) (unidiff)
tree2cdbfe5281c2ffa645def488d53db0a8b82842f4
parent18dfbdc099c1398016427b6fa7f1a1facb363998 (diff)
downloadcgit-46b7abed99e957008c01c02cf612aa526ba92f04.zip
cgit-46b7abed99e957008c01c02cf612aa526ba92f04.tar.gz
cgit-46b7abed99e957008c01c02cf612aa526ba92f04.tar.bz2
ui-tree: add support for source-filter option
This new option is used to specify an external command which will be executed when displaying blob content in the tree view. Blob content will be written to STDIN of the filter and STDOUT from the filter will be included verbatim in the html output from cgit. The file name of the blob will be passed as the only argument to the filter command. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c2
-rw-r--r--cgit.h1
-rw-r--r--cgitrc.5.txt8
-rw-r--r--ui-tree.c18
4 files changed, 25 insertions, 4 deletions
diff --git a/cgit.c b/cgit.c
index 779a464..eb7b45d 100644
--- a/cgit.c
+++ b/cgit.c
@@ -55,96 +55,98 @@ void config_cb(const char *name, const char *value)
55 else if (!strcmp(name, "index-header")) 55 else if (!strcmp(name, "index-header"))
56 ctx.cfg.index_header = xstrdup(value); 56 ctx.cfg.index_header = xstrdup(value);
57 else if (!strcmp(name, "index-info")) 57 else if (!strcmp(name, "index-info"))
58 ctx.cfg.index_info = xstrdup(value); 58 ctx.cfg.index_info = xstrdup(value);
59 else if (!strcmp(name, "logo-link")) 59 else if (!strcmp(name, "logo-link"))
60 ctx.cfg.logo_link = xstrdup(value); 60 ctx.cfg.logo_link = xstrdup(value);
61 else if (!strcmp(name, "module-link")) 61 else if (!strcmp(name, "module-link"))
62 ctx.cfg.module_link = xstrdup(value); 62 ctx.cfg.module_link = xstrdup(value);
63 else if (!strcmp(name, "virtual-root")) { 63 else if (!strcmp(name, "virtual-root")) {
64 ctx.cfg.virtual_root = trim_end(value, '/'); 64 ctx.cfg.virtual_root = trim_end(value, '/');
65 if (!ctx.cfg.virtual_root && (!strcmp(value, "/"))) 65 if (!ctx.cfg.virtual_root && (!strcmp(value, "/")))
66 ctx.cfg.virtual_root = ""; 66 ctx.cfg.virtual_root = "";
67 } else if (!strcmp(name, "nocache")) 67 } else if (!strcmp(name, "nocache"))
68 ctx.cfg.nocache = atoi(value); 68 ctx.cfg.nocache = atoi(value);
69 else if (!strcmp(name, "noheader")) 69 else if (!strcmp(name, "noheader"))
70 ctx.cfg.noheader = atoi(value); 70 ctx.cfg.noheader = atoi(value);
71 else if (!strcmp(name, "snapshots")) 71 else if (!strcmp(name, "snapshots"))
72 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value); 72 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value);
73 else if (!strcmp(name, "enable-index-links")) 73 else if (!strcmp(name, "enable-index-links"))
74 ctx.cfg.enable_index_links = atoi(value); 74 ctx.cfg.enable_index_links = atoi(value);
75 else if (!strcmp(name, "enable-log-filecount")) 75 else if (!strcmp(name, "enable-log-filecount"))
76 ctx.cfg.enable_log_filecount = atoi(value); 76 ctx.cfg.enable_log_filecount = atoi(value);
77 else if (!strcmp(name, "enable-log-linecount")) 77 else if (!strcmp(name, "enable-log-linecount"))
78 ctx.cfg.enable_log_linecount = atoi(value); 78 ctx.cfg.enable_log_linecount = atoi(value);
79 else if (!strcmp(name, "max-stats")) 79 else if (!strcmp(name, "max-stats"))
80 ctx.cfg.max_stats = cgit_find_stats_period(value, NULL); 80 ctx.cfg.max_stats = cgit_find_stats_period(value, NULL);
81 else if (!strcmp(name, "cache-size")) 81 else if (!strcmp(name, "cache-size"))
82 ctx.cfg.cache_size = atoi(value); 82 ctx.cfg.cache_size = atoi(value);
83 else if (!strcmp(name, "cache-root")) 83 else if (!strcmp(name, "cache-root"))
84 ctx.cfg.cache_root = xstrdup(value); 84 ctx.cfg.cache_root = xstrdup(value);
85 else if (!strcmp(name, "cache-root-ttl")) 85 else if (!strcmp(name, "cache-root-ttl"))
86 ctx.cfg.cache_root_ttl = atoi(value); 86 ctx.cfg.cache_root_ttl = atoi(value);
87 else if (!strcmp(name, "cache-repo-ttl")) 87 else if (!strcmp(name, "cache-repo-ttl"))
88 ctx.cfg.cache_repo_ttl = atoi(value); 88 ctx.cfg.cache_repo_ttl = atoi(value);
89 else if (!strcmp(name, "cache-static-ttl")) 89 else if (!strcmp(name, "cache-static-ttl"))
90 ctx.cfg.cache_static_ttl = atoi(value); 90 ctx.cfg.cache_static_ttl = atoi(value);
91 else if (!strcmp(name, "cache-dynamic-ttl")) 91 else if (!strcmp(name, "cache-dynamic-ttl"))
92 ctx.cfg.cache_dynamic_ttl = atoi(value); 92 ctx.cfg.cache_dynamic_ttl = atoi(value);
93 else if (!strcmp(name, "embedded")) 93 else if (!strcmp(name, "embedded"))
94 ctx.cfg.embedded = atoi(value); 94 ctx.cfg.embedded = atoi(value);
95 else if (!strcmp(name, "max-message-length")) 95 else if (!strcmp(name, "max-message-length"))
96 ctx.cfg.max_msg_len = atoi(value); 96 ctx.cfg.max_msg_len = atoi(value);
97 else if (!strcmp(name, "max-repodesc-length")) 97 else if (!strcmp(name, "max-repodesc-length"))
98 ctx.cfg.max_repodesc_len = atoi(value); 98 ctx.cfg.max_repodesc_len = atoi(value);
99 else if (!strcmp(name, "max-repo-count")) 99 else if (!strcmp(name, "max-repo-count"))
100 ctx.cfg.max_repo_count = atoi(value); 100 ctx.cfg.max_repo_count = atoi(value);
101 else if (!strcmp(name, "max-commit-count")) 101 else if (!strcmp(name, "max-commit-count"))
102 ctx.cfg.max_commit_count = atoi(value); 102 ctx.cfg.max_commit_count = atoi(value);
103 else if (!strcmp(name, "source-filter"))
104 ctx.cfg.source_filter = new_filter(value, 1);
103 else if (!strcmp(name, "summary-log")) 105 else if (!strcmp(name, "summary-log"))
104 ctx.cfg.summary_log = atoi(value); 106 ctx.cfg.summary_log = atoi(value);
105 else if (!strcmp(name, "summary-branches")) 107 else if (!strcmp(name, "summary-branches"))
106 ctx.cfg.summary_branches = atoi(value); 108 ctx.cfg.summary_branches = atoi(value);
107 else if (!strcmp(name, "summary-tags")) 109 else if (!strcmp(name, "summary-tags"))
108 ctx.cfg.summary_tags = atoi(value); 110 ctx.cfg.summary_tags = atoi(value);
109 else if (!strcmp(name, "agefile")) 111 else if (!strcmp(name, "agefile"))
110 ctx.cfg.agefile = xstrdup(value); 112 ctx.cfg.agefile = xstrdup(value);
111 else if (!strcmp(name, "renamelimit")) 113 else if (!strcmp(name, "renamelimit"))
112 ctx.cfg.renamelimit = atoi(value); 114 ctx.cfg.renamelimit = atoi(value);
113 else if (!strcmp(name, "robots")) 115 else if (!strcmp(name, "robots"))
114 ctx.cfg.robots = xstrdup(value); 116 ctx.cfg.robots = xstrdup(value);
115 else if (!strcmp(name, "clone-prefix")) 117 else if (!strcmp(name, "clone-prefix"))
116 ctx.cfg.clone_prefix = xstrdup(value); 118 ctx.cfg.clone_prefix = xstrdup(value);
117 else if (!strcmp(name, "local-time")) 119 else if (!strcmp(name, "local-time"))
118 ctx.cfg.local_time = atoi(value); 120 ctx.cfg.local_time = atoi(value);
119 else if (!strcmp(name, "repo.group")) 121 else if (!strcmp(name, "repo.group"))
120 ctx.cfg.repo_group = xstrdup(value); 122 ctx.cfg.repo_group = xstrdup(value);
121 else if (!strcmp(name, "repo.url")) 123 else if (!strcmp(name, "repo.url"))
122 ctx.repo = cgit_add_repo(value); 124 ctx.repo = cgit_add_repo(value);
123 else if (!strcmp(name, "repo.name")) 125 else if (!strcmp(name, "repo.name"))
124 ctx.repo->name = xstrdup(value); 126 ctx.repo->name = xstrdup(value);
125 else if (ctx.repo && !strcmp(name, "repo.path")) 127 else if (ctx.repo && !strcmp(name, "repo.path"))
126 ctx.repo->path = trim_end(value, '/'); 128 ctx.repo->path = trim_end(value, '/');
127 else if (ctx.repo && !strcmp(name, "repo.clone-url")) 129 else if (ctx.repo && !strcmp(name, "repo.clone-url"))
128 ctx.repo->clone_url = xstrdup(value); 130 ctx.repo->clone_url = xstrdup(value);
129 else if (ctx.repo && !strcmp(name, "repo.desc")) 131 else if (ctx.repo && !strcmp(name, "repo.desc"))
130 ctx.repo->desc = xstrdup(value); 132 ctx.repo->desc = xstrdup(value);
131 else if (ctx.repo && !strcmp(name, "repo.owner")) 133 else if (ctx.repo && !strcmp(name, "repo.owner"))
132 ctx.repo->owner = xstrdup(value); 134 ctx.repo->owner = xstrdup(value);
133 else if (ctx.repo && !strcmp(name, "repo.defbranch")) 135 else if (ctx.repo && !strcmp(name, "repo.defbranch"))
134 ctx.repo->defbranch = xstrdup(value); 136 ctx.repo->defbranch = xstrdup(value);
135 else if (ctx.repo && !strcmp(name, "repo.snapshots")) 137 else if (ctx.repo && !strcmp(name, "repo.snapshots"))
136 ctx.repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */ 138 ctx.repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */
137 else if (ctx.repo && !strcmp(name, "repo.enable-log-filecount")) 139 else if (ctx.repo && !strcmp(name, "repo.enable-log-filecount"))
138 ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value); 140 ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value);
139 else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount")) 141 else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount"))
140 ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value); 142 ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value);
141 else if (ctx.repo && !strcmp(name, "repo.max-stats")) 143 else if (ctx.repo && !strcmp(name, "repo.max-stats"))
142 ctx.repo->max_stats = cgit_find_stats_period(value, NULL); 144 ctx.repo->max_stats = cgit_find_stats_period(value, NULL);
143 else if (ctx.repo && !strcmp(name, "repo.module-link")) 145 else if (ctx.repo && !strcmp(name, "repo.module-link"))
144 ctx.repo->module_link= xstrdup(value); 146 ctx.repo->module_link= xstrdup(value);
145 else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) { 147 else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) {
146 if (*value == '/') 148 if (*value == '/')
147 ctx.repo->readme = xstrdup(value); 149 ctx.repo->readme = xstrdup(value);
148 else 150 else
149 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value)); 151 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value));
150 } else if (!strcmp(name, "include")) 152 } else if (!strcmp(name, "include"))
diff --git a/cgit.h b/cgit.h
index d0fff1f..f9cf0df 100644
--- a/cgit.h
+++ b/cgit.h
@@ -138,96 +138,97 @@ struct cgit_filter {
138 int exitstatus; 138 int exitstatus;
139}; 139};
140 140
141struct cgit_config { 141struct cgit_config {
142 char *agefile; 142 char *agefile;
143 char *cache_root; 143 char *cache_root;
144 char *clone_prefix; 144 char *clone_prefix;
145 char *css; 145 char *css;
146 char *favicon; 146 char *favicon;
147 char *footer; 147 char *footer;
148 char *head_include; 148 char *head_include;
149 char *header; 149 char *header;
150 char *index_header; 150 char *index_header;
151 char *index_info; 151 char *index_info;
152 char *logo; 152 char *logo;
153 char *logo_link; 153 char *logo_link;
154 char *module_link; 154 char *module_link;
155 char *repo_group; 155 char *repo_group;
156 char *robots; 156 char *robots;
157 char *root_title; 157 char *root_title;
158 char *root_desc; 158 char *root_desc;
159 char *root_readme; 159 char *root_readme;
160 char *script_name; 160 char *script_name;
161 char *virtual_root; 161 char *virtual_root;
162 int cache_size; 162 int cache_size;
163 int cache_dynamic_ttl; 163 int cache_dynamic_ttl;
164 int cache_max_create_time; 164 int cache_max_create_time;
165 int cache_repo_ttl; 165 int cache_repo_ttl;
166 int cache_root_ttl; 166 int cache_root_ttl;
167 int cache_static_ttl; 167 int cache_static_ttl;
168 int embedded; 168 int embedded;
169 int enable_index_links; 169 int enable_index_links;
170 int enable_log_filecount; 170 int enable_log_filecount;
171 int enable_log_linecount; 171 int enable_log_linecount;
172 int local_time; 172 int local_time;
173 int max_repo_count; 173 int max_repo_count;
174 int max_commit_count; 174 int max_commit_count;
175 int max_lock_attempts; 175 int max_lock_attempts;
176 int max_msg_len; 176 int max_msg_len;
177 int max_repodesc_len; 177 int max_repodesc_len;
178 int max_stats; 178 int max_stats;
179 int nocache; 179 int nocache;
180 int noheader; 180 int noheader;
181 int renamelimit; 181 int renamelimit;
182 int snapshots; 182 int snapshots;
183 int summary_branches; 183 int summary_branches;
184 int summary_log; 184 int summary_log;
185 int summary_tags; 185 int summary_tags;
186 struct cgit_filter *source_filter;
186}; 187};
187 188
188struct cgit_page { 189struct cgit_page {
189 time_t modified; 190 time_t modified;
190 time_t expires; 191 time_t expires;
191 size_t size; 192 size_t size;
192 char *mimetype; 193 char *mimetype;
193 char *charset; 194 char *charset;
194 char *filename; 195 char *filename;
195 char *etag; 196 char *etag;
196 char *title; 197 char *title;
197 int status; 198 int status;
198 char *statusmsg; 199 char *statusmsg;
199}; 200};
200 201
201struct cgit_context { 202struct cgit_context {
202 struct cgit_query qry; 203 struct cgit_query qry;
203 struct cgit_config cfg; 204 struct cgit_config cfg;
204 struct cgit_repo *repo; 205 struct cgit_repo *repo;
205 struct cgit_page page; 206 struct cgit_page page;
206}; 207};
207 208
208struct cgit_snapshot_format { 209struct cgit_snapshot_format {
209 const char *suffix; 210 const char *suffix;
210 const char *mimetype; 211 const char *mimetype;
211 write_archive_fn_t write_func; 212 write_archive_fn_t write_func;
212 int bit; 213 int bit;
213}; 214};
214 215
215extern const char *cgit_version; 216extern const char *cgit_version;
216 217
217extern struct cgit_repolist cgit_repolist; 218extern struct cgit_repolist cgit_repolist;
218extern struct cgit_context ctx; 219extern struct cgit_context ctx;
219extern const struct cgit_snapshot_format cgit_snapshot_formats[]; 220extern const struct cgit_snapshot_format cgit_snapshot_formats[];
220 221
221extern struct cgit_repo *cgit_add_repo(const char *url); 222extern struct cgit_repo *cgit_add_repo(const char *url);
222extern struct cgit_repo *cgit_get_repoinfo(const char *url); 223extern struct cgit_repo *cgit_get_repoinfo(const char *url);
223extern void cgit_repo_config_cb(const char *name, const char *value); 224extern void cgit_repo_config_cb(const char *name, const char *value);
224 225
225extern int chk_zero(int result, char *msg); 226extern int chk_zero(int result, char *msg);
226extern int chk_positive(int result, char *msg); 227extern int chk_positive(int result, char *msg);
227extern int chk_non_negative(int result, char *msg); 228extern int chk_non_negative(int result, char *msg);
228 229
229extern char *trim_end(const char *str, char c); 230extern char *trim_end(const char *str, char c);
230extern char *strlpart(char *txt, int maxlen); 231extern char *strlpart(char *txt, int maxlen);
231extern char *strrpart(char *txt, int maxlen); 232extern char *strrpart(char *txt, int maxlen);
232 233
233extern void cgit_add_ref(struct reflist *list, struct refinfo *ref); 234extern void cgit_add_ref(struct reflist *list, struct refinfo *ref);
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index a207fe0..d420ad4 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -153,96 +153,104 @@ module-link::
153 formatstring are the path and SHA1 of the submodule commit. Default 153 formatstring are the path and SHA1 of the submodule commit. Default
154 value: "./?repo=%s&page=commit&id=%s" 154 value: "./?repo=%s&page=commit&id=%s"
155 155
156nocache:: 156nocache::
157 If set to the value "1" caching will be disabled. This settings is 157 If set to the value "1" caching will be disabled. This settings is
158 deprecated, and will not be honored starting with cgit-1.0. Default 158 deprecated, and will not be honored starting with cgit-1.0. Default
159 value: "0". 159 value: "0".
160 160
161noheader:: 161noheader::
162 Flag which, when set to "1", will make cgit omit the standard header 162 Flag which, when set to "1", will make cgit omit the standard header
163 on all pages. Default value: none. See also: "embedded". 163 on all pages. Default value: none. See also: "embedded".
164 164
165renamelimit:: 165renamelimit::
166 Maximum number of files to consider when detecting renames. The value 166 Maximum number of files to consider when detecting renames. The value
167 "-1" uses the compiletime value in git (for further info, look at 167 "-1" uses the compiletime value in git (for further info, look at
168 `man git-diff`). Default value: "-1". 168 `man git-diff`). Default value: "-1".
169 169
170repo.group:: 170repo.group::
171 A value for the current repository group, which all repositories 171 A value for the current repository group, which all repositories
172 specified after this setting will inherit. Default value: none. 172 specified after this setting will inherit. Default value: none.
173 173
174robots:: 174robots::
175 Text used as content for the "robots" meta-tag. Default value: 175 Text used as content for the "robots" meta-tag. Default value:
176 "index, nofollow". 176 "index, nofollow".
177 177
178root-desc:: 178root-desc::
179 Text printed below the heading on the repository index page. Default 179 Text printed below the heading on the repository index page. Default
180 value: "a fast webinterface for the git dscm". 180 value: "a fast webinterface for the git dscm".
181 181
182root-readme:: 182root-readme::
183 The content of the file specified with this option will be included 183 The content of the file specified with this option will be included
184 verbatim below the "about" link on the repository index page. Default 184 verbatim below the "about" link on the repository index page. Default
185 value: none. 185 value: none.
186 186
187root-title:: 187root-title::
188 Text printed as heading on the repository index page. Default value: 188 Text printed as heading on the repository index page. Default value:
189 "Git Repository Browser". 189 "Git Repository Browser".
190 190
191snapshots:: 191snapshots::
192 Text which specifies the default (and allowed) set of snapshot formats 192 Text which specifies the default (and allowed) set of snapshot formats
193 supported by cgit. The value is a space-separated list of zero or more 193 supported by cgit. The value is a space-separated list of zero or more
194 of the following values: 194 of the following values:
195 "tar" uncompressed tar-file 195 "tar" uncompressed tar-file
196 "tar.gz"gzip-compressed tar-file 196 "tar.gz"gzip-compressed tar-file
197 "tar.bz2"bzip-compressed tar-file 197 "tar.bz2"bzip-compressed tar-file
198 "zip" zip-file 198 "zip" zip-file
199 Default value: none. 199 Default value: none.
200 200
201source-filter::
202 Specifies a command which will be invoked to format plaintext blobs
203 in the tree view. The command will get the blob content on its STDIN
204 and the name of the blob as its only command line argument. The STDOUT
205 from the command will be included verbatim as the blob contents, i.e.
206 this can be used to implement e.g. syntax highlighting. Default value:
207 none.
208
201summary-branches:: 209summary-branches::
202 Specifies the number of branches to display in the repository "summary" 210 Specifies the number of branches to display in the repository "summary"
203 view. Default value: "10". 211 view. Default value: "10".
204 212
205summary-log:: 213summary-log::
206 Specifies the number of log entries to display in the repository 214 Specifies the number of log entries to display in the repository
207 "summary" view. Default value: "10". 215 "summary" view. Default value: "10".
208 216
209summary-tags:: 217summary-tags::
210 Specifies the number of tags to display in the repository "summary" 218 Specifies the number of tags to display in the repository "summary"
211 view. Default value: "10". 219 view. Default value: "10".
212 220
213virtual-root:: 221virtual-root::
214 Url which, if specified, will be used as root for all cgit links. It 222 Url which, if specified, will be used as root for all cgit links. It
215 will also cause cgit to generate 'virtual urls', i.e. urls like 223 will also cause cgit to generate 'virtual urls', i.e. urls like
216 '/cgit/tree/README' as opposed to '?r=cgit&p=tree&path=README'. Default 224 '/cgit/tree/README' as opposed to '?r=cgit&p=tree&path=README'. Default
217 value: none. 225 value: none.
218 NOTE: cgit has recently learned how to use PATH_INFO to achieve the 226 NOTE: cgit has recently learned how to use PATH_INFO to achieve the
219 same kind of virtual urls, so this option will probably be deprecated. 227 same kind of virtual urls, so this option will probably be deprecated.
220 228
221REPOSITORY SETTINGS 229REPOSITORY SETTINGS
222------------------- 230-------------------
223repo.clone-url:: 231repo.clone-url::
224 A list of space-separated urls which can be used to clone this repo. 232 A list of space-separated urls which can be used to clone this repo.
225 Default value: none. 233 Default value: none.
226 234
227repo.defbranch:: 235repo.defbranch::
228 The name of the default branch for this repository. If no such branch 236 The name of the default branch for this repository. If no such branch
229 exists in the repository, the first branch name (when sorted) is used 237 exists in the repository, the first branch name (when sorted) is used
230 as default instead. Default value: "master". 238 as default instead. Default value: "master".
231 239
232repo.desc:: 240repo.desc::
233 The value to show as repository description. Default value: none. 241 The value to show as repository description. Default value: none.
234 242
235repo.enable-log-filecount:: 243repo.enable-log-filecount::
236 A flag which can be used to disable the global setting 244 A flag which can be used to disable the global setting
237 `enable-log-filecount'. Default value: none. 245 `enable-log-filecount'. Default value: none.
238 246
239repo.enable-log-linecount:: 247repo.enable-log-linecount::
240 A flag which can be used to disable the global setting 248 A flag which can be used to disable the global setting
241 `enable-log-linecount'. Default value: none. 249 `enable-log-linecount'. Default value: none.
242 250
243repo.max-stats:: 251repo.max-stats::
244 Override the default maximum statistics period. Valid values are equal 252 Override the default maximum statistics period. Valid values are equal
245 to the values specified for the global "max-stats" setting. Default 253 to the values specified for the global "max-stats" setting. Default
246 value: none. 254 value: none.
247 255
248repo.name:: 256repo.name::
diff --git a/ui-tree.c b/ui-tree.c
index 553dbaa..816e121 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -1,144 +1,154 @@
1/* ui-tree.c: functions for tree output 1/* ui-tree.c: functions for tree output
2 * 2 *
3 * Copyright (C) 2006 Lars Hjemli 3 * Copyright (C) 2006 Lars Hjemli
4 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include <ctype.h> 9#include <ctype.h>
10#include "cgit.h" 10#include "cgit.h"
11#include "html.h" 11#include "html.h"
12#include "ui-shared.h" 12#include "ui-shared.h"
13 13
14char *curr_rev; 14char *curr_rev;
15char *match_path; 15char *match_path;
16int header = 0; 16int header = 0;
17 17
18static void print_text_buffer(char *buf, unsigned long size) 18static void print_text_buffer(const char *name, char *buf, unsigned long size)
19{ 19{
20 unsigned long lineno, idx; 20 unsigned long lineno, idx;
21 const char *numberfmt = 21 const char *numberfmt =
22 "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n"; 22 "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n";
23 23
24 html("<table summary='blob content' class='blob'>\n"); 24 html("<table summary='blob content' class='blob'>\n");
25 if (ctx.cfg.source_filter) {
26 html("<tr><td class='lines'><pre><code>");
27 ctx.cfg.source_filter->argv[1] = xstrdup(name);
28 cgit_open_filter(ctx.cfg.source_filter);
29 write(STDOUT_FILENO, buf, size);
30 cgit_close_filter(ctx.cfg.source_filter);
31 html("</code></pre></td></tr></table>\n");
32 return;
33 }
34
25 html("<tr><td class='linenumbers'><pre>"); 35 html("<tr><td class='linenumbers'><pre>");
26 idx = 0; 36 idx = 0;
27 lineno = 0; 37 lineno = 0;
28 38
29 if (size) { 39 if (size) {
30 htmlf(numberfmt, ++lineno); 40 htmlf(numberfmt, ++lineno);
31 while(idx < size - 1) { // skip absolute last newline 41 while(idx < size - 1) { // skip absolute last newline
32 if (buf[idx] == '\n') 42 if (buf[idx] == '\n')
33 htmlf(numberfmt, ++lineno); 43 htmlf(numberfmt, ++lineno);
34 idx++; 44 idx++;
35 } 45 }
36 } 46 }
37 html("</pre></td>\n"); 47 html("</pre></td>\n");
38 html("<td class='lines'><pre><code>"); 48 html("<td class='lines'><pre><code>");
39 html_txt(buf); 49 html_txt(buf);
40 html("</code></pre></td></tr></table>\n"); 50 html("</code></pre></td></tr></table>\n");
41} 51}
42 52
43#define ROWLEN 32 53#define ROWLEN 32
44 54
45static void print_binary_buffer(char *buf, unsigned long size) 55static void print_binary_buffer(char *buf, unsigned long size)
46{ 56{
47 unsigned long ofs, idx; 57 unsigned long ofs, idx;
48 static char ascii[ROWLEN + 1]; 58 static char ascii[ROWLEN + 1];
49 59
50 html("<table summary='blob content' class='bin-blob'>\n"); 60 html("<table summary='blob content' class='bin-blob'>\n");
51 html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>"); 61 html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>");
52 for (ofs = 0; ofs < size; ofs += ROWLEN, buf += ROWLEN) { 62 for (ofs = 0; ofs < size; ofs += ROWLEN, buf += ROWLEN) {
53 htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs); 63 htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs);
54 for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) 64 for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++)
55 htmlf("%*s%02x", 65 htmlf("%*s%02x",
56 idx == 16 ? 4 : 1, "", 66 idx == 16 ? 4 : 1, "",
57 buf[idx] & 0xff); 67 buf[idx] & 0xff);
58 html(" </td><td class='hex'>"); 68 html(" </td><td class='hex'>");
59 for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) 69 for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++)
60 ascii[idx] = isgraph(buf[idx]) ? buf[idx] : '.'; 70 ascii[idx] = isgraph(buf[idx]) ? buf[idx] : '.';
61 ascii[idx] = '\0'; 71 ascii[idx] = '\0';
62 html_txt(ascii); 72 html_txt(ascii);
63 html("</td></tr>\n"); 73 html("</td></tr>\n");
64 } 74 }
65 html("</table>\n"); 75 html("</table>\n");
66} 76}
67 77
68static void print_object(const unsigned char *sha1, char *path) 78static void print_object(const unsigned char *sha1, char *path, const char *basename)
69{ 79{
70 enum object_type type; 80 enum object_type type;
71 char *buf; 81 char *buf;
72 unsigned long size; 82 unsigned long size;
73 83
74 type = sha1_object_info(sha1, &size); 84 type = sha1_object_info(sha1, &size);
75 if (type == OBJ_BAD) { 85 if (type == OBJ_BAD) {
76 cgit_print_error(fmt("Bad object name: %s", 86 cgit_print_error(fmt("Bad object name: %s",
77 sha1_to_hex(sha1))); 87 sha1_to_hex(sha1)));
78 return; 88 return;
79 } 89 }
80 90
81 buf = read_sha1_file(sha1, &type, &size); 91 buf = read_sha1_file(sha1, &type, &size);
82 if (!buf) { 92 if (!buf) {
83 cgit_print_error(fmt("Error reading object %s", 93 cgit_print_error(fmt("Error reading object %s",
84 sha1_to_hex(sha1))); 94 sha1_to_hex(sha1)));
85 return; 95 return;
86 } 96 }
87 97
88 html(" ("); 98 html(" (");
89 cgit_plain_link("plain", NULL, NULL, ctx.qry.head, 99 cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
90 curr_rev, path); 100 curr_rev, path);
91 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1)); 101 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1));
92 102
93 if (buffer_is_binary(buf, size)) 103 if (buffer_is_binary(buf, size))
94 print_binary_buffer(buf, size); 104 print_binary_buffer(buf, size);
95 else 105 else
96 print_text_buffer(buf, size); 106 print_text_buffer(basename, buf, size);
97} 107}
98 108
99 109
100static int ls_item(const unsigned char *sha1, const char *base, int baselen, 110static int ls_item(const unsigned char *sha1, const char *base, int baselen,
101 const char *pathname, unsigned int mode, int stage, 111 const char *pathname, unsigned int mode, int stage,
102 void *cbdata) 112 void *cbdata)
103{ 113{
104 char *name; 114 char *name;
105 char *fullpath; 115 char *fullpath;
106 enum object_type type; 116 enum object_type type;
107 unsigned long size = 0; 117 unsigned long size = 0;
108 118
109 name = xstrdup(pathname); 119 name = xstrdup(pathname);
110 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", 120 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "",
111 ctx.qry.path ? "/" : "", name); 121 ctx.qry.path ? "/" : "", name);
112 122
113 if (!S_ISGITLINK(mode)) { 123 if (!S_ISGITLINK(mode)) {
114 type = sha1_object_info(sha1, &size); 124 type = sha1_object_info(sha1, &size);
115 if (type == OBJ_BAD) { 125 if (type == OBJ_BAD) {
116 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", 126 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>",
117 name, 127 name,
118 sha1_to_hex(sha1)); 128 sha1_to_hex(sha1));
119 return 0; 129 return 0;
120 } 130 }
121 } 131 }
122 132
123 html("<tr><td class='ls-mode'>"); 133 html("<tr><td class='ls-mode'>");
124 cgit_print_filemode(mode); 134 cgit_print_filemode(mode);
125 html("</td><td>"); 135 html("</td><td>");
126 if (S_ISGITLINK(mode)) { 136 if (S_ISGITLINK(mode)) {
127 htmlf("<a class='ls-mod' href='"); 137 htmlf("<a class='ls-mod' href='");
128 html_attr(fmt(ctx.repo->module_link, 138 html_attr(fmt(ctx.repo->module_link,
129 name, 139 name,
130 sha1_to_hex(sha1))); 140 sha1_to_hex(sha1)));
131 html("'>"); 141 html("'>");
132 html_txt(name); 142 html_txt(name);
133 html("</a>"); 143 html("</a>");
134 } else if (S_ISDIR(mode)) { 144 } else if (S_ISDIR(mode)) {
135 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, 145 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head,
136 curr_rev, fullpath); 146 curr_rev, fullpath);
137 } else { 147 } else {
138 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head, 148 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head,
139 curr_rev, fullpath); 149 curr_rev, fullpath);
140 } 150 }
141 htmlf("</td><td class='ls-size'>%li</td>", size); 151 htmlf("</td><td class='ls-size'>%li</td>", size);
142 152
143 html("<td>"); 153 html("<td>");
144 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, 154 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev,
@@ -168,95 +178,95 @@ static void ls_tail()
168 if (!header) 178 if (!header)
169 return; 179 return;
170 html("</table>\n"); 180 html("</table>\n");
171 header = 0; 181 header = 0;
172} 182}
173 183
174static void ls_tree(const unsigned char *sha1, char *path) 184static void ls_tree(const unsigned char *sha1, char *path)
175{ 185{
176 struct tree *tree; 186 struct tree *tree;
177 187
178 tree = parse_tree_indirect(sha1); 188 tree = parse_tree_indirect(sha1);
179 if (!tree) { 189 if (!tree) {
180 cgit_print_error(fmt("Not a tree object: %s", 190 cgit_print_error(fmt("Not a tree object: %s",
181 sha1_to_hex(sha1))); 191 sha1_to_hex(sha1)));
182 return; 192 return;
183 } 193 }
184 194
185 ls_head(); 195 ls_head();
186 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL); 196 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL);
187 ls_tail(); 197 ls_tail();
188} 198}
189 199
190 200
191static int walk_tree(const unsigned char *sha1, const char *base, int baselen, 201static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
192 const char *pathname, unsigned mode, int stage, 202 const char *pathname, unsigned mode, int stage,
193 void *cbdata) 203 void *cbdata)
194{ 204{
195 static int state; 205 static int state;
196 static char buffer[PATH_MAX]; 206 static char buffer[PATH_MAX];
197 char *url; 207 char *url;
198 208
199 if (state == 0) { 209 if (state == 0) {
200 memcpy(buffer, base, baselen); 210 memcpy(buffer, base, baselen);
201 strcpy(buffer+baselen, pathname); 211 strcpy(buffer+baselen, pathname);
202 url = cgit_pageurl(ctx.qry.repo, "tree", 212 url = cgit_pageurl(ctx.qry.repo, "tree",
203 fmt("h=%s&amp;path=%s", curr_rev, buffer)); 213 fmt("h=%s&amp;path=%s", curr_rev, buffer));
204 html("/"); 214 html("/");
205 cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head, 215 cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head,
206 curr_rev, buffer); 216 curr_rev, buffer);
207 217
208 if (strcmp(match_path, buffer)) 218 if (strcmp(match_path, buffer))
209 return READ_TREE_RECURSIVE; 219 return READ_TREE_RECURSIVE;
210 220
211 if (S_ISDIR(mode)) { 221 if (S_ISDIR(mode)) {
212 state = 1; 222 state = 1;
213 ls_head(); 223 ls_head();
214 return READ_TREE_RECURSIVE; 224 return READ_TREE_RECURSIVE;
215 } else { 225 } else {
216 print_object(sha1, buffer); 226 print_object(sha1, buffer, pathname);
217 return 0; 227 return 0;
218 } 228 }
219 } 229 }
220 ls_item(sha1, base, baselen, pathname, mode, stage, NULL); 230 ls_item(sha1, base, baselen, pathname, mode, stage, NULL);
221 return 0; 231 return 0;
222} 232}
223 233
224 234
225/* 235/*
226 * Show a tree or a blob 236 * Show a tree or a blob
227 * rev: the commit pointing at the root tree object 237 * rev: the commit pointing at the root tree object
228 * path: path to tree or blob 238 * path: path to tree or blob
229 */ 239 */
230void cgit_print_tree(const char *rev, char *path) 240void cgit_print_tree(const char *rev, char *path)
231{ 241{
232 unsigned char sha1[20]; 242 unsigned char sha1[20];
233 struct commit *commit; 243 struct commit *commit;
234 const char *paths[] = {path, NULL}; 244 const char *paths[] = {path, NULL};
235 245
236 if (!rev) 246 if (!rev)
237 rev = ctx.qry.head; 247 rev = ctx.qry.head;
238 248
239 curr_rev = xstrdup(rev); 249 curr_rev = xstrdup(rev);
240 if (get_sha1(rev, sha1)) { 250 if (get_sha1(rev, sha1)) {
241 cgit_print_error(fmt("Invalid revision name: %s", rev)); 251 cgit_print_error(fmt("Invalid revision name: %s", rev));
242 return; 252 return;
243 } 253 }
244 commit = lookup_commit_reference(sha1); 254 commit = lookup_commit_reference(sha1);
245 if (!commit || parse_commit(commit)) { 255 if (!commit || parse_commit(commit)) {
246 cgit_print_error(fmt("Invalid commit reference: %s", rev)); 256 cgit_print_error(fmt("Invalid commit reference: %s", rev));
247 return; 257 return;
248 } 258 }
249 259
250 html("path: <a href='"); 260 html("path: <a href='");
251 html_attr(cgit_pageurl(ctx.qry.repo, "tree", fmt("h=%s", rev))); 261 html_attr(cgit_pageurl(ctx.qry.repo, "tree", fmt("h=%s", rev)));
252 html("'>root</a>"); 262 html("'>root</a>");
253 263
254 if (path == NULL) { 264 if (path == NULL) {
255 ls_tree(commit->tree->object.sha1, NULL); 265 ls_tree(commit->tree->object.sha1, NULL);
256 return; 266 return;
257 } 267 }
258 268
259 match_path = path; 269 match_path = path;
260 read_tree_recursive(commit->tree, NULL, 0, 0, paths, walk_tree, NULL); 270 read_tree_recursive(commit->tree, NULL, 0, 0, paths, walk_tree, NULL);
261 ls_tail(); 271 ls_tail();
262} 272}