-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | cgit.h | 1 | ||||
-rw-r--r-- | cmd.c | 7 | ||||
-rw-r--r-- | ui-atom.c | 129 | ||||
-rw-r--r-- | ui-atom.h | 6 | ||||
-rw-r--r-- | ui-shared.c | 23 | ||||
-rw-r--r-- | ui-shared.h | 1 |
7 files changed, 168 insertions, 0 deletions
@@ -26,64 +26,65 @@ NO_SUBDIR = : | |||
26 | endif | 26 | endif |
27 | 27 | ||
28 | ifndef V | 28 | ifndef V |
29 | QUIET_CC = @echo ' ' CC $@; | 29 | QUIET_CC = @echo ' ' CC $@; |
30 | QUIET_MM = @echo ' ' MM $@; | 30 | QUIET_MM = @echo ' ' MM $@; |
31 | QUIET_SUBDIR0 = +@subdir= | 31 | QUIET_SUBDIR0 = +@subdir= |
32 | QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ | 32 | QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ |
33 | $(MAKE) $(PRINT_DIR) -C $$subdir | 33 | $(MAKE) $(PRINT_DIR) -C $$subdir |
34 | endif | 34 | endif |
35 | 35 | ||
36 | # | 36 | # |
37 | # Define a pattern rule for automatic dependency building | 37 | # Define a pattern rule for automatic dependency building |
38 | # | 38 | # |
39 | %.d: %.c | 39 | %.d: %.c |
40 | $(QUIET_MM)$(CC) $(CFLAGS) -MM $< | sed -e 's/\($*\)\.o:/\1.o $@:/g' >$@ | 40 | $(QUIET_MM)$(CC) $(CFLAGS) -MM $< | sed -e 's/\($*\)\.o:/\1.o $@:/g' >$@ |
41 | 41 | ||
42 | # | 42 | # |
43 | # Define a pattern rule for silent object building | 43 | # Define a pattern rule for silent object building |
44 | # | 44 | # |
45 | %.o: %.c | 45 | %.o: %.c |
46 | $(QUIET_CC)$(CC) -o $*.o -c $(CFLAGS) $< | 46 | $(QUIET_CC)$(CC) -o $*.o -c $(CFLAGS) $< |
47 | 47 | ||
48 | 48 | ||
49 | EXTLIBS = git/libgit.a git/xdiff/lib.a -lz -lcrypto | 49 | EXTLIBS = git/libgit.a git/xdiff/lib.a -lz -lcrypto |
50 | OBJECTS = | 50 | OBJECTS = |
51 | OBJECTS += cache.o | 51 | OBJECTS += cache.o |
52 | OBJECTS += cgit.o | 52 | OBJECTS += cgit.o |
53 | OBJECTS += cmd.o | 53 | OBJECTS += cmd.o |
54 | OBJECTS += configfile.o | 54 | OBJECTS += configfile.o |
55 | OBJECTS += html.o | 55 | OBJECTS += html.o |
56 | OBJECTS += parsing.o | 56 | OBJECTS += parsing.o |
57 | OBJECTS += shared.o | 57 | OBJECTS += shared.o |
58 | OBJECTS += ui-atom.o | ||
58 | OBJECTS += ui-blob.o | 59 | OBJECTS += ui-blob.o |
59 | OBJECTS += ui-commit.o | 60 | OBJECTS += ui-commit.o |
60 | OBJECTS += ui-diff.o | 61 | OBJECTS += ui-diff.o |
61 | OBJECTS += ui-log.o | 62 | OBJECTS += ui-log.o |
62 | OBJECTS += ui-patch.o | 63 | OBJECTS += ui-patch.o |
63 | OBJECTS += ui-refs.o | 64 | OBJECTS += ui-refs.o |
64 | OBJECTS += ui-repolist.o | 65 | OBJECTS += ui-repolist.o |
65 | OBJECTS += ui-shared.o | 66 | OBJECTS += ui-shared.o |
66 | OBJECTS += ui-snapshot.o | 67 | OBJECTS += ui-snapshot.o |
67 | OBJECTS += ui-summary.o | 68 | OBJECTS += ui-summary.o |
68 | OBJECTS += ui-tag.o | 69 | OBJECTS += ui-tag.o |
69 | OBJECTS += ui-tree.o | 70 | OBJECTS += ui-tree.o |
70 | 71 | ||
71 | ifdef NEEDS_LIBICONV | 72 | ifdef NEEDS_LIBICONV |
72 | EXTLIBS += -liconv | 73 | EXTLIBS += -liconv |
73 | endif | 74 | endif |
74 | 75 | ||
75 | 76 | ||
76 | .PHONY: all git test install uninstall clean force-version get-git | 77 | .PHONY: all git test install uninstall clean force-version get-git |
77 | 78 | ||
78 | all: cgit | 79 | all: cgit |
79 | 80 | ||
80 | VERSION: force-version | 81 | VERSION: force-version |
81 | @./gen-version.sh "$(CGIT_VERSION)" | 82 | @./gen-version.sh "$(CGIT_VERSION)" |
82 | -include VERSION | 83 | -include VERSION |
83 | 84 | ||
84 | 85 | ||
85 | CFLAGS += -g -Wall -Igit | 86 | CFLAGS += -g -Wall -Igit |
86 | CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)' | 87 | CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)' |
87 | CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"' | 88 | CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"' |
88 | CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"' | 89 | CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"' |
89 | CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"' | 90 | CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"' |
@@ -1,58 +1,59 @@ | |||
1 | #ifndef CGIT_H | 1 | #ifndef CGIT_H |
2 | #define CGIT_H | 2 | #define CGIT_H |
3 | 3 | ||
4 | 4 | ||
5 | #include <git-compat-util.h> | 5 | #include <git-compat-util.h> |
6 | #include <cache.h> | 6 | #include <cache.h> |
7 | #include <grep.h> | 7 | #include <grep.h> |
8 | #include <object.h> | 8 | #include <object.h> |
9 | #include <tree.h> | 9 | #include <tree.h> |
10 | #include <commit.h> | 10 | #include <commit.h> |
11 | #include <tag.h> | 11 | #include <tag.h> |
12 | #include <diff.h> | 12 | #include <diff.h> |
13 | #include <diffcore.h> | 13 | #include <diffcore.h> |
14 | #include <refs.h> | 14 | #include <refs.h> |
15 | #include <revision.h> | 15 | #include <revision.h> |
16 | #include <log-tree.h> | 16 | #include <log-tree.h> |
17 | #include <archive.h> | 17 | #include <archive.h> |
18 | #include <xdiff/xdiff.h> | 18 | #include <xdiff/xdiff.h> |
19 | #include <utf8.h> | 19 | #include <utf8.h> |
20 | 20 | ||
21 | 21 | ||
22 | /* | 22 | /* |
23 | * Dateformats used on misc. pages | 23 | * Dateformats used on misc. pages |
24 | */ | 24 | */ |
25 | #define FMT_LONGDATE "%Y-%m-%d %H:%M:%S (%Z)" | 25 | #define FMT_LONGDATE "%Y-%m-%d %H:%M:%S (%Z)" |
26 | #define FMT_SHORTDATE "%Y-%m-%d" | 26 | #define FMT_SHORTDATE "%Y-%m-%d" |
27 | #define FMT_ATOMDATE "%Y-%m-%dT%H:%M:%SZ" | ||
27 | 28 | ||
28 | 29 | ||
29 | /* | 30 | /* |
30 | * Limits used for relative dates | 31 | * Limits used for relative dates |
31 | */ | 32 | */ |
32 | #define TM_MIN 60 | 33 | #define TM_MIN 60 |
33 | #define TM_HOUR (TM_MIN * 60) | 34 | #define TM_HOUR (TM_MIN * 60) |
34 | #define TM_DAY (TM_HOUR * 24) | 35 | #define TM_DAY (TM_HOUR * 24) |
35 | #define TM_WEEK (TM_DAY * 7) | 36 | #define TM_WEEK (TM_DAY * 7) |
36 | #define TM_YEAR (TM_DAY * 365) | 37 | #define TM_YEAR (TM_DAY * 365) |
37 | #define TM_MONTH (TM_YEAR / 12.0) | 38 | #define TM_MONTH (TM_YEAR / 12.0) |
38 | 39 | ||
39 | 40 | ||
40 | /* | 41 | /* |
41 | * Default encoding | 42 | * Default encoding |
42 | */ | 43 | */ |
43 | #define PAGE_ENCODING "UTF-8" | 44 | #define PAGE_ENCODING "UTF-8" |
44 | 45 | ||
45 | typedef void (*configfn)(const char *name, const char *value); | 46 | typedef void (*configfn)(const char *name, const char *value); |
46 | typedef void (*filepair_fn)(struct diff_filepair *pair); | 47 | typedef void (*filepair_fn)(struct diff_filepair *pair); |
47 | typedef void (*linediff_fn)(char *line, int len); | 48 | typedef void (*linediff_fn)(char *line, int len); |
48 | 49 | ||
49 | struct cgit_repo { | 50 | struct cgit_repo { |
50 | char *url; | 51 | char *url; |
51 | char *name; | 52 | char *name; |
52 | char *path; | 53 | char *path; |
53 | char *desc; | 54 | char *desc; |
54 | char *owner; | 55 | char *owner; |
55 | char *defbranch; | 56 | char *defbranch; |
56 | char *group; | 57 | char *group; |
57 | char *module_link; | 58 | char *module_link; |
58 | char *readme; | 59 | char *readme; |
@@ -1,56 +1,62 @@ | |||
1 | /* cmd.c: the cgit command dispatcher | 1 | /* cmd.c: the cgit command dispatcher |
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 "cmd.h" | 10 | #include "cmd.h" |
11 | #include "cache.h" | 11 | #include "cache.h" |
12 | #include "ui-shared.h" | 12 | #include "ui-shared.h" |
13 | #include "ui-atom.h" | ||
13 | #include "ui-blob.h" | 14 | #include "ui-blob.h" |
14 | #include "ui-commit.h" | 15 | #include "ui-commit.h" |
15 | #include "ui-diff.h" | 16 | #include "ui-diff.h" |
16 | #include "ui-log.h" | 17 | #include "ui-log.h" |
17 | #include "ui-patch.h" | 18 | #include "ui-patch.h" |
18 | #include "ui-refs.h" | 19 | #include "ui-refs.h" |
19 | #include "ui-repolist.h" | 20 | #include "ui-repolist.h" |
20 | #include "ui-snapshot.h" | 21 | #include "ui-snapshot.h" |
21 | #include "ui-summary.h" | 22 | #include "ui-summary.h" |
22 | #include "ui-tag.h" | 23 | #include "ui-tag.h" |
23 | #include "ui-tree.h" | 24 | #include "ui-tree.h" |
24 | 25 | ||
26 | static void atom_fn(struct cgit_context *ctx) | ||
27 | { | ||
28 | cgit_print_atom(ctx->qry.head, ctx->qry.path, 10); | ||
29 | } | ||
30 | |||
25 | static void about_fn(struct cgit_context *ctx) | 31 | static void about_fn(struct cgit_context *ctx) |
26 | { | 32 | { |
27 | if (ctx->repo) | 33 | if (ctx->repo) |
28 | cgit_print_repo_readme(); | 34 | cgit_print_repo_readme(); |
29 | else | 35 | else |
30 | cgit_print_site_readme(); | 36 | cgit_print_site_readme(); |
31 | } | 37 | } |
32 | 38 | ||
33 | static void blob_fn(struct cgit_context *ctx) | 39 | static void blob_fn(struct cgit_context *ctx) |
34 | { | 40 | { |
35 | cgit_print_blob(ctx->qry.sha1, ctx->qry.path, ctx->qry.head); | 41 | cgit_print_blob(ctx->qry.sha1, ctx->qry.path, ctx->qry.head); |
36 | } | 42 | } |
37 | 43 | ||
38 | static void commit_fn(struct cgit_context *ctx) | 44 | static void commit_fn(struct cgit_context *ctx) |
39 | { | 45 | { |
40 | cgit_print_commit(ctx->qry.sha1); | 46 | cgit_print_commit(ctx->qry.sha1); |
41 | } | 47 | } |
42 | 48 | ||
43 | static void diff_fn(struct cgit_context *ctx) | 49 | static void diff_fn(struct cgit_context *ctx) |
44 | { | 50 | { |
45 | cgit_print_diff(ctx->qry.sha1, ctx->qry.sha2, ctx->qry.path); | 51 | cgit_print_diff(ctx->qry.sha1, ctx->qry.sha2, ctx->qry.path); |
46 | } | 52 | } |
47 | 53 | ||
48 | static void log_fn(struct cgit_context *ctx) | 54 | static void log_fn(struct cgit_context *ctx) |
49 | { | 55 | { |
50 | cgit_print_log(ctx->qry.sha1, ctx->qry.ofs, ctx->cfg.max_commit_count, | 56 | cgit_print_log(ctx->qry.sha1, ctx->qry.ofs, ctx->cfg.max_commit_count, |
51 | ctx->qry.grep, ctx->qry.search, ctx->qry.path, 1); | 57 | ctx->qry.grep, ctx->qry.search, ctx->qry.path, 1); |
52 | } | 58 | } |
53 | 59 | ||
54 | static void ls_cache_fn(struct cgit_context *ctx) | 60 | static void ls_cache_fn(struct cgit_context *ctx) |
55 | { | 61 | { |
56 | ctx->page.mimetype = "text/plain"; | 62 | ctx->page.mimetype = "text/plain"; |
@@ -73,60 +79,61 @@ static void refs_fn(struct cgit_context *ctx) | |||
73 | { | 79 | { |
74 | cgit_print_refs(); | 80 | cgit_print_refs(); |
75 | } | 81 | } |
76 | 82 | ||
77 | static void snapshot_fn(struct cgit_context *ctx) | 83 | static void snapshot_fn(struct cgit_context *ctx) |
78 | { | 84 | { |
79 | cgit_print_snapshot(ctx->qry.head, ctx->qry.sha1, | 85 | cgit_print_snapshot(ctx->qry.head, ctx->qry.sha1, |
80 | cgit_repobasename(ctx->repo->url), ctx->qry.path, | 86 | cgit_repobasename(ctx->repo->url), ctx->qry.path, |
81 | ctx->repo->snapshots); | 87 | ctx->repo->snapshots); |
82 | } | 88 | } |
83 | 89 | ||
84 | static void summary_fn(struct cgit_context *ctx) | 90 | static void summary_fn(struct cgit_context *ctx) |
85 | { | 91 | { |
86 | cgit_print_summary(); | 92 | cgit_print_summary(); |
87 | } | 93 | } |
88 | 94 | ||
89 | static void tag_fn(struct cgit_context *ctx) | 95 | static void tag_fn(struct cgit_context *ctx) |
90 | { | 96 | { |
91 | cgit_print_tag(ctx->qry.sha1); | 97 | cgit_print_tag(ctx->qry.sha1); |
92 | } | 98 | } |
93 | 99 | ||
94 | static void tree_fn(struct cgit_context *ctx) | 100 | static void tree_fn(struct cgit_context *ctx) |
95 | { | 101 | { |
96 | cgit_print_tree(ctx->qry.sha1, ctx->qry.path); | 102 | cgit_print_tree(ctx->qry.sha1, ctx->qry.path); |
97 | } | 103 | } |
98 | 104 | ||
99 | #define def_cmd(name, want_repo, want_layout) \ | 105 | #define def_cmd(name, want_repo, want_layout) \ |
100 | {#name, name##_fn, want_repo, want_layout} | 106 | {#name, name##_fn, want_repo, want_layout} |
101 | 107 | ||
102 | struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx) | 108 | struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx) |
103 | { | 109 | { |
104 | static struct cgit_cmd cmds[] = { | 110 | static struct cgit_cmd cmds[] = { |
111 | def_cmd(atom, 1, 0), | ||
105 | def_cmd(about, 0, 1), | 112 | def_cmd(about, 0, 1), |
106 | def_cmd(blob, 1, 0), | 113 | def_cmd(blob, 1, 0), |
107 | def_cmd(commit, 1, 1), | 114 | def_cmd(commit, 1, 1), |
108 | def_cmd(diff, 1, 1), | 115 | def_cmd(diff, 1, 1), |
109 | def_cmd(log, 1, 1), | 116 | def_cmd(log, 1, 1), |
110 | def_cmd(ls_cache, 0, 0), | 117 | def_cmd(ls_cache, 0, 0), |
111 | def_cmd(patch, 1, 0), | 118 | def_cmd(patch, 1, 0), |
112 | def_cmd(refs, 1, 1), | 119 | def_cmd(refs, 1, 1), |
113 | def_cmd(repolist, 0, 0), | 120 | def_cmd(repolist, 0, 0), |
114 | def_cmd(snapshot, 1, 0), | 121 | def_cmd(snapshot, 1, 0), |
115 | def_cmd(summary, 1, 1), | 122 | def_cmd(summary, 1, 1), |
116 | def_cmd(tag, 1, 1), | 123 | def_cmd(tag, 1, 1), |
117 | def_cmd(tree, 1, 1), | 124 | def_cmd(tree, 1, 1), |
118 | }; | 125 | }; |
119 | int i; | 126 | int i; |
120 | 127 | ||
121 | if (ctx->qry.page == NULL) { | 128 | if (ctx->qry.page == NULL) { |
122 | if (ctx->repo) | 129 | if (ctx->repo) |
123 | ctx->qry.page = "summary"; | 130 | ctx->qry.page = "summary"; |
124 | else | 131 | else |
125 | ctx->qry.page = "repolist"; | 132 | ctx->qry.page = "repolist"; |
126 | } | 133 | } |
127 | 134 | ||
128 | for(i = 0; i < sizeof(cmds)/sizeof(*cmds); i++) | 135 | for(i = 0; i < sizeof(cmds)/sizeof(*cmds); i++) |
129 | if (!strcmp(ctx->qry.page, cmds[i].name)) | 136 | if (!strcmp(ctx->qry.page, cmds[i].name)) |
130 | return &cmds[i]; | 137 | return &cmds[i]; |
131 | return NULL; | 138 | return NULL; |
132 | } | 139 | } |
diff --git a/ui-atom.c b/ui-atom.c new file mode 100644 index 0000000..a6ea3ee --- a/dev/null +++ b/ui-atom.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* ui-atom.c: functions for atom feeds | ||
2 | * | ||
3 | * Copyright (C) 2008 Lars Hjemli | ||
4 | * | ||
5 | * Licensed under GNU General Public License v2 | ||
6 | * (see COPYING for full license text) | ||
7 | */ | ||
8 | |||
9 | #include "cgit.h" | ||
10 | #include "html.h" | ||
11 | #include "ui-shared.h" | ||
12 | |||
13 | void add_entry(struct commit *commit, char *host) | ||
14 | { | ||
15 | char delim = '&'; | ||
16 | char *hex; | ||
17 | char *mail, *t, *t2; | ||
18 | struct commitinfo *info; | ||
19 | |||
20 | info = cgit_parse_commit(commit); | ||
21 | hex = sha1_to_hex(commit->object.sha1); | ||
22 | html("<entry>\n"); | ||
23 | html("<title>"); | ||
24 | html_txt(info->subject); | ||
25 | html("</title>\n"); | ||
26 | html("<updated>"); | ||
27 | cgit_print_date(info->author_date, FMT_ATOMDATE, ctx.cfg.local_time); | ||
28 | html("</updated>\n"); | ||
29 | html("<author>\n"); | ||
30 | if (info->author) { | ||
31 | html("<name>"); | ||
32 | html_txt(info->author); | ||
33 | html("</name>\n"); | ||
34 | } | ||
35 | if (info->author_email) { | ||
36 | mail = xstrdup(info->author_email); | ||
37 | t = strchr(mail, '<'); | ||
38 | if (t) | ||
39 | t++; | ||
40 | else | ||
41 | t = mail; | ||
42 | t2 = strchr(t, '>'); | ||
43 | if (t2) | ||
44 | *t2 = '\0'; | ||
45 | html("<email>"); | ||
46 | html_txt(t); | ||
47 | html("</email>\n"); | ||
48 | free(mail); | ||
49 | } | ||
50 | html("</author>\n"); | ||
51 | html("<published>"); | ||
52 | cgit_print_date(info->author_date, FMT_ATOMDATE, ctx.cfg.local_time); | ||
53 | html("</published>\n"); | ||
54 | if (host) { | ||
55 | html("<link rel='alternate' type='text/html' href='http://"); | ||
56 | html_attr(host); | ||
57 | html_attr(cgit_pageurl(ctx.repo->url, "commit", NULL)); | ||
58 | if (ctx.cfg.virtual_root) | ||
59 | delim = '?'; | ||
60 | htmlf("%cid=%s", delim, hex); | ||
61 | html("'/>\n"); | ||
62 | } | ||
63 | htmlf("<id>%s</id>\n", hex); | ||
64 | html("<content type='text'>\n"); | ||
65 | html_txt(info->msg); | ||
66 | html("</content>\n"); | ||
67 | html("<content type='xhtml'>\n"); | ||
68 | html("<div xmlns='http://www.w3.org/1999/xhtml'>\n"); | ||
69 | html("<pre>\n"); | ||
70 | html_txt(info->msg); | ||
71 | html("</pre>\n"); | ||
72 | html("</div>\n"); | ||
73 | html("</content>\n"); | ||
74 | html("</entry>\n"); | ||
75 | cgit_free_commitinfo(info); | ||
76 | } | ||
77 | |||
78 | |||
79 | void cgit_print_atom(char *tip, char *path, int max_count) | ||
80 | { | ||
81 | char *host; | ||
82 | const char *argv[] = {NULL, tip, NULL, NULL, NULL}; | ||
83 | struct commit *commit; | ||
84 | struct rev_info rev; | ||
85 | int argc = 2; | ||
86 | |||
87 | if (!tip) | ||
88 | argv[1] = ctx.qry.head; | ||
89 | |||
90 | if (path) { | ||
91 | argv[argc++] = "--"; | ||
92 | argv[argc++] = path; | ||
93 | } | ||
94 | |||
95 | init_revisions(&rev, NULL); | ||
96 | rev.abbrev = DEFAULT_ABBREV; | ||
97 | rev.commit_format = CMIT_FMT_DEFAULT; | ||
98 | rev.verbose_header = 1; | ||
99 | rev.show_root_diff = 0; | ||
100 | rev.max_count = max_count; | ||
101 | setup_revisions(argc, argv, &rev, NULL); | ||
102 | prepare_revision_walk(&rev); | ||
103 | |||
104 | host = cgit_hosturl(); | ||
105 | ctx.page.mimetype = "text/xml"; | ||
106 | ctx.page.charset = "utf-8"; | ||
107 | cgit_print_http_headers(&ctx); | ||
108 | html("<feed xmlns='http://www.w3.org/2005/Atom'>\n"); | ||
109 | html("<title>"); | ||
110 | html_txt(ctx.repo->name); | ||
111 | html("</title>\n"); | ||
112 | html("<subtitle>"); | ||
113 | html_txt(ctx.repo->desc); | ||
114 | html("</subtitle>\n"); | ||
115 | if (host) { | ||
116 | html("<link rel='alternate' type='text/html' href='http://"); | ||
117 | html_attr(host); | ||
118 | html_attr(cgit_repourl(ctx.repo->url)); | ||
119 | html("'/>\n"); | ||
120 | } | ||
121 | while ((commit = get_revision(&rev)) != NULL) { | ||
122 | add_entry(commit, host); | ||
123 | free(commit->buffer); | ||
124 | commit->buffer = NULL; | ||
125 | free_commit_list(commit->parents); | ||
126 | commit->parents = NULL; | ||
127 | } | ||
128 | html("</feed>\n"); | ||
129 | } | ||
diff --git a/ui-atom.h b/ui-atom.h new file mode 100644 index 0000000..749ffd3 --- a/dev/null +++ b/ui-atom.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef UI_ATOM_H | ||
2 | #define UI_ATOM_H | ||
3 | |||
4 | extern void cgit_print_atom(char *tip, char *path, int max_count); | ||
5 | |||
6 | #endif | ||
diff --git a/ui-shared.c b/ui-shared.c index 197ee37..37c60b2 100644 --- a/ui-shared.c +++ b/ui-shared.c | |||
@@ -5,64 +5,79 @@ | |||
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 "html.h" | 11 | #include "html.h" |
12 | 12 | ||
13 | const char cgit_doctype[] = | 13 | const char cgit_doctype[] = |
14 | "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" | 14 | "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" |
15 | " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"; | 15 | " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"; |
16 | 16 | ||
17 | static char *http_date(time_t t) | 17 | static char *http_date(time_t t) |
18 | { | 18 | { |
19 | static char day[][4] = | 19 | static char day[][4] = |
20 | {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; | 20 | {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; |
21 | static char month[][4] = | 21 | static char month[][4] = |
22 | {"Jan", "Feb", "Mar", "Apr", "May", "Jun", | 22 | {"Jan", "Feb", "Mar", "Apr", "May", "Jun", |
23 | "Jul", "Aug", "Sep", "Oct", "Now", "Dec"}; | 23 | "Jul", "Aug", "Sep", "Oct", "Now", "Dec"}; |
24 | struct tm *tm = gmtime(&t); | 24 | struct tm *tm = gmtime(&t); |
25 | return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday], | 25 | return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday], |
26 | tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year, | 26 | tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year, |
27 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 27 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
28 | } | 28 | } |
29 | 29 | ||
30 | void cgit_print_error(char *msg) | 30 | void cgit_print_error(char *msg) |
31 | { | 31 | { |
32 | html("<div class='error'>"); | 32 | html("<div class='error'>"); |
33 | html_txt(msg); | 33 | html_txt(msg); |
34 | html("</div>\n"); | 34 | html("</div>\n"); |
35 | } | 35 | } |
36 | 36 | ||
37 | char *cgit_hosturl() | ||
38 | { | ||
39 | char *host, *port; | ||
40 | |||
41 | host = getenv("SERVER_NAME"); | ||
42 | if (!host) | ||
43 | return NULL; | ||
44 | port = getenv("SERVER_PORT"); | ||
45 | if (port && atoi(port) != 80) | ||
46 | host = xstrdup(fmt("%s:%d", host, atoi(port))); | ||
47 | else | ||
48 | host = xstrdup(host); | ||
49 | return host; | ||
50 | } | ||
51 | |||
37 | char *cgit_rooturl() | 52 | char *cgit_rooturl() |
38 | { | 53 | { |
39 | if (ctx.cfg.virtual_root) | 54 | if (ctx.cfg.virtual_root) |
40 | return fmt("%s/", ctx.cfg.virtual_root); | 55 | return fmt("%s/", ctx.cfg.virtual_root); |
41 | else | 56 | else |
42 | return ctx.cfg.script_name; | 57 | return ctx.cfg.script_name; |
43 | } | 58 | } |
44 | 59 | ||
45 | char *cgit_repourl(const char *reponame) | 60 | char *cgit_repourl(const char *reponame) |
46 | { | 61 | { |
47 | if (ctx.cfg.virtual_root) { | 62 | if (ctx.cfg.virtual_root) { |
48 | return fmt("%s/%s/", ctx.cfg.virtual_root, reponame); | 63 | return fmt("%s/%s/", ctx.cfg.virtual_root, reponame); |
49 | } else { | 64 | } else { |
50 | return fmt("?r=%s", reponame); | 65 | return fmt("?r=%s", reponame); |
51 | } | 66 | } |
52 | } | 67 | } |
53 | 68 | ||
54 | char *cgit_fileurl(const char *reponame, const char *pagename, | 69 | char *cgit_fileurl(const char *reponame, const char *pagename, |
55 | const char *filename, const char *query) | 70 | const char *filename, const char *query) |
56 | { | 71 | { |
57 | char *tmp; | 72 | char *tmp; |
58 | char *delim; | 73 | char *delim; |
59 | 74 | ||
60 | if (ctx.cfg.virtual_root) { | 75 | if (ctx.cfg.virtual_root) { |
61 | tmp = fmt("%s/%s/%s/%s", ctx.cfg.virtual_root, reponame, | 76 | tmp = fmt("%s/%s/%s/%s", ctx.cfg.virtual_root, reponame, |
62 | pagename, (filename ? filename:"")); | 77 | pagename, (filename ? filename:"")); |
63 | delim = "?"; | 78 | delim = "?"; |
64 | } else { | 79 | } else { |
65 | tmp = fmt("?url=%s/%s/%s", reponame, pagename, | 80 | tmp = fmt("?url=%s/%s/%s", reponame, pagename, |
66 | (filename ? filename : "")); | 81 | (filename ? filename : "")); |
67 | delim = "&"; | 82 | delim = "&"; |
68 | } | 83 | } |
@@ -399,81 +414,89 @@ void cgit_print_age(time_t t, time_t max_relative, char *format) | |||
399 | } | 414 | } |
400 | if (secs < TM_MONTH * 2) { | 415 | if (secs < TM_MONTH * 2) { |
401 | htmlf("<span class='age-weeks'>%.0f weeks</span>", | 416 | htmlf("<span class='age-weeks'>%.0f weeks</span>", |
402 | secs * 1.0 / TM_WEEK); | 417 | secs * 1.0 / TM_WEEK); |
403 | return; | 418 | return; |
404 | } | 419 | } |
405 | if (secs < TM_YEAR * 2) { | 420 | if (secs < TM_YEAR * 2) { |
406 | htmlf("<span class='age-months'>%.0f months</span>", | 421 | htmlf("<span class='age-months'>%.0f months</span>", |
407 | secs * 1.0 / TM_MONTH); | 422 | secs * 1.0 / TM_MONTH); |
408 | return; | 423 | return; |
409 | } | 424 | } |
410 | htmlf("<span class='age-years'>%.0f years</span>", | 425 | htmlf("<span class='age-years'>%.0f years</span>", |
411 | secs * 1.0 / TM_YEAR); | 426 | secs * 1.0 / TM_YEAR); |
412 | } | 427 | } |
413 | 428 | ||
414 | void cgit_print_http_headers(struct cgit_context *ctx) | 429 | void cgit_print_http_headers(struct cgit_context *ctx) |
415 | { | 430 | { |
416 | if (ctx->page.mimetype && ctx->page.charset) | 431 | if (ctx->page.mimetype && ctx->page.charset) |
417 | htmlf("Content-Type: %s; charset=%s\n", ctx->page.mimetype, | 432 | htmlf("Content-Type: %s; charset=%s\n", ctx->page.mimetype, |
418 | ctx->page.charset); | 433 | ctx->page.charset); |
419 | else if (ctx->page.mimetype) | 434 | else if (ctx->page.mimetype) |
420 | htmlf("Content-Type: %s\n", ctx->page.mimetype); | 435 | htmlf("Content-Type: %s\n", ctx->page.mimetype); |
421 | if (ctx->page.filename) | 436 | if (ctx->page.filename) |
422 | htmlf("Content-Disposition: inline; filename=\"%s\"\n", | 437 | htmlf("Content-Disposition: inline; filename=\"%s\"\n", |
423 | ctx->page.filename); | 438 | ctx->page.filename); |
424 | htmlf("Last-Modified: %s\n", http_date(ctx->page.modified)); | 439 | htmlf("Last-Modified: %s\n", http_date(ctx->page.modified)); |
425 | htmlf("Expires: %s\n", http_date(ctx->page.expires)); | 440 | htmlf("Expires: %s\n", http_date(ctx->page.expires)); |
426 | html("\n"); | 441 | html("\n"); |
427 | } | 442 | } |
428 | 443 | ||
429 | void cgit_print_docstart(struct cgit_context *ctx) | 444 | void cgit_print_docstart(struct cgit_context *ctx) |
430 | { | 445 | { |
446 | char *host = cgit_hosturl(); | ||
431 | html(cgit_doctype); | 447 | html(cgit_doctype); |
432 | html("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n"); | 448 | html("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n"); |
433 | html("<head>\n"); | 449 | html("<head>\n"); |
434 | html("<title>"); | 450 | html("<title>"); |
435 | html_txt(ctx->page.title); | 451 | html_txt(ctx->page.title); |
436 | html("</title>\n"); | 452 | html("</title>\n"); |
437 | htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version); | 453 | htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version); |
438 | if (ctx->cfg.robots && *ctx->cfg.robots) | 454 | if (ctx->cfg.robots && *ctx->cfg.robots) |
439 | htmlf("<meta name='robots' content='%s'/>\n", ctx->cfg.robots); | 455 | htmlf("<meta name='robots' content='%s'/>\n", ctx->cfg.robots); |
440 | html("<link rel='stylesheet' type='text/css' href='"); | 456 | html("<link rel='stylesheet' type='text/css' href='"); |
441 | html_attr(ctx->cfg.css); | 457 | html_attr(ctx->cfg.css); |
442 | html("'/>\n"); | 458 | html("'/>\n"); |
443 | if (ctx->cfg.favicon) { | 459 | if (ctx->cfg.favicon) { |
444 | html("<link rel='shortcut icon' href='"); | 460 | html("<link rel='shortcut icon' href='"); |
445 | html_attr(ctx->cfg.favicon); | 461 | html_attr(ctx->cfg.favicon); |
446 | html("'/>\n"); | 462 | html("'/>\n"); |
447 | } | 463 | } |
464 | if (host && ctx->repo) { | ||
465 | html("<link rel='alternate' title='Atom feed' href='http://"); | ||
466 | html_attr(cgit_hosturl()); | ||
467 | html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.path, | ||
468 | fmt("h=%s", ctx->qry.head))); | ||
469 | html("' type='application/atom+xml'/>"); | ||
470 | } | ||
448 | html("</head>\n"); | 471 | html("</head>\n"); |
449 | html("<body>\n"); | 472 | html("<body>\n"); |
450 | } | 473 | } |
451 | 474 | ||
452 | void cgit_print_docend() | 475 | void cgit_print_docend() |
453 | { | 476 | { |
454 | html("</div>"); | 477 | html("</div>"); |
455 | if (ctx.cfg.footer) | 478 | if (ctx.cfg.footer) |
456 | html_include(ctx.cfg.footer); | 479 | html_include(ctx.cfg.footer); |
457 | else { | 480 | else { |
458 | html("<div class='footer'>generated "); | 481 | html("<div class='footer'>generated "); |
459 | cgit_print_date(time(NULL), FMT_LONGDATE, ctx.cfg.local_time); | 482 | cgit_print_date(time(NULL), FMT_LONGDATE, ctx.cfg.local_time); |
460 | htmlf(" by cgit %s", cgit_version); | 483 | htmlf(" by cgit %s", cgit_version); |
461 | html("</div>\n"); | 484 | html("</div>\n"); |
462 | } | 485 | } |
463 | html("</body>\n</html>\n"); | 486 | html("</body>\n</html>\n"); |
464 | } | 487 | } |
465 | 488 | ||
466 | int print_branch_option(const char *refname, const unsigned char *sha1, | 489 | int print_branch_option(const char *refname, const unsigned char *sha1, |
467 | int flags, void *cb_data) | 490 | int flags, void *cb_data) |
468 | { | 491 | { |
469 | char *name = (char *)refname; | 492 | char *name = (char *)refname; |
470 | html_option(name, name, ctx.qry.head); | 493 | html_option(name, name, ctx.qry.head); |
471 | return 0; | 494 | return 0; |
472 | } | 495 | } |
473 | 496 | ||
474 | int print_archive_ref(const char *refname, const unsigned char *sha1, | 497 | int print_archive_ref(const char *refname, const unsigned char *sha1, |
475 | int flags, void *cb_data) | 498 | int flags, void *cb_data) |
476 | { | 499 | { |
477 | struct tag *tag; | 500 | struct tag *tag; |
478 | struct taginfo *info; | 501 | struct taginfo *info; |
479 | struct object *obj; | 502 | struct object *obj; |
diff --git a/ui-shared.h b/ui-shared.h index 07da4b4..f4123d3 100644 --- a/ui-shared.h +++ b/ui-shared.h | |||
@@ -1,35 +1,36 @@ | |||
1 | #ifndef UI_SHARED_H | 1 | #ifndef UI_SHARED_H |
2 | #define UI_SHARED_H | 2 | #define UI_SHARED_H |
3 | 3 | ||
4 | extern char *cgit_hosturl(); | ||
4 | extern char *cgit_repourl(const char *reponame); | 5 | extern char *cgit_repourl(const char *reponame); |
5 | extern char *cgit_fileurl(const char *reponame, const char *pagename, | 6 | extern char *cgit_fileurl(const char *reponame, const char *pagename, |
6 | const char *filename, const char *query); | 7 | const char *filename, const char *query); |
7 | extern char *cgit_pageurl(const char *reponame, const char *pagename, | 8 | extern char *cgit_pageurl(const char *reponame, const char *pagename, |
8 | const char *query); | 9 | const char *query); |
9 | 10 | ||
10 | extern void cgit_index_link(char *name, char *title, char *class, | 11 | extern void cgit_index_link(char *name, char *title, char *class, |
11 | char *pattern, int ofs); | 12 | char *pattern, int ofs); |
12 | extern void cgit_tree_link(char *name, char *title, char *class, char *head, | 13 | extern void cgit_tree_link(char *name, char *title, char *class, char *head, |
13 | char *rev, char *path); | 14 | char *rev, char *path); |
14 | extern void cgit_log_link(char *name, char *title, char *class, char *head, | 15 | extern void cgit_log_link(char *name, char *title, char *class, char *head, |
15 | char *rev, char *path, int ofs, char *grep, | 16 | char *rev, char *path, int ofs, char *grep, |
16 | char *pattern); | 17 | char *pattern); |
17 | extern void cgit_commit_link(char *name, char *title, char *class, char *head, | 18 | extern void cgit_commit_link(char *name, char *title, char *class, char *head, |
18 | char *rev); | 19 | char *rev); |
19 | extern void cgit_patch_link(char *name, char *title, char *class, char *head, | 20 | extern void cgit_patch_link(char *name, char *title, char *class, char *head, |
20 | char *rev); | 21 | char *rev); |
21 | extern void cgit_refs_link(char *name, char *title, char *class, char *head, | 22 | extern void cgit_refs_link(char *name, char *title, char *class, char *head, |
22 | char *rev, char *path); | 23 | char *rev, char *path); |
23 | extern void cgit_snapshot_link(char *name, char *title, char *class, | 24 | extern void cgit_snapshot_link(char *name, char *title, char *class, |
24 | char *head, char *rev, char *archivename); | 25 | char *head, char *rev, char *archivename); |
25 | extern void cgit_diff_link(char *name, char *title, char *class, char *head, | 26 | extern void cgit_diff_link(char *name, char *title, char *class, char *head, |
26 | char *new_rev, char *old_rev, char *path); | 27 | char *new_rev, char *old_rev, char *path); |
27 | extern void cgit_object_link(struct object *obj); | 28 | extern void cgit_object_link(struct object *obj); |
28 | 29 | ||
29 | extern void cgit_print_error(char *msg); | 30 | extern void cgit_print_error(char *msg); |
30 | extern void cgit_print_date(time_t secs, char *format, int local_time); | 31 | extern void cgit_print_date(time_t secs, char *format, int local_time); |
31 | extern void cgit_print_age(time_t t, time_t max_relative, char *format); | 32 | extern void cgit_print_age(time_t t, time_t max_relative, char *format); |
32 | extern void cgit_print_http_headers(struct cgit_context *ctx); | 33 | extern void cgit_print_http_headers(struct cgit_context *ctx); |
33 | extern void cgit_print_docstart(struct cgit_context *ctx); | 34 | extern void cgit_print_docstart(struct cgit_context *ctx); |
34 | extern void cgit_print_docend(); | 35 | extern void cgit_print_docend(); |
35 | extern void cgit_print_pageheader(struct cgit_context *ctx); | 36 | extern void cgit_print_pageheader(struct cgit_context *ctx); |