summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--Makefile2
-rw-r--r--cgit.c3
-rw-r--r--cgit.h5
-rw-r--r--shared.c2
-rw-r--r--ui-shared.c24
-rw-r--r--ui-summary.c33
-rw-r--r--ui-tag.c74
7 files changed, 111 insertions, 32 deletions
diff --git a/Makefile b/Makefile
index cea09f1..50d0011 100644
--- a/Makefile
+++ b/Makefile
@@ -1,58 +1,58 @@
1prefix = /var/www/htdocs/cgit 1prefix = /var/www/htdocs/cgit
2SHA1_HEADER = <openssl/sha.h> 2SHA1_HEADER = <openssl/sha.h>
3CACHE_ROOT = /var/cache/cgit 3CACHE_ROOT = /var/cache/cgit
4CGIT_CONFIG = /etc/cgitrc 4CGIT_CONFIG = /etc/cgitrc
5CGIT_SCRIPT_NAME = cgit.cgi 5CGIT_SCRIPT_NAME = cgit.cgi
6 6
7# 7#
8# Let the user override the above settings. 8# Let the user override the above settings.
9# 9#
10-include cgit.conf 10-include cgit.conf
11 11
12 12
13CGIT_VERSION = 0.5 13CGIT_VERSION = 0.5
14 14
15all: cgit 15all: cgit
16 16
17VERSION: 17VERSION:
18 sh gen-version.sh 18 sh gen-version.sh
19 19
20-include VERSION 20-include VERSION
21 21
22 22
23EXTLIBS = git/libgit.a git/xdiff/lib.a -lz -lcrypto 23EXTLIBS = git/libgit.a git/xdiff/lib.a -lz -lcrypto
24OBJECTS = shared.o cache.o parsing.o html.o ui-shared.o ui-repolist.o \ 24OBJECTS = shared.o cache.o parsing.o html.o ui-shared.o ui-repolist.o \
25 ui-summary.o ui-log.o ui-tree.o ui-commit.o ui-diff.o \ 25 ui-summary.o ui-log.o ui-tree.o ui-commit.o ui-diff.o \
26 ui-snapshot.o ui-blob.o 26 ui-snapshot.o ui-blob.o ui-tag.o
27 27
28CFLAGS += -Wall 28CFLAGS += -Wall
29 29
30ifdef DEBUG 30ifdef DEBUG
31 CFLAGS += -g 31 CFLAGS += -g
32endif 32endif
33 33
34CFLAGS += -Igit 34CFLAGS += -Igit
35CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)' 35CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)'
36CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"' 36CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"'
37CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"' 37CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"'
38CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"' 38CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"'
39 39
40 40
41# 41#
42# If make is run on a nongit platform, get the git sources as a tarball. 42# If make is run on a nongit platform, get the git sources as a tarball.
43# 43#
44GITVER = $(shell git version 2>/dev/null || echo nogit) 44GITVER = $(shell git version 2>/dev/null || echo nogit)
45ifeq ($(GITVER),nogit) 45ifeq ($(GITVER),nogit)
46GITURL = http://www.kernel.org/pub/software/scm/git/git-1.5.2.tar.bz2 46GITURL = http://www.kernel.org/pub/software/scm/git/git-1.5.2.tar.bz2
47INITGIT = test -e git/git.c || ((curl "$(GITURL)" | tar -xj) && mv git-1.5.2 git) 47INITGIT = test -e git/git.c || ((curl "$(GITURL)" | tar -xj) && mv git-1.5.2 git)
48else 48else
49INITGIT = ./submodules.sh -i 49INITGIT = ./submodules.sh -i
50endif 50endif
51 51
52 52
53cgit: cgit.c cgit.h VERSION $(OBJECTS) 53cgit: cgit.c cgit.h VERSION $(OBJECTS)
54 $(CC) $(CFLAGS) cgit.c -o cgit $(OBJECTS) $(EXTLIBS) 54 $(CC) $(CFLAGS) cgit.c -o cgit $(OBJECTS) $(EXTLIBS)
55 55
56$(OBJECTS): cgit.h git/libgit.a 56$(OBJECTS): cgit.h git/libgit.a
57 57
58git/libgit.a: 58git/libgit.a:
diff --git a/cgit.c b/cgit.c
index 1281bfa..4b91829 100644
--- a/cgit.c
+++ b/cgit.c
@@ -72,64 +72,67 @@ static void cgit_print_repo_page(struct cacheitem *item)
72 cgit_repo->url, cgit_query_name); 72 cgit_repo->url, cgit_query_name);
73 return; 73 return;
74 } 74 }
75 75
76 if (cgit_cmd == CMD_BLOB) { 76 if (cgit_cmd == CMD_BLOB) {
77 cgit_print_blob(item, cgit_query_sha1, cgit_query_path); 77 cgit_print_blob(item, cgit_query_sha1, cgit_query_path);
78 return; 78 return;
79 } 79 }
80 80
81 show_search = (cgit_cmd == CMD_LOG); 81 show_search = (cgit_cmd == CMD_LOG);
82 cgit_print_docstart(title, item); 82 cgit_print_docstart(title, item);
83 if (!cgit_cmd) { 83 if (!cgit_cmd) {
84 cgit_print_pageheader("summary", show_search); 84 cgit_print_pageheader("summary", show_search);
85 cgit_print_summary(); 85 cgit_print_summary();
86 cgit_print_docend(); 86 cgit_print_docend();
87 return; 87 return;
88 } 88 }
89 89
90 cgit_print_pageheader(cgit_query_page, show_search); 90 cgit_print_pageheader(cgit_query_page, show_search);
91 91
92 switch(cgit_cmd) { 92 switch(cgit_cmd) {
93 case CMD_LOG: 93 case CMD_LOG:
94 cgit_print_log(cgit_query_sha1, cgit_query_ofs, 94 cgit_print_log(cgit_query_sha1, cgit_query_ofs,
95 cgit_max_commit_count, cgit_query_search, 95 cgit_max_commit_count, cgit_query_search,
96 cgit_query_path, 1); 96 cgit_query_path, 1);
97 break; 97 break;
98 case CMD_TREE: 98 case CMD_TREE:
99 cgit_print_tree(cgit_query_sha1, cgit_query_path); 99 cgit_print_tree(cgit_query_sha1, cgit_query_path);
100 break; 100 break;
101 case CMD_COMMIT: 101 case CMD_COMMIT:
102 cgit_print_commit(cgit_query_sha1); 102 cgit_print_commit(cgit_query_sha1);
103 break; 103 break;
104 case CMD_TAG:
105 cgit_print_tag(cgit_query_sha1);
106 break;
104 case CMD_DIFF: 107 case CMD_DIFF:
105 cgit_print_diff(cgit_query_sha1, cgit_query_sha2); 108 cgit_print_diff(cgit_query_sha1, cgit_query_sha2);
106 break; 109 break;
107 default: 110 default:
108 cgit_print_error("Invalid request"); 111 cgit_print_error("Invalid request");
109 } 112 }
110 cgit_print_docend(); 113 cgit_print_docend();
111} 114}
112 115
113static void cgit_fill_cache(struct cacheitem *item, int use_cache) 116static void cgit_fill_cache(struct cacheitem *item, int use_cache)
114{ 117{
115 static char buf[PATH_MAX]; 118 static char buf[PATH_MAX];
116 int stdout2; 119 int stdout2;
117 120
118 getcwd(buf, sizeof(buf)); 121 getcwd(buf, sizeof(buf));
119 item->st.st_mtime = time(NULL); 122 item->st.st_mtime = time(NULL);
120 123
121 if (use_cache) { 124 if (use_cache) {
122 stdout2 = chk_positive(dup(STDOUT_FILENO), 125 stdout2 = chk_positive(dup(STDOUT_FILENO),
123 "Preserving STDOUT"); 126 "Preserving STDOUT");
124 chk_zero(close(STDOUT_FILENO), "Closing STDOUT"); 127 chk_zero(close(STDOUT_FILENO), "Closing STDOUT");
125 chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)"); 128 chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)");
126 } 129 }
127 130
128 if (cgit_repo) 131 if (cgit_repo)
129 cgit_print_repo_page(item); 132 cgit_print_repo_page(item);
130 else 133 else
131 cgit_print_repolist(item); 134 cgit_print_repolist(item);
132 135
133 if (use_cache) { 136 if (use_cache) {
134 chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT"); 137 chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT");
135 chk_positive(dup2(stdout2, STDOUT_FILENO), 138 chk_positive(dup2(stdout2, STDOUT_FILENO),
diff --git a/cgit.h b/cgit.h
index 2ff5340..610a16d 100644
--- a/cgit.h
+++ b/cgit.h
@@ -1,62 +1,62 @@
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 19
20 20
21/* 21/*
22 * The valid cgit repo-commands 22 * The valid cgit repo-commands
23 */ 23 */
24#define CMD_LOG 1 24#define CMD_LOG 1
25#define CMD_COMMIT 2 25#define CMD_COMMIT 2
26#define CMD_DIFF 3 26#define CMD_DIFF 3
27#define CMD_TREE 4 27#define CMD_TREE 4
28#define CMD_BLOB 5 28#define CMD_BLOB 5
29#define CMD_SNAPSHOT 6 29#define CMD_SNAPSHOT 6
30 30#define CMD_TAG 7
31 31
32/* 32/*
33 * Dateformats used on misc. pages 33 * Dateformats used on misc. pages
34 */ 34 */
35#define FMT_LONGDATE "%Y-%m-%d %H:%M:%S" 35#define FMT_LONGDATE "%Y-%m-%d %H:%M:%S"
36#define FMT_SHORTDATE "%Y-%m-%d" 36#define FMT_SHORTDATE "%Y-%m-%d"
37 37
38 38
39/* 39/*
40 * Limits used for relative dates 40 * Limits used for relative dates
41 */ 41 */
42#define TM_MIN 60 42#define TM_MIN 60
43#define TM_HOUR (TM_MIN * 60) 43#define TM_HOUR (TM_MIN * 60)
44#define TM_DAY (TM_HOUR * 24) 44#define TM_DAY (TM_HOUR * 24)
45#define TM_WEEK (TM_DAY * 7) 45#define TM_WEEK (TM_DAY * 7)
46#define TM_YEAR (TM_DAY * 365) 46#define TM_YEAR (TM_DAY * 365)
47#define TM_MONTH (TM_YEAR / 12.0) 47#define TM_MONTH (TM_YEAR / 12.0)
48 48
49 49
50typedef void (*configfn)(const char *name, const char *value); 50typedef void (*configfn)(const char *name, const char *value);
51typedef void (*filepair_fn)(struct diff_filepair *pair); 51typedef void (*filepair_fn)(struct diff_filepair *pair);
52typedef void (*linediff_fn)(char *line, int len); 52typedef void (*linediff_fn)(char *line, int len);
53 53
54struct cacheitem { 54struct cacheitem {
55 char *name; 55 char *name;
56 struct stat st; 56 struct stat st;
57 int ttl; 57 int ttl;
58 int fd; 58 int fd;
59}; 59};
60 60
61struct repoinfo { 61struct repoinfo {
62 char *url; 62 char *url;
@@ -183,54 +183,57 @@ extern void html_attr(char *txt);
183extern void html_hidden(char *name, char *value); 183extern void html_hidden(char *name, char *value);
184extern void html_link_open(char *url, char *title, char *class); 184extern void html_link_open(char *url, char *title, char *class);
185extern void html_link_close(void); 185extern void html_link_close(void);
186extern void html_filemode(unsigned short mode); 186extern void html_filemode(unsigned short mode);
187extern int html_include(const char *filename); 187extern int html_include(const char *filename);
188 188
189extern int cgit_read_config(const char *filename, configfn fn); 189extern int cgit_read_config(const char *filename, configfn fn);
190extern int cgit_parse_query(char *txt, configfn fn); 190extern int cgit_parse_query(char *txt, configfn fn);
191extern struct commitinfo *cgit_parse_commit(struct commit *commit); 191extern struct commitinfo *cgit_parse_commit(struct commit *commit);
192extern struct taginfo *cgit_parse_tag(struct tag *tag); 192extern struct taginfo *cgit_parse_tag(struct tag *tag);
193extern void cgit_parse_url(const char *url); 193extern void cgit_parse_url(const char *url);
194 194
195extern char *cache_safe_filename(const char *unsafe); 195extern char *cache_safe_filename(const char *unsafe);
196extern int cache_lock(struct cacheitem *item); 196extern int cache_lock(struct cacheitem *item);
197extern int cache_unlock(struct cacheitem *item); 197extern int cache_unlock(struct cacheitem *item);
198extern int cache_cancel_lock(struct cacheitem *item); 198extern int cache_cancel_lock(struct cacheitem *item);
199extern int cache_exist(struct cacheitem *item); 199extern int cache_exist(struct cacheitem *item);
200extern int cache_expired(struct cacheitem *item); 200extern int cache_expired(struct cacheitem *item);
201 201
202extern char *cgit_repourl(const char *reponame); 202extern char *cgit_repourl(const char *reponame);
203extern char *cgit_pageurl(const char *reponame, const char *pagename, 203extern char *cgit_pageurl(const char *reponame, const char *pagename,
204 const char *query); 204 const char *query);
205 205
206extern void cgit_tree_link(char *name, char *title, char *class, char *head, 206extern void cgit_tree_link(char *name, char *title, char *class, char *head,
207 char *rev, char *path); 207 char *rev, char *path);
208extern void cgit_log_link(char *name, char *title, char *class, char *head, 208extern void cgit_log_link(char *name, char *title, char *class, char *head,
209 char *rev, char *path, int ofs); 209 char *rev, char *path, int ofs);
210extern void cgit_commit_link(char *name, char *title, char *class, char *head, 210extern void cgit_commit_link(char *name, char *title, char *class, char *head,
211 char *rev); 211 char *rev);
212extern void cgit_diff_link(char *name, char *title, char *class, char *head, 212extern void cgit_diff_link(char *name, char *title, char *class, char *head,
213 char *new_rev, char *old_rev, char *path); 213 char *new_rev, char *old_rev, char *path);
214 214
215extern void cgit_object_link(struct object *obj);
216
215extern void cgit_print_error(char *msg); 217extern void cgit_print_error(char *msg);
216extern void cgit_print_date(time_t secs, char *format); 218extern void cgit_print_date(time_t secs, char *format);
217extern void cgit_print_age(time_t t, time_t max_relative, char *format); 219extern void cgit_print_age(time_t t, time_t max_relative, char *format);
218extern void cgit_print_docstart(char *title, struct cacheitem *item); 220extern void cgit_print_docstart(char *title, struct cacheitem *item);
219extern void cgit_print_docend(); 221extern void cgit_print_docend();
220extern void cgit_print_pageheader(char *title, int show_search); 222extern void cgit_print_pageheader(char *title, int show_search);
221extern void cgit_print_snapshot_start(const char *mimetype, 223extern void cgit_print_snapshot_start(const char *mimetype,
222 const char *filename, 224 const char *filename,
223 struct cacheitem *item); 225 struct cacheitem *item);
224 226
225extern void cgit_print_repolist(struct cacheitem *item); 227extern void cgit_print_repolist(struct cacheitem *item);
226extern void cgit_print_summary(); 228extern void cgit_print_summary();
227extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *path, int pager); 229extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *path, int pager);
228extern void cgit_print_blob(struct cacheitem *item, const char *hex, char *path); 230extern void cgit_print_blob(struct cacheitem *item, const char *hex, char *path);
229extern void cgit_print_tree(const char *rev, char *path); 231extern void cgit_print_tree(const char *rev, char *path);
230extern void cgit_print_commit(char *hex); 232extern void cgit_print_commit(char *hex);
233extern void cgit_print_tag(char *revname);
231extern void cgit_print_diff(const char *new_hex, const char *old_hex); 234extern void cgit_print_diff(const char *new_hex, const char *old_hex);
232extern void cgit_print_snapshot(struct cacheitem *item, const char *hex, 235extern void cgit_print_snapshot(struct cacheitem *item, const char *hex,
233 const char *format, const char *prefix, 236 const char *format, const char *prefix,
234 const char *filename); 237 const char *filename);
235 238
236#endif /* CGIT_H */ 239#endif /* CGIT_H */
diff --git a/shared.c b/shared.c
index 1a5b866..06693b0 100644
--- a/shared.c
+++ b/shared.c
@@ -34,65 +34,65 @@ int cgit_enable_log_linecount = 0;
34int cgit_max_lock_attempts = 5; 34int cgit_max_lock_attempts = 5;
35int cgit_cache_root_ttl = 5; 35int cgit_cache_root_ttl = 5;
36int cgit_cache_repo_ttl = 5; 36int cgit_cache_repo_ttl = 5;
37int cgit_cache_dynamic_ttl = 5; 37int cgit_cache_dynamic_ttl = 5;
38int cgit_cache_static_ttl = -1; 38int cgit_cache_static_ttl = -1;
39int cgit_cache_max_create_time = 5; 39int cgit_cache_max_create_time = 5;
40int cgit_summary_log = 0; 40int cgit_summary_log = 0;
41 41
42int cgit_max_msg_len = 60; 42int cgit_max_msg_len = 60;
43int cgit_max_repodesc_len = 60; 43int cgit_max_repodesc_len = 60;
44int cgit_max_commit_count = 50; 44int cgit_max_commit_count = 50;
45 45
46int cgit_query_has_symref = 0; 46int cgit_query_has_symref = 0;
47int cgit_query_has_sha1 = 0; 47int cgit_query_has_sha1 = 0;
48 48
49char *cgit_querystring = NULL; 49char *cgit_querystring = NULL;
50char *cgit_query_repo = NULL; 50char *cgit_query_repo = NULL;
51char *cgit_query_page = NULL; 51char *cgit_query_page = NULL;
52char *cgit_query_head = NULL; 52char *cgit_query_head = NULL;
53char *cgit_query_search = NULL; 53char *cgit_query_search = NULL;
54char *cgit_query_sha1 = NULL; 54char *cgit_query_sha1 = NULL;
55char *cgit_query_sha2 = NULL; 55char *cgit_query_sha2 = NULL;
56char *cgit_query_path = NULL; 56char *cgit_query_path = NULL;
57char *cgit_query_name = NULL; 57char *cgit_query_name = NULL;
58int cgit_query_ofs = 0; 58int cgit_query_ofs = 0;
59 59
60int htmlfd = 0; 60int htmlfd = 0;
61 61
62 62
63int cgit_get_cmd_index(const char *cmd) 63int cgit_get_cmd_index(const char *cmd)
64{ 64{
65 static char *cmds[] = {"log", "commit", "diff", "tree", "blob", 65 static char *cmds[] = {"log", "commit", "diff", "tree", "blob",
66 "snapshot", NULL}; 66 "snapshot", "tag", NULL};
67 int i; 67 int i;
68 68
69 for(i = 0; cmds[i]; i++) 69 for(i = 0; cmds[i]; i++)
70 if (!strcmp(cmd, cmds[i])) 70 if (!strcmp(cmd, cmds[i]))
71 return i + 1; 71 return i + 1;
72 return 0; 72 return 0;
73} 73}
74 74
75int chk_zero(int result, char *msg) 75int chk_zero(int result, char *msg)
76{ 76{
77 if (result != 0) 77 if (result != 0)
78 die("%s: %s", msg, strerror(errno)); 78 die("%s: %s", msg, strerror(errno));
79 return result; 79 return result;
80} 80}
81 81
82int chk_positive(int result, char *msg) 82int chk_positive(int result, char *msg)
83{ 83{
84 if (result <= 0) 84 if (result <= 0)
85 die("%s: %s", msg, strerror(errno)); 85 die("%s: %s", msg, strerror(errno));
86 return result; 86 return result;
87} 87}
88 88
89struct repoinfo *add_repo(const char *url) 89struct repoinfo *add_repo(const char *url)
90{ 90{
91 struct repoinfo *ret; 91 struct repoinfo *ret;
92 92
93 if (++cgit_repolist.count > cgit_repolist.length) { 93 if (++cgit_repolist.count > cgit_repolist.length) {
94 if (cgit_repolist.length == 0) 94 if (cgit_repolist.length == 0)
95 cgit_repolist.length = 8; 95 cgit_repolist.length = 8;
96 else 96 else
97 cgit_repolist.length *= 2; 97 cgit_repolist.length *= 2;
98 cgit_repolist.repos = xrealloc(cgit_repolist.repos, 98 cgit_repolist.repos = xrealloc(cgit_repolist.repos,
diff --git a/ui-shared.c b/ui-shared.c
index d4376ce..fd71c12 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -189,64 +189,88 @@ void cgit_commit_link(char *name, char *title, char *class, char *head,
189{ 189{
190 if (strlen(name) > cgit_max_msg_len && cgit_max_msg_len >= 15) { 190 if (strlen(name) > cgit_max_msg_len && cgit_max_msg_len >= 15) {
191 name[cgit_max_msg_len] = '\0'; 191 name[cgit_max_msg_len] = '\0';
192 name[cgit_max_msg_len - 1] = '.'; 192 name[cgit_max_msg_len - 1] = '.';
193 name[cgit_max_msg_len - 2] = '.'; 193 name[cgit_max_msg_len - 2] = '.';
194 name[cgit_max_msg_len - 3] = '.'; 194 name[cgit_max_msg_len - 3] = '.';
195 } 195 }
196 reporevlink("commit", name, title, class, head, rev, NULL); 196 reporevlink("commit", name, title, class, head, rev, NULL);
197} 197}
198 198
199void cgit_diff_link(char *name, char *title, char *class, char *head, 199void cgit_diff_link(char *name, char *title, char *class, char *head,
200 char *new_rev, char *old_rev, char *path) 200 char *new_rev, char *old_rev, char *path)
201{ 201{
202 char *delim; 202 char *delim;
203 203
204 delim = repolink(title, class, "diff", head, path); 204 delim = repolink(title, class, "diff", head, path);
205 if (new_rev && strcmp(new_rev, cgit_query_head)) { 205 if (new_rev && strcmp(new_rev, cgit_query_head)) {
206 html(delim); 206 html(delim);
207 html("id="); 207 html("id=");
208 html_attr(new_rev); 208 html_attr(new_rev);
209 delim = "&amp;"; 209 delim = "&amp;";
210 } 210 }
211 if (old_rev) { 211 if (old_rev) {
212 html(delim); 212 html(delim);
213 html("id2="); 213 html("id2=");
214 html_attr(old_rev); 214 html_attr(old_rev);
215 } 215 }
216 html("'>"); 216 html("'>");
217 html_txt(name); 217 html_txt(name);
218 html("</a>"); 218 html("</a>");
219} 219}
220 220
221void cgit_object_link(struct object *obj)
222{
223 char *page, *arg, *url;
224
225 if (obj->type == OBJ_COMMIT) {
226 cgit_commit_link(fmt("commit %s", sha1_to_hex(obj->sha1)), NULL, NULL,
227 cgit_query_head, sha1_to_hex(obj->sha1));
228 return;
229 } else if (obj->type == OBJ_TREE) {
230 page = "tree";
231 arg = "id";
232 } else {
233 page = "blob";
234 arg = "id";
235 }
236
237 url = cgit_pageurl(cgit_query_repo, page,
238 fmt("%s=%s", arg, sha1_to_hex(obj->sha1)));
239 html_link_open(url, NULL, NULL);
240 htmlf("%s %s", typename(obj->type),
241 sha1_to_hex(obj->sha1));
242 html_link_close();
243}
244
221void cgit_print_date(time_t secs, char *format) 245void cgit_print_date(time_t secs, char *format)
222{ 246{
223 char buf[64]; 247 char buf[64];
224 struct tm *time; 248 struct tm *time;
225 249
226 time = gmtime(&secs); 250 time = gmtime(&secs);
227 strftime(buf, sizeof(buf)-1, format, time); 251 strftime(buf, sizeof(buf)-1, format, time);
228 html_txt(buf); 252 html_txt(buf);
229} 253}
230 254
231void cgit_print_age(time_t t, time_t max_relative, char *format) 255void cgit_print_age(time_t t, time_t max_relative, char *format)
232{ 256{
233 time_t now, secs; 257 time_t now, secs;
234 258
235 time(&now); 259 time(&now);
236 secs = now - t; 260 secs = now - t;
237 261
238 if (secs > max_relative && max_relative >= 0) { 262 if (secs > max_relative && max_relative >= 0) {
239 cgit_print_date(t, format); 263 cgit_print_date(t, format);
240 return; 264 return;
241 } 265 }
242 266
243 if (secs < TM_HOUR * 2) { 267 if (secs < TM_HOUR * 2) {
244 htmlf("<span class='age-mins'>%.0f min.</span>", 268 htmlf("<span class='age-mins'>%.0f min.</span>",
245 secs * 1.0 / TM_MIN); 269 secs * 1.0 / TM_MIN);
246 return; 270 return;
247 } 271 }
248 if (secs < TM_DAY * 2) { 272 if (secs < TM_DAY * 2) {
249 htmlf("<span class='age-hours'>%.0f hours</span>", 273 htmlf("<span class='age-hours'>%.0f hours</span>",
250 secs * 1.0 / TM_HOUR); 274 secs * 1.0 / TM_HOUR);
251 return; 275 return;
252 } 276 }
diff --git a/ui-summary.c b/ui-summary.c
index b4bc6d8..de8a180 100644
--- a/ui-summary.c
+++ b/ui-summary.c
@@ -18,138 +18,113 @@ static int cgit_print_branch_cb(const char *refname, const unsigned char *sha1,
18 char buf[256]; 18 char buf[256];
19 char *ref; 19 char *ref;
20 20
21 ref = xstrdup(refname); 21 ref = xstrdup(refname);
22 strncpy(buf, refname, sizeof(buf)); 22 strncpy(buf, refname, sizeof(buf));
23 commit = lookup_commit(sha1); 23 commit = lookup_commit(sha1);
24 // object is not really parsed at this point, because of some fallout 24 // object is not really parsed at this point, because of some fallout
25 // from previous calls to git functions in cgit_print_log() 25 // from previous calls to git functions in cgit_print_log()
26 commit->object.parsed = 0; 26 commit->object.parsed = 0;
27 if (commit && !parse_commit(commit)){ 27 if (commit && !parse_commit(commit)){
28 info = cgit_parse_commit(commit); 28 info = cgit_parse_commit(commit);
29 html("<tr><td>"); 29 html("<tr><td>");
30 cgit_log_link(ref, NULL, NULL, ref, NULL, NULL, 0); 30 cgit_log_link(ref, NULL, NULL, ref, NULL, NULL, 0);
31 html("</td><td>"); 31 html("</td><td>");
32 cgit_print_age(commit->date, -1, NULL); 32 cgit_print_age(commit->date, -1, NULL);
33 html("</td><td>"); 33 html("</td><td>");
34 html_txt(info->author); 34 html_txt(info->author);
35 html("</td><td>"); 35 html("</td><td>");
36 cgit_commit_link(info->subject, NULL, NULL, ref, NULL); 36 cgit_commit_link(info->subject, NULL, NULL, ref, NULL);
37 html("</td></tr>\n"); 37 html("</td></tr>\n");
38 cgit_free_commitinfo(info); 38 cgit_free_commitinfo(info);
39 } else { 39 } else {
40 html("<tr><td>"); 40 html("<tr><td>");
41 html_txt(buf); 41 html_txt(buf);
42 html("</td><td colspan='3'>"); 42 html("</td><td colspan='3'>");
43 htmlf("*** bad ref %s ***", sha1_to_hex(sha1)); 43 htmlf("*** bad ref %s ***", sha1_to_hex(sha1));
44 html("</td></tr>\n"); 44 html("</td></tr>\n");
45 } 45 }
46 free(ref); 46 free(ref);
47 return 0; 47 return 0;
48} 48}
49 49
50
51static void cgit_print_object_ref(struct object *obj)
52{
53 char *page, *arg, *url;
54
55 if (obj->type == OBJ_COMMIT) {
56 cgit_commit_link(fmt("commit %s", sha1_to_hex(obj->sha1)), NULL, NULL,
57 cgit_query_head, sha1_to_hex(obj->sha1));
58 return;
59 } else if (obj->type == OBJ_TREE) {
60 page = "tree";
61 arg = "id";
62 } else {
63 page = "view";
64 arg = "id";
65 }
66
67 url = cgit_pageurl(cgit_query_repo, page,
68 fmt("%s=%s", arg, sha1_to_hex(obj->sha1)));
69 html_link_open(url, NULL, NULL);
70 htmlf("%s %s", typename(obj->type),
71 sha1_to_hex(obj->sha1));
72 html_link_close();
73}
74
75static void print_tag_header() 50static void print_tag_header()
76{ 51{
77 html("<tr class='nohover'><th class='left'>Tag</th>" 52 html("<tr class='nohover'><th class='left'>Tag</th>"
78 "<th class='left'>Age</th>" 53 "<th class='left'>Age</th>"
79 "<th class='left'>Author</th>" 54 "<th class='left'>Author</th>"
80 "<th class='left'>Reference</th></tr>\n"); 55 "<th class='left'>Reference</th></tr>\n");
81 header = 1; 56 header = 1;
82} 57}
83 58
84static int cgit_print_tag_cb(const char *refname, const unsigned char *sha1, 59static int cgit_print_tag_cb(const char *refname, const unsigned char *sha1,
85 int flags, void *cb_data) 60 int flags, void *cb_data)
86{ 61{
87 struct tag *tag; 62 struct tag *tag;
88 struct taginfo *info; 63 struct taginfo *info;
89 struct object *obj; 64 struct object *obj;
90 char buf[256], *url; 65 char buf[256], *url;
91 66
92 strncpy(buf, refname, sizeof(buf)); 67 strncpy(buf, refname, sizeof(buf));
93 obj = parse_object(sha1); 68 obj = parse_object(sha1);
94 if (!obj) 69 if (!obj)
95 return 1; 70 return 1;
96 if (obj->type == OBJ_TAG) { 71 if (obj->type == OBJ_TAG) {
97 tag = lookup_tag(sha1); 72 tag = lookup_tag(sha1);
98 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) 73 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag)))
99 return 2; 74 return 2;
100 if (!header) 75 if (!header)
101 print_tag_header(); 76 print_tag_header();
102 html("<tr><td>"); 77 html("<tr><td>");
103 url = cgit_pageurl(cgit_query_repo, "view", 78 url = cgit_pageurl(cgit_query_repo, "tag",
104 fmt("id=%s", sha1_to_hex(sha1))); 79 fmt("id=%s", refname));
105 html_link_open(url, NULL, NULL); 80 html_link_open(url, NULL, NULL);
106 html_txt(buf); 81 html_txt(buf);
107 html_link_close(); 82 html_link_close();
108 html("</td><td>"); 83 html("</td><td>");
109 if (info->tagger_date > 0) 84 if (info->tagger_date > 0)
110 cgit_print_age(info->tagger_date, -1, NULL); 85 cgit_print_age(info->tagger_date, -1, NULL);
111 html("</td><td>"); 86 html("</td><td>");
112 if (info->tagger) 87 if (info->tagger)
113 html(info->tagger); 88 html(info->tagger);
114 html("</td><td>"); 89 html("</td><td>");
115 cgit_print_object_ref(tag->tagged); 90 cgit_object_link(tag->tagged);
116 html("</td></tr>\n"); 91 html("</td></tr>\n");
117 } else { 92 } else {
118 if (!header) 93 if (!header)
119 print_tag_header(); 94 print_tag_header();
120 html("<tr><td>"); 95 html("<tr><td>");
121 html_txt(buf); 96 html_txt(buf);
122 html("</td><td colspan='2'/><td>"); 97 html("</td><td colspan='2'/><td>");
123 cgit_print_object_ref(obj); 98 cgit_object_link(obj);
124 html("</td></tr>\n"); 99 html("</td></tr>\n");
125 } 100 }
126 return 0; 101 return 0;
127} 102}
128 103
129static int cgit_print_archive_cb(const char *refname, const unsigned char *sha1, 104static int cgit_print_archive_cb(const char *refname, const unsigned char *sha1,
130 int flags, void *cb_data) 105 int flags, void *cb_data)
131{ 106{
132 struct tag *tag; 107 struct tag *tag;
133 struct taginfo *info; 108 struct taginfo *info;
134 struct object *obj; 109 struct object *obj;
135 char buf[256], *url; 110 char buf[256], *url;
136 unsigned char fileid[20]; 111 unsigned char fileid[20];
137 112
138 if (prefixcmp(refname, "refs/archives")) 113 if (prefixcmp(refname, "refs/archives"))
139 return 0; 114 return 0;
140 strncpy(buf, refname+14, sizeof(buf)); 115 strncpy(buf, refname+14, sizeof(buf));
141 obj = parse_object(sha1); 116 obj = parse_object(sha1);
142 if (!obj) 117 if (!obj)
143 return 1; 118 return 1;
144 if (obj->type == OBJ_TAG) { 119 if (obj->type == OBJ_TAG) {
145 tag = lookup_tag(sha1); 120 tag = lookup_tag(sha1);
146 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) 121 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag)))
147 return 0; 122 return 0;
148 hashcpy(fileid, tag->tagged->sha1); 123 hashcpy(fileid, tag->tagged->sha1);
149 } else if (obj->type != OBJ_BLOB) { 124 } else if (obj->type != OBJ_BLOB) {
150 return 0; 125 return 0;
151 } else { 126 } else {
152 hashcpy(fileid, sha1); 127 hashcpy(fileid, sha1);
153 } 128 }
154 if (!header) { 129 if (!header) {
155 html("<table id='downloads'>"); 130 html("<table id='downloads'>");
diff --git a/ui-tag.c b/ui-tag.c
new file mode 100644
index 0000000..a6989ff
--- a/dev/null
+++ b/ui-tag.c
@@ -0,0 +1,74 @@
1/* ui-tag.c: display a tag
2 *
3 * Copyright (C) 2007 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
11
12static void print_tag_content(char *buf)
13{
14 char *p;
15
16 if (!buf)
17 return;
18
19 html("<div class='commit-subject'>");
20 p = strchr(buf, '\n');
21 if (p)
22 *p = '\0';
23 html_txt(buf);
24 html("</div>");
25 if (p) {
26 html("<div class='commit-msg'>");
27 html_txt(++p);
28 html("</div>");
29 }
30}
31
32void cgit_print_tag(char *revname)
33{
34 unsigned char sha1[20];
35 struct object *obj;
36 struct tag *tag;
37 struct taginfo *info;
38
39 if (get_sha1(revname, sha1)) {
40 cgit_print_error(fmt("Bad tag reference: %s", revname));
41 return;
42 }
43 obj = parse_object(sha1);
44 if (!obj) {
45 cgit_print_error(fmt("Bad object id: %s", sha1_to_hex(sha1)));
46 return;
47 }
48 if (obj->type == OBJ_TAG) {
49 tag = lookup_tag(sha1);
50 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) {
51 cgit_print_error(fmt("Bad tag object: %s", revname));
52 return;
53 }
54 html("<table class='commit-info'>\n");
55 htmlf("<tr><td>Tag name</td><td>%s (%s)</td></tr>\n",
56 revname, sha1_to_hex(sha1));
57 if (info->tagger_date > 0) {
58 html("<tr><td>Tag date</td><td>");
59 cgit_print_date(info->tagger_date, FMT_LONGDATE);
60 html("</td><tr>\n");
61 }
62 if (info->tagger) {
63 html("<tr><td>Tagged by</td><td>");
64 html_txt(info->tagger);
65 html("</td></tr>\n");
66 }
67 html("<tr><td>Tagged object</td><td>");
68 cgit_object_link(tag->tagged);
69 html("</td></tr>\n");
70 html("</table>\n");
71 print_tag_content(info->msg);
72 }
73 return;
74}