summaryrefslogtreecommitdiffabout
authorJason A. Donenfeld <Jason@zx2c4.com>2010-08-03 22:45:42 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2010-08-20 16:57:30 (UTC)
commit379e80e3a83481d3639c5d312eeddcce57c486b2 (patch) (unidiff)
tree474ac38e3812008532d4ebd0b095ac835b5478b5
parentaec9c245e7eaf444c7ae1851e3eda3b30748950f (diff)
downloadcgit-379e80e3a83481d3639c5d312eeddcce57c486b2.zip
cgit-379e80e3a83481d3639c5d312eeddcce57c486b2.tar.gz
cgit-379e80e3a83481d3639c5d312eeddcce57c486b2.tar.bz2
Support refspecs in about-filter.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c4
-rw-r--r--cgitrc.5.txt4
-rw-r--r--ui-blob.c35
-rw-r--r--ui-blob.h1
-rw-r--r--ui-summary.c26
5 files changed, 63 insertions, 7 deletions
diff --git a/cgit.c b/cgit.c
index eff5b7a..4f2c752 100644
--- a/cgit.c
+++ b/cgit.c
@@ -1,27 +1,28 @@
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 * Copyright (C) 2010 Jason A. Donenfeld <Jason@zx2c4.com>
4 * 5 *
5 * Licensed under GNU General Public License v2 6 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 7 * (see COPYING for full license text)
7 */ 8 */
8 9
9#include "cgit.h" 10#include "cgit.h"
10#include "cache.h" 11#include "cache.h"
11#include "cmd.h" 12#include "cmd.h"
12#include "configfile.h" 13#include "configfile.h"
13#include "html.h" 14#include "html.h"
14#include "ui-shared.h" 15#include "ui-shared.h"
15#include "ui-stats.h" 16#include "ui-stats.h"
16#include "scan-tree.h" 17#include "scan-tree.h"
17 18
18const char *cgit_version = CGIT_VERSION; 19const char *cgit_version = CGIT_VERSION;
19 20
20void add_mimetype(const char *name, const char *value) 21void add_mimetype(const char *name, const char *value)
21{ 22{
22 struct string_list_item *item; 23 struct string_list_item *item;
23 24
24 item = string_list_insert(xstrdup(name), &ctx.cfg.mimetypes); 25 item = string_list_insert(xstrdup(name), &ctx.cfg.mimetypes);
25 item->util = xstrdup(value); 26 item->util = xstrdup(value);
26} 27}
27 28
@@ -50,49 +51,50 @@ void repo_config(struct cgit_repo *repo, const char *name, const char *value)
50 repo->clone_url = xstrdup(value); 51 repo->clone_url = xstrdup(value);
51 else if (!strcmp(name, "desc")) 52 else if (!strcmp(name, "desc"))
52 repo->desc = xstrdup(value); 53 repo->desc = xstrdup(value);
53 else if (!strcmp(name, "owner")) 54 else if (!strcmp(name, "owner"))
54 repo->owner = xstrdup(value); 55 repo->owner = xstrdup(value);
55 else if (!strcmp(name, "defbranch")) 56 else if (!strcmp(name, "defbranch"))
56 repo->defbranch = xstrdup(value); 57 repo->defbranch = xstrdup(value);
57 else if (!strcmp(name, "snapshots")) 58 else if (!strcmp(name, "snapshots"))
58 repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); 59 repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value);
59 else if (!strcmp(name, "enable-log-filecount")) 60 else if (!strcmp(name, "enable-log-filecount"))
60 repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value); 61 repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value);
61 else if (!strcmp(name, "enable-log-linecount")) 62 else if (!strcmp(name, "enable-log-linecount"))
62 repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value); 63 repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value);
63 else if (!strcmp(name, "enable-remote-branches")) 64 else if (!strcmp(name, "enable-remote-branches"))
64 repo->enable_remote_branches = atoi(value); 65 repo->enable_remote_branches = atoi(value);
65 else if (!strcmp(name, "enable-subject-links")) 66 else if (!strcmp(name, "enable-subject-links"))
66 repo->enable_subject_links = atoi(value); 67 repo->enable_subject_links = atoi(value);
67 else if (!strcmp(name, "max-stats")) 68 else if (!strcmp(name, "max-stats"))
68 repo->max_stats = cgit_find_stats_period(value, NULL); 69 repo->max_stats = cgit_find_stats_period(value, NULL);
69 else if (!strcmp(name, "module-link")) 70 else if (!strcmp(name, "module-link"))
70 repo->module_link= xstrdup(value); 71 repo->module_link= xstrdup(value);
71 else if (!strcmp(name, "section")) 72 else if (!strcmp(name, "section"))
72 repo->section = xstrdup(value); 73 repo->section = xstrdup(value);
73 else if (!strcmp(name, "readme") && value != NULL) { 74 else if (!strcmp(name, "readme") && value != NULL) {
74 if (*value == '/') 75 char *colon;
76 if (*value == '/' || ((colon = strchr(value, ':')) != NULL && colon != value && *(colon + 1) != '\0'))
75 repo->readme = xstrdup(value); 77 repo->readme = xstrdup(value);
76 else 78 else
77 repo->readme = xstrdup(fmt("%s/%s", repo->path, value)); 79 repo->readme = xstrdup(fmt("%s/%s", repo->path, value));
78 } else if (ctx.cfg.enable_filter_overrides) { 80 } else if (ctx.cfg.enable_filter_overrides) {
79 if (!strcmp(name, "about-filter")) 81 if (!strcmp(name, "about-filter"))
80 repo->about_filter = new_filter(value, 0); 82 repo->about_filter = new_filter(value, 0);
81 else if (!strcmp(name, "commit-filter")) 83 else if (!strcmp(name, "commit-filter"))
82 repo->commit_filter = new_filter(value, 0); 84 repo->commit_filter = new_filter(value, 0);
83 else if (!strcmp(name, "source-filter")) 85 else if (!strcmp(name, "source-filter"))
84 repo->source_filter = new_filter(value, 1); 86 repo->source_filter = new_filter(value, 1);
85 } 87 }
86} 88}
87 89
88void config_cb(const char *name, const char *value) 90void config_cb(const char *name, const char *value)
89{ 91{
90 if (!strcmp(name, "section") || !strcmp(name, "repo.group")) 92 if (!strcmp(name, "section") || !strcmp(name, "repo.group"))
91 ctx.cfg.section = xstrdup(value); 93 ctx.cfg.section = xstrdup(value);
92 else if (!strcmp(name, "repo.url")) 94 else if (!strcmp(name, "repo.url"))
93 ctx.repo = cgit_add_repo(value); 95 ctx.repo = cgit_add_repo(value);
94 else if (ctx.repo && !strcmp(name, "repo.path")) 96 else if (ctx.repo && !strcmp(name, "repo.path"))
95 ctx.repo->path = trim_end(value, '/'); 97 ctx.repo->path = trim_end(value, '/');
96 else if (ctx.repo && !prefixcmp(name, "repo.")) 98 else if (ctx.repo && !prefixcmp(name, "repo."))
97 repo_config(ctx.repo, name + 5, value); 99 repo_config(ctx.repo, name + 5, value);
98 else if (!strcmp(name, "root-title")) 100 else if (!strcmp(name, "root-title"))
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 5d77973..c643fae 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -350,49 +350,51 @@ repo.enable-remote-branches::
350 in the summary and refs views. Default value: <enable-remote-branches>. 350 in the summary and refs views. Default value: <enable-remote-branches>.
351 351
352repo.enable-subject-links:: 352repo.enable-subject-links::
353 A flag which can be used to override the global setting 353 A flag which can be used to override the global setting
354 `enable-subject-links'. Default value: none. 354 `enable-subject-links'. Default value: none.
355 355
356repo.max-stats:: 356repo.max-stats::
357 Override the default maximum statistics period. Valid values are equal 357 Override the default maximum statistics period. Valid values are equal
358 to the values specified for the global "max-stats" setting. Default 358 to the values specified for the global "max-stats" setting. Default
359 value: none. 359 value: none.
360 360
361repo.name:: 361repo.name::
362 The value to show as repository name. Default value: <repo.url>. 362 The value to show as repository name. Default value: <repo.url>.
363 363
364repo.owner:: 364repo.owner::
365 A value used to identify the owner of the repository. Default value: 365 A value used to identify the owner of the repository. Default value:
366 none. 366 none.
367 367
368repo.path:: 368repo.path::
369 An absolute path to the repository directory. For non-bare repositories 369 An absolute path to the repository directory. For non-bare repositories
370 this is the .git-directory. Default value: none. 370 this is the .git-directory. Default value: none.
371 371
372repo.readme:: 372repo.readme::
373 A path (relative to <repo.path>) which specifies a file to include 373 A path (relative to <repo.path>) which specifies a file to include
374 verbatim as the "About" page for this repo. Default value: none. 374 verbatim as the "About" page for this repo. You may also specify a
375 git refspec by head or by hash by prepending the refspec followed by
376 a colon. For example, "master:docs/readme.mkd" Default value: none.
375 377
376repo.snapshots:: 378repo.snapshots::
377 A mask of allowed snapshot-formats for this repo, restricted by the 379 A mask of allowed snapshot-formats for this repo, restricted by the
378 "snapshots" global setting. Default value: <snapshots>. 380 "snapshots" global setting. Default value: <snapshots>.
379 381
380repo.section:: 382repo.section::
381 Override the current section name for this repository. Default value: 383 Override the current section name for this repository. Default value:
382 none. 384 none.
383 385
384repo.source-filter:: 386repo.source-filter::
385 Override the default source-filter. Default value: none. See also: 387 Override the default source-filter. Default value: none. See also:
386 "enable-filter-overrides". 388 "enable-filter-overrides".
387 389
388repo.url:: 390repo.url::
389 The relative url used to access the repository. This must be the first 391 The relative url used to access the repository. This must be the first
390 setting specified for each repo. Default value: none. 392 setting specified for each repo. Default value: none.
391 393
392 394
393REPOSITORY-SPECIFIC CGITRC FILE 395REPOSITORY-SPECIFIC CGITRC FILE
394------------------------------- 396-------------------------------
395When the option "scan-path" is used to auto-discover git repositories, cgit 397When the option "scan-path" is used to auto-discover git repositories, cgit
396will try to parse the file "cgitrc" within any found repository. Such a 398will try to parse the file "cgitrc" within any found repository. Such a
397repo-specific config file may contain any of the repo-specific options 399repo-specific config file may contain any of the repo-specific options
398described above, except "repo.url" and "repo.path". Additionally, the "filter" 400described above, except "repo.url" and "repo.path". Additionally, the "filter"
diff --git a/ui-blob.c b/ui-blob.c
index 89330ce..667a451 100644
--- a/ui-blob.c
+++ b/ui-blob.c
@@ -1,51 +1,84 @@
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 * Copyright (C) 2010 Jason A. Donenfeld <Jason@zx2c4.com>
4 * 5 *
5 * Licensed under GNU General Public License v2 6 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 7 * (see COPYING for full license text)
7 */ 8 */
8 9
9#include "cgit.h" 10#include "cgit.h"
10#include "html.h" 11#include "html.h"
11#include "ui-shared.h" 12#include "ui-shared.h"
12 13
13static char *match_path; 14static char *match_path;
14static unsigned char *matched_sha1; 15static unsigned char *matched_sha1;
16static int found_path;
15 17
16static int walk_tree(const unsigned char *sha1, const char *base,int baselen, 18static int walk_tree(const unsigned char *sha1, const char *base,int baselen,
17 const char *pathname, unsigned mode, int stage, void *cbdata) { 19 const char *pathname, unsigned mode, int stage, void *cbdata) {
18 if(strncmp(base,match_path,baselen) 20 if(strncmp(base,match_path,baselen)
19 || strcmp(match_path+baselen,pathname) ) 21 || strcmp(match_path+baselen,pathname) )
20 return READ_TREE_RECURSIVE; 22 return READ_TREE_RECURSIVE;
21 memmove(matched_sha1,sha1,20); 23 memmove(matched_sha1,sha1,20);
24 found_path = 1;
22 return 0; 25 return 0;
23} 26}
24 27
25void cgit_print_blob(const char *hex, char *path, const char *head) 28int cgit_print_file(char *path, const char *head)
26{ 29{
30 unsigned char sha1[20];
31 enum object_type type;
32 char *buf;
33 unsigned long size;
34 struct commit *commit;
35 const char *paths[] = {path, NULL};
36 if (get_sha1(head, sha1))
37 return -1;
38 type = sha1_object_info(sha1, &size);
39 if(type == OBJ_COMMIT && path) {
40 commit = lookup_commit_reference(sha1);
41 match_path = path;
42 matched_sha1 = sha1;
43 found_path = 0;
44 read_tree_recursive(commit->tree, "", 0, 0, paths, walk_tree, NULL);
45 if (!found_path)
46 return -1;
47 type = sha1_object_info(sha1, &size);
48 }
49 if (type == OBJ_BAD)
50 return -1;
51 buf = read_sha1_file(sha1, &type, &size);
52 if (!buf)
53 return -1;
54 buf[size] = '\0';
55 write(htmlfd, buf, size);
56 return 0;
57}
27 58
59void cgit_print_blob(const char *hex, char *path, const char *head)
60{
28 unsigned char sha1[20]; 61 unsigned char sha1[20];
29 enum object_type type; 62 enum object_type type;
30 char *buf; 63 char *buf;
31 unsigned long size; 64 unsigned long size;
32 struct commit *commit; 65 struct commit *commit;
33 const char *paths[] = {path, NULL}; 66 const char *paths[] = {path, NULL};
34 67
35 if (hex) { 68 if (hex) {
36 if (get_sha1_hex(hex, sha1)){ 69 if (get_sha1_hex(hex, sha1)){
37 cgit_print_error(fmt("Bad hex value: %s", hex)); 70 cgit_print_error(fmt("Bad hex value: %s", hex));
38 return; 71 return;
39 } 72 }
40 } else { 73 } else {
41 if (get_sha1(head,sha1)) { 74 if (get_sha1(head,sha1)) {
42 cgit_print_error(fmt("Bad ref: %s", head)); 75 cgit_print_error(fmt("Bad ref: %s", head));
43 return; 76 return;
44 } 77 }
45 } 78 }
46 79
47 type = sha1_object_info(sha1, &size); 80 type = sha1_object_info(sha1, &size);
48 81
49 if((!hex) && type == OBJ_COMMIT && path) { 82 if((!hex) && type == OBJ_COMMIT && path) {
50 commit = lookup_commit_reference(sha1); 83 commit = lookup_commit_reference(sha1);
51 match_path = path; 84 match_path = path;
diff --git a/ui-blob.h b/ui-blob.h
index dad275a..d7e7d45 100644
--- a/ui-blob.h
+++ b/ui-blob.h
@@ -1,6 +1,7 @@
1#ifndef UI_BLOB_H 1#ifndef UI_BLOB_H
2#define UI_BLOB_H 2#define UI_BLOB_H
3 3
4extern int cgit_print_file(char *path, const char *head);
4extern void cgit_print_blob(const char *hex, char *path, const char *head); 5extern void cgit_print_blob(const char *hex, char *path, const char *head);
5 6
6#endif /* UI_BLOB_H */ 7#endif /* UI_BLOB_H */
diff --git a/ui-summary.c b/ui-summary.c
index a2c018e..02f191e 100644
--- a/ui-summary.c
+++ b/ui-summary.c
@@ -1,36 +1,38 @@
1/* ui-summary.c: functions for generating repo summary page 1/* ui-summary.c: functions for generating repo summary page
2 * 2 *
3 * Copyright (C) 2006 Lars Hjemli 3 * Copyright (C) 2006 Lars Hjemli
4 * Copyright (C) 2010 Jason A. Donenfeld <Jason@zx2c4.com>
4 * 5 *
5 * Licensed under GNU General Public License v2 6 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 7 * (see COPYING for full license text)
7 */ 8 */
8 9
9#include "cgit.h" 10#include "cgit.h"
10#include "html.h" 11#include "html.h"
11#include "ui-log.h" 12#include "ui-log.h"
12#include "ui-refs.h" 13#include "ui-refs.h"
14#include "ui-blob.h"
13 15
14int urls = 0; 16int urls = 0;
15 17
16static void print_url(char *base, char *suffix) 18static void print_url(char *base, char *suffix)
17{ 19{
18 if (!base || !*base) 20 if (!base || !*base)
19 return; 21 return;
20 if (urls++ == 0) { 22 if (urls++ == 0) {
21 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>"); 23 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>");
22 html("<tr><th class='left' colspan='4'>Clone</th></tr>\n"); 24 html("<tr><th class='left' colspan='4'>Clone</th></tr>\n");
23 } 25 }
24 if (suffix && *suffix) 26 if (suffix && *suffix)
25 base = fmt("%s/%s", base, suffix); 27 base = fmt("%s/%s", base, suffix);
26 html("<tr><td colspan='4'><a href='"); 28 html("<tr><td colspan='4'><a href='");
27 html_url_path(base); 29 html_url_path(base);
28 html("'>"); 30 html("'>");
29 html_txt(base); 31 html_txt(base);
30 html("</a></td></tr>\n"); 32 html("</a></td></tr>\n");
31} 33}
32 34
33static void print_urls(char *txt, char *suffix) 35static void print_urls(char *txt, char *suffix)
34{ 36{
35 char *h = txt, *t, c; 37 char *h = txt, *t, c;
36 38
@@ -47,46 +49,62 @@ static void print_urls(char *txt, char *suffix)
47 h = t; 49 h = t;
48 } 50 }
49} 51}
50 52
51void cgit_print_summary() 53void cgit_print_summary()
52{ 54{
53 html("<table summary='repository info' class='list nowrap'>"); 55 html("<table summary='repository info' class='list nowrap'>");
54 cgit_print_branches(ctx.cfg.summary_branches); 56 cgit_print_branches(ctx.cfg.summary_branches);
55 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>"); 57 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>");
56 cgit_print_tags(ctx.cfg.summary_tags); 58 cgit_print_tags(ctx.cfg.summary_tags);
57 if (ctx.cfg.summary_log > 0) { 59 if (ctx.cfg.summary_log > 0) {
58 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>"); 60 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>");
59 cgit_print_log(ctx.qry.head, 0, ctx.cfg.summary_log, NULL, 61 cgit_print_log(ctx.qry.head, 0, ctx.cfg.summary_log, NULL,
60 NULL, NULL, 0); 62 NULL, NULL, 0);
61 } 63 }
62 if (ctx.repo->clone_url) 64 if (ctx.repo->clone_url)
63 print_urls(ctx.repo->clone_url, NULL); 65 print_urls(ctx.repo->clone_url, NULL);
64 else if (ctx.cfg.clone_prefix) 66 else if (ctx.cfg.clone_prefix)
65 print_urls(ctx.cfg.clone_prefix, ctx.repo->url); 67 print_urls(ctx.cfg.clone_prefix, ctx.repo->url);
66 html("</table>"); 68 html("</table>");
67} 69}
68 70
69void cgit_print_repo_readme(char *path) 71void cgit_print_repo_readme(char *path)
70{ 72{
71 char *slash, *tmp; 73 char *slash, *tmp, *colon, *ref = 0;
72 74
73 if (!ctx.repo->readme) 75 if (!ctx.repo->readme)
74 return; 76 return;
75 77
76 if (path) { 78 if (path) {
77 slash = strrchr(ctx.repo->readme, '/'); 79 slash = strrchr(ctx.repo->readme, '/');
78 if (!slash) 80 if (!slash) {
79 return; 81 slash = strchr(ctx.repo->readme, ':');
82 if (!slash)
83 return;
84 }
80 tmp = xmalloc(slash - ctx.repo->readme + 1 + strlen(path) + 1); 85 tmp = xmalloc(slash - ctx.repo->readme + 1 + strlen(path) + 1);
81 strncpy(tmp, ctx.repo->readme, slash - ctx.repo->readme + 1); 86 strncpy(tmp, ctx.repo->readme, slash - ctx.repo->readme + 1);
82 strcpy(tmp + (slash - ctx.repo->readme + 1), path); 87 strcpy(tmp + (slash - ctx.repo->readme + 1), path);
83 } else 88 } else
84 tmp = ctx.repo->readme; 89 tmp = ctx.repo->readme;
90 colon = strchr(tmp, ':');
91 if (colon && strlen(colon) > 1) {
92 *colon = '\0';
93 ref = tmp;
94 tmp = colon + 1;
95 while ((*tmp == '/' || *tmp == ':') && *tmp != '\0')
96 ++tmp;
97 if (!(*tmp))
98 return;
99 }
85 html("<div id='summary'>"); 100 html("<div id='summary'>");
86 if (ctx.repo->about_filter) 101 if (ctx.repo->about_filter)
87 cgit_open_filter(ctx.repo->about_filter); 102 cgit_open_filter(ctx.repo->about_filter);
88 html_include(tmp); 103 if (ref)
104 cgit_print_file(tmp, ref);
105 else
106 html_include(tmp);
89 if (ctx.repo->about_filter) 107 if (ctx.repo->about_filter)
90 cgit_close_filter(ctx.repo->about_filter); 108 cgit_close_filter(ctx.repo->about_filter);
91 html("</div>"); 109 html("</div>");
92} 110}