aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--cgit.c17
-rw-r--r--cgit.css15
-rw-r--r--cgit.h8
-rw-r--r--cgitrc.5.txt16
-rw-r--r--cmd.c48
-rw-r--r--cmd.h3
-rw-r--r--parsing.c4
-rw-r--r--scan-tree.c2
-rw-r--r--shared.c15
-rw-r--r--ui-atom.c4
-rw-r--r--ui-commit.c30
-rw-r--r--ui-commit.h2
-rw-r--r--ui-diff.c22
-rw-r--r--ui-log.c40
-rw-r--r--ui-patch.c8
-rw-r--r--ui-patch.h2
-rw-r--r--ui-plain.c68
-rw-r--r--ui-refs.c2
-rw-r--r--ui-shared.c231
-rw-r--r--ui-shared.h72
-rw-r--r--ui-tree.c15
22 files changed, 435 insertions, 191 deletions
diff --git a/Makefile b/Makefile
index 0a5055b..3a4d974 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
1CGIT_VERSION = v0.8.3.1 1CGIT_VERSION = v0.8.3.2
2CGIT_SCRIPT_NAME = cgit.cgi 2CGIT_SCRIPT_NAME = cgit.cgi
3CGIT_SCRIPT_PATH = /var/www/htdocs/cgit 3CGIT_SCRIPT_PATH = /var/www/htdocs/cgit
4CGIT_DATA_PATH = $(CGIT_SCRIPT_PATH) 4CGIT_DATA_PATH = $(CGIT_SCRIPT_PATH)
diff --git a/cgit.c b/cgit.c
index 37154e3..fde0757 100644
--- a/cgit.c
+++ b/cgit.c
@@ -62,6 +62,8 @@ void repo_config(struct cgit_repo *repo, const char *name, const char *value)
62 repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value); 62 repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value);
63 else if (!strcmp(name, "enable-remote-branches")) 63 else if (!strcmp(name, "enable-remote-branches"))
64 repo->enable_remote_branches = atoi(value); 64 repo->enable_remote_branches = atoi(value);
65 else if (!strcmp(name, "enable-subject-links"))
66 repo->enable_subject_links = atoi(value);
65 else if (!strcmp(name, "max-stats")) 67 else if (!strcmp(name, "max-stats"))
66 repo->max_stats = cgit_find_stats_period(value, NULL); 68 repo->max_stats = cgit_find_stats_period(value, NULL);
67 else if (!strcmp(name, "module-link")) 69 else if (!strcmp(name, "module-link"))
@@ -141,6 +143,8 @@ void config_cb(const char *name, const char *value)
141 ctx.cfg.enable_log_linecount = atoi(value); 143 ctx.cfg.enable_log_linecount = atoi(value);
142 else if (!strcmp(name, "enable-remote-branches")) 144 else if (!strcmp(name, "enable-remote-branches"))
143 ctx.cfg.enable_remote_branches = atoi(value); 145 ctx.cfg.enable_remote_branches = atoi(value);
146 else if (!strcmp(name, "enable-subject-links"))
147 ctx.cfg.enable_subject_links = atoi(value);
144 else if (!strcmp(name, "enable-tree-linenumbers")) 148 else if (!strcmp(name, "enable-tree-linenumbers"))
145 ctx.cfg.enable_tree_linenumbers = atoi(value); 149 ctx.cfg.enable_tree_linenumbers = atoi(value);
146 else if (!strcmp(name, "max-stats")) 150 else if (!strcmp(name, "max-stats"))
@@ -165,6 +169,8 @@ void config_cb(const char *name, const char *value)
165 ctx.cfg.commit_filter = new_filter(value, 0); 169 ctx.cfg.commit_filter = new_filter(value, 0);
166 else if (!strcmp(name, "embedded")) 170 else if (!strcmp(name, "embedded"))
167 ctx.cfg.embedded = atoi(value); 171 ctx.cfg.embedded = atoi(value);
172 else if (!strcmp(name, "max-atom-items"))
173 ctx.cfg.max_atom_items = atoi(value);
168 else if (!strcmp(name, "max-message-length")) 174 else if (!strcmp(name, "max-message-length"))
169 ctx.cfg.max_msg_len = atoi(value); 175 ctx.cfg.max_msg_len = atoi(value);
170 else if (!strcmp(name, "max-repodesc-length")) 176 else if (!strcmp(name, "max-repodesc-length"))
@@ -250,6 +256,10 @@ static void querystring_cb(const char *name, const char *value)
250 ctx.qry.period = xstrdup(value); 256 ctx.qry.period = xstrdup(value);
251 } else if (!strcmp(name, "ss")) { 257 } else if (!strcmp(name, "ss")) {
252 ctx.qry.ssdiff = atoi(value); 258 ctx.qry.ssdiff = atoi(value);
259 } else if (!strcmp(name, "all")) {
260 ctx.qry.show_all = atoi(value);
261 } else if (!strcmp(name, "context")) {
262 ctx.qry.context = atoi(value);
253 } 263 }
254} 264}
255 265
@@ -292,6 +302,7 @@ static void prepare_context(struct cgit_context *ctx)
292 ctx->cfg.summary_branches = 10; 302 ctx->cfg.summary_branches = 10;
293 ctx->cfg.summary_log = 10; 303 ctx->cfg.summary_log = 10;
294 ctx->cfg.summary_tags = 10; 304 ctx->cfg.summary_tags = 10;
305 ctx->cfg.max_atom_items = 10;
295 ctx->cfg.ssdiff = 0; 306 ctx->cfg.ssdiff = 0;
296 ctx->env.cgit_config = xstrdupn(getenv("CGIT_CONFIG")); 307 ctx->env.cgit_config = xstrdupn(getenv("CGIT_CONFIG"));
297 ctx->env.http_host = xstrdupn(getenv("HTTP_HOST")); 308 ctx->env.http_host = xstrdupn(getenv("HTTP_HOST"));
@@ -424,6 +435,12 @@ static void process_request(void *cbdata)
424 return; 435 return;
425 } 436 }
426 437
438 /* If cmd->want_vpath is set, assume ctx->qry.path contains a "virtual"
439 * in-project path limit to be made available at ctx->qry.vpath.
440 * Otherwise, no path limit is in effect (ctx->qry.vpath = NULL).
441 */
442 ctx->qry.vpath = cmd->want_vpath ? ctx->qry.path : NULL;
443
427 if (cmd->want_repo && !ctx->repo) { 444 if (cmd->want_repo && !ctx->repo) {
428 cgit_print_http_headers(ctx); 445 cgit_print_http_headers(ctx);
429 cgit_print_docstart(ctx); 446 cgit_print_docstart(ctx);
diff --git a/cgit.css b/cgit.css
index 0cb894a..6e47eb3 100644
--- a/cgit.css
+++ b/cgit.css
@@ -64,7 +64,7 @@ table#header td.sub {
64} 64}
65 65
66table.tabs { 66table.tabs {
67 /* border-bottom: solid 2px #ccc; */ 67 border-bottom: solid 3px #ccc;
68 border-collapse: collapse; 68 border-collapse: collapse;
69 margin-top: 2em; 69 margin-top: 2em;
70 margin-bottom: 0px; 70 margin-bottom: 0px;
@@ -102,10 +102,16 @@ table.tabs td.form select {
102 font-size: 90%; 102 font-size: 90%;
103} 103}
104 104
105div.path {
106 margin: 0px;
107 padding: 5px 2em 2px 2em;
108 color: #000;
109 background-color: #eee;
110}
111
105div.content { 112div.content {
106 margin: 0px; 113 margin: 0px;
107 padding: 2em; 114 padding: 2em;
108 border-top: solid 3px #ccc;
109 border-bottom: solid 3px #ccc; 115 border-bottom: solid 3px #ccc;
110} 116}
111 117
@@ -525,7 +531,10 @@ a.deco {
525 border: solid 1px #770000; 531 border: solid 1px #770000;
526} 532}
527 533
528div.commit-subject a { 534div.commit-subject a.branch-deco,
535div.commit-subject a.tag-deco,
536div.commit-subject a.remote-deco,
537div.commit-subject a.deco {
529 margin-left: 1em; 538 margin-left: 1em;
530 font-size: 75%; 539 font-size: 75%;
531} 540}
diff --git a/cgit.h b/cgit.h
index 568e0c0..2bf6ab0 100644
--- a/cgit.h
+++ b/cgit.h
@@ -73,6 +73,7 @@ struct cgit_repo {
73 int enable_log_filecount; 73 int enable_log_filecount;
74 int enable_log_linecount; 74 int enable_log_linecount;
75 int enable_remote_branches; 75 int enable_remote_branches;
76 int enable_subject_links;
76 int max_stats; 77 int max_stats;
77 time_t mtime; 78 time_t mtime;
78 struct cgit_filter *about_filter; 79 struct cgit_filter *about_filter;
@@ -145,6 +146,9 @@ struct cgit_query {
145 char *sort; 146 char *sort;
146 int showmsg; 147 int showmsg;
147 int ssdiff; 148 int ssdiff;
149 int show_all;
150 int context;
151 char *vpath;
148}; 152};
149 153
150struct cgit_config { 154struct cgit_config {
@@ -181,8 +185,10 @@ struct cgit_config {
181 int enable_log_filecount; 185 int enable_log_filecount;
182 int enable_log_linecount; 186 int enable_log_linecount;
183 int enable_remote_branches; 187 int enable_remote_branches;
188 int enable_subject_links;
184 int enable_tree_linenumbers; 189 int enable_tree_linenumbers;
185 int local_time; 190 int local_time;
191 int max_atom_items;
186 int max_repo_count; 192 int max_repo_count;
187 int max_commit_count; 193 int max_commit_count;
188 int max_lock_attempts; 194 int max_lock_attempts;
@@ -273,7 +279,7 @@ extern void *cgit_free_commitinfo(struct commitinfo *info);
273extern int cgit_diff_files(const unsigned char *old_sha1, 279extern int cgit_diff_files(const unsigned char *old_sha1,
274 const unsigned char *new_sha1, 280 const unsigned char *new_sha1,
275 unsigned long *old_size, unsigned long *new_size, 281 unsigned long *old_size, unsigned long *new_size,
276 int *binary, linediff_fn fn); 282 int *binary, int context, linediff_fn fn);
277 283
278extern void cgit_diff_tree(const unsigned char *old_sha1, 284extern void cgit_diff_tree(const unsigned char *old_sha1,
279 const unsigned char *new_sha1, 285 const unsigned char *new_sha1,
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index d74d9e7..a853522 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -115,6 +115,12 @@ enable-remote-branches::
115 in the summary and refs views. Default value: "0". See also: 115 in the summary and refs views. Default value: "0". See also:
116 "repo.enable-remote-branches". 116 "repo.enable-remote-branches".
117 117
118enable-subject-links::
119 Flag which, when set to "1", will make cgit use the subject of the
120 parent commit as link text when generating links to parent commits
121 in commit view. Default value: "0". See also:
122 "repo.enable-subject-links".
123
118enable-tree-linenumbers:: 124enable-tree-linenumbers::
119 Flag which, when set to "1", will make cgit generate linenumber links 125 Flag which, when set to "1", will make cgit generate linenumber links
120 for plaintext blobs printed in the tree view. Default value: "1". 126 for plaintext blobs printed in the tree view. Default value: "1".
@@ -166,6 +172,10 @@ logo-link::
166 calculated url of the repository index page will be used. Default 172 calculated url of the repository index page will be used. Default
167 value: none. 173 value: none.
168 174
175max-atom-items::
176 Specifies the number of items to display in atom feeds view. Default
177 value: "10".
178
169max-commit-count:: 179max-commit-count::
170 Specifies the number of entries to list per page in "log" view. Default 180 Specifies the number of entries to list per page in "log" view. Default
171 value: "50". 181 value: "50".
@@ -321,6 +331,10 @@ repo.enable-remote-branches::
321 Flag which, when set to "1", will make cgit display remote branches 331 Flag which, when set to "1", will make cgit display remote branches
322 in the summary and refs views. Default value: <enable-remote-branches>. 332 in the summary and refs views. Default value: <enable-remote-branches>.
323 333
334repo.enable-subject-links::
335 A flag which can be used to override the global setting
336 `enable-subject-links'. Default value: none.
337
324repo.max-stats:: 338repo.max-stats::
325 Override the default maximum statistics period. Valid values are equal 339 Override the default maximum statistics period. Valid values are equal
326 to the values specified for the global "max-stats" setting. Default 340 to the values specified for the global "max-stats" setting. Default
@@ -430,7 +444,7 @@ snapshots=tar.gz tar.bz2 zip
430## List of common mimetypes 444## List of common mimetypes
431## 445##
432 446
433mimetype.git=image/git 447mimetype.gif=image/gif
434mimetype.html=text/html 448mimetype.html=text/html
435mimetype.jpg=image/jpeg 449mimetype.jpg=image/jpeg
436mimetype.jpeg=image/jpeg 450mimetype.jpeg=image/jpeg
diff --git a/cmd.c b/cmd.c
index 766f903..6dc9f5e 100644
--- a/cmd.c
+++ b/cmd.c
@@ -33,7 +33,7 @@ static void HEAD_fn(struct cgit_context *ctx)
33 33
34static void atom_fn(struct cgit_context *ctx) 34static void atom_fn(struct cgit_context *ctx)
35{ 35{
36 cgit_print_atom(ctx->qry.head, ctx->qry.path, 10); 36 cgit_print_atom(ctx->qry.head, ctx->qry.path, ctx->cfg.max_atom_items);
37} 37}
38 38
39static void about_fn(struct cgit_context *ctx) 39static void about_fn(struct cgit_context *ctx)
@@ -51,7 +51,7 @@ static void blob_fn(struct cgit_context *ctx)
51 51
52static void commit_fn(struct cgit_context *ctx) 52static void commit_fn(struct cgit_context *ctx)
53{ 53{
54 cgit_print_commit(ctx->qry.sha1); 54 cgit_print_commit(ctx->qry.sha1, ctx->qry.path);
55} 55}
56 56
57static void diff_fn(struct cgit_context *ctx) 57static void diff_fn(struct cgit_context *ctx)
@@ -90,7 +90,7 @@ static void repolist_fn(struct cgit_context *ctx)
90 90
91static void patch_fn(struct cgit_context *ctx) 91static void patch_fn(struct cgit_context *ctx)
92{ 92{
93 cgit_print_patch(ctx->qry.sha1); 93 cgit_print_patch(ctx->qry.sha1, ctx->qry.path);
94} 94}
95 95
96static void plain_fn(struct cgit_context *ctx) 96static void plain_fn(struct cgit_context *ctx)
@@ -129,31 +129,31 @@ static void tree_fn(struct cgit_context *ctx)
129 cgit_print_tree(ctx->qry.sha1, ctx->qry.path); 129 cgit_print_tree(ctx->qry.sha1, ctx->qry.path);
130} 130}
131 131
132#define def_cmd(name, want_repo, want_layout) \ 132#define def_cmd(name, want_repo, want_layout, want_vpath) \
133 {#name, name##_fn, want_repo, want_layout} 133 {#name, name##_fn, want_repo, want_layout, want_vpath}
134 134
135struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx) 135struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx)
136{ 136{
137 static struct cgit_cmd cmds[] = { 137 static struct cgit_cmd cmds[] = {
138 def_cmd(HEAD, 1, 0), 138 def_cmd(HEAD, 1, 0, 0),
139 def_cmd(atom, 1, 0), 139 def_cmd(atom, 1, 0, 0),
140 def_cmd(about, 0, 1), 140 def_cmd(about, 0, 1, 0),
141 def_cmd(blob, 1, 0), 141 def_cmd(blob, 1, 0, 0),
142 def_cmd(commit, 1, 1), 142 def_cmd(commit, 1, 1, 1),
143 def_cmd(diff, 1, 1), 143 def_cmd(diff, 1, 1, 1),
144 def_cmd(info, 1, 0), 144 def_cmd(info, 1, 0, 0),
145 def_cmd(log, 1, 1), 145 def_cmd(log, 1, 1, 1),
146 def_cmd(ls_cache, 0, 0), 146 def_cmd(ls_cache, 0, 0, 0),
147 def_cmd(objects, 1, 0), 147 def_cmd(objects, 1, 0, 0),
148 def_cmd(patch, 1, 0), 148 def_cmd(patch, 1, 0, 1),
149 def_cmd(plain, 1, 0), 149 def_cmd(plain, 1, 0, 0),
150 def_cmd(refs, 1, 1), 150 def_cmd(refs, 1, 1, 0),
151 def_cmd(repolist, 0, 0), 151 def_cmd(repolist, 0, 0, 0),
152 def_cmd(snapshot, 1, 0), 152 def_cmd(snapshot, 1, 0, 0),
153 def_cmd(stats, 1, 1), 153 def_cmd(stats, 1, 1, 1),
154 def_cmd(summary, 1, 1), 154 def_cmd(summary, 1, 1, 0),
155 def_cmd(tag, 1, 1), 155 def_cmd(tag, 1, 1, 0),
156 def_cmd(tree, 1, 1), 156 def_cmd(tree, 1, 1, 1),
157 }; 157 };
158 int i; 158 int i;
159 159
diff --git a/cmd.h b/cmd.h
index ec9e691..8dc01bd 100644
--- a/cmd.h
+++ b/cmd.h
@@ -7,7 +7,8 @@ struct cgit_cmd {
7 const char *name; 7 const char *name;
8 cgit_cmd_fn fn; 8 cgit_cmd_fn fn;
9 unsigned int want_repo:1, 9 unsigned int want_repo:1,
10 want_layout:1; 10 want_layout:1,
11 want_vpath:1;
11}; 12};
12 13
13extern struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx); 14extern struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx);
diff --git a/parsing.c b/parsing.c
index f3f3b15..f37c49d 100644
--- a/parsing.c
+++ b/parsing.c
@@ -190,6 +190,10 @@ struct commitinfo *cgit_parse_commit(struct commit *commit)
190 ret->subject = xstrdup(p); 190 ret->subject = xstrdup(p);
191 191
192 if (ret->msg_encoding) { 192 if (ret->msg_encoding) {
193 reencode(&ret->author, PAGE_ENCODING, ret->msg_encoding);
194 reencode(&ret->author_email, PAGE_ENCODING, ret->msg_encoding);
195 reencode(&ret->committer, PAGE_ENCODING, ret->msg_encoding);
196 reencode(&ret->committer_email, PAGE_ENCODING, ret->msg_encoding);
193 reencode(&ret->subject, PAGE_ENCODING, ret->msg_encoding); 197 reencode(&ret->subject, PAGE_ENCODING, ret->msg_encoding);
194 reencode(&ret->msg, PAGE_ENCODING, ret->msg_encoding); 198 reencode(&ret->msg, PAGE_ENCODING, ret->msg_encoding);
195 } 199 }
diff --git a/scan-tree.c b/scan-tree.c
index dbca797..1e18f3c 100644
--- a/scan-tree.c
+++ b/scan-tree.c
@@ -56,6 +56,8 @@ static void add_repo(const char *base, const char *path, repo_config_fn fn)
56 path, strerror(errno), errno); 56 path, strerror(errno), errno);
57 return; 57 return;
58 } 58 }
59 if (!stat(fmt("%s/noweb", path), &st))
60 return;
59 if ((pwd = getpwuid(st.st_uid)) == NULL) { 61 if ((pwd = getpwuid(st.st_uid)) == NULL) {
60 fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n", 62 fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n",
61 path, strerror(errno), errno); 63 path, strerror(errno), errno);
diff --git a/shared.c b/shared.c
index 76d26dd..9f7d6a5 100644
--- a/shared.c
+++ b/shared.c
@@ -10,7 +10,6 @@
10 10
11struct cgit_repolist cgit_repolist; 11struct cgit_repolist cgit_repolist;
12struct cgit_context ctx; 12struct cgit_context ctx;
13int cgit_cmd;
14 13
15int chk_zero(int result, char *msg) 14int chk_zero(int result, char *msg)
16{ 15{
@@ -60,6 +59,7 @@ struct cgit_repo *cgit_add_repo(const char *url)
60 ret->enable_log_filecount = ctx.cfg.enable_log_filecount; 59 ret->enable_log_filecount = ctx.cfg.enable_log_filecount;
61 ret->enable_log_linecount = ctx.cfg.enable_log_linecount; 60 ret->enable_log_linecount = ctx.cfg.enable_log_linecount;
62 ret->enable_remote_branches = ctx.cfg.enable_remote_branches; 61 ret->enable_remote_branches = ctx.cfg.enable_remote_branches;
62 ret->enable_subject_links = ctx.cfg.enable_subject_links;
63 ret->max_stats = ctx.cfg.max_stats; 63 ret->max_stats = ctx.cfg.max_stats;
64 ret->module_link = ctx.cfg.module_link; 64 ret->module_link = ctx.cfg.module_link;
65 ret->readme = NULL; 65 ret->readme = NULL;
@@ -263,7 +263,8 @@ int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf)
263 263
264int cgit_diff_files(const unsigned char *old_sha1, 264int cgit_diff_files(const unsigned char *old_sha1,
265 const unsigned char *new_sha1, unsigned long *old_size, 265 const unsigned char *new_sha1, unsigned long *old_size,
266 unsigned long *new_size, int *binary, linediff_fn fn) 266 unsigned long *new_size, int *binary, int context,
267 linediff_fn fn)
267{ 268{
268 mmfile_t file1, file2; 269 mmfile_t file1, file2;
269 xpparam_t diff_params; 270 xpparam_t diff_params;
@@ -279,6 +280,10 @@ int cgit_diff_files(const unsigned char *old_sha1,
279 if ((file1.ptr && buffer_is_binary(file1.ptr, file1.size)) || 280 if ((file1.ptr && buffer_is_binary(file1.ptr, file1.size)) ||
280 (file2.ptr && buffer_is_binary(file2.ptr, file2.size))) { 281 (file2.ptr && buffer_is_binary(file2.ptr, file2.size))) {
281 *binary = 1; 282 *binary = 1;
283 if (file1.size)
284 free(file1.ptr);
285 if (file2.size)
286 free(file2.ptr);
282 return 0; 287 return 0;
283 } 288 }
284 289
@@ -286,11 +291,15 @@ int cgit_diff_files(const unsigned char *old_sha1,
286 memset(&emit_params, 0, sizeof(emit_params)); 291 memset(&emit_params, 0, sizeof(emit_params));
287 memset(&emit_cb, 0, sizeof(emit_cb)); 292 memset(&emit_cb, 0, sizeof(emit_cb));
288 diff_params.flags = XDF_NEED_MINIMAL; 293 diff_params.flags = XDF_NEED_MINIMAL;
289 emit_params.ctxlen = 3; 294 emit_params.ctxlen = context > 0 ? context : 3;
290 emit_params.flags = XDL_EMIT_FUNCNAMES; 295 emit_params.flags = XDL_EMIT_FUNCNAMES;
291 emit_cb.outf = filediff_cb; 296 emit_cb.outf = filediff_cb;
292 emit_cb.priv = fn; 297 emit_cb.priv = fn;
293 xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); 298 xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb);
299 if (file1.size)
300 free(file1.ptr);
301 if (file2.size)
302 free(file2.ptr);
294 return 0; 303 return 0;
295} 304}
296 305
diff --git a/ui-atom.c b/ui-atom.c
index 808b2d0..9f049ae 100644
--- a/ui-atom.c
+++ b/ui-atom.c
@@ -85,7 +85,9 @@ void cgit_print_atom(char *tip, char *path, int max_count)
85 struct rev_info rev; 85 struct rev_info rev;
86 int argc = 2; 86 int argc = 2;
87 87
88 if (!tip) 88 if (ctx.qry.show_all)
89 argv[1] = "--all";
90 else if (!tip)
89 argv[1] = ctx.qry.head; 91 argv[1] = ctx.qry.head;
90 92
91 if (path) { 93 if (path) {
diff --git a/ui-commit.c b/ui-commit.c
index b5e3c01..a11bc5f 100644
--- a/ui-commit.c
+++ b/ui-commit.c
@@ -12,13 +12,13 @@
12#include "ui-diff.h" 12#include "ui-diff.h"
13#include "ui-log.h" 13#include "ui-log.h"
14 14
15void cgit_print_commit(char *hex) 15void cgit_print_commit(char *hex, const char *prefix)
16{ 16{
17 struct commit *commit, *parent; 17 struct commit *commit, *parent;
18 struct commitinfo *info; 18 struct commitinfo *info, *parent_info;
19 struct commit_list *p; 19 struct commit_list *p;
20 unsigned char sha1[20]; 20 unsigned char sha1[20];
21 char *tmp; 21 char *tmp, *tmp2;
22 int parents = 0; 22 int parents = 0;
23 23
24 if (!hex) 24 if (!hex)
@@ -58,19 +58,23 @@ void cgit_print_commit(char *hex)
58 html("</td></tr>\n"); 58 html("</td></tr>\n");
59 html("<tr><th>commit</th><td colspan='2' class='sha1'>"); 59 html("<tr><th>commit</th><td colspan='2' class='sha1'>");
60 tmp = sha1_to_hex(commit->object.sha1); 60 tmp = sha1_to_hex(commit->object.sha1);
61 cgit_commit_link(tmp, NULL, NULL, ctx.qry.head, tmp, 0); 61 cgit_commit_link(tmp, NULL, NULL, ctx.qry.head, tmp, prefix, 0);
62 html(" ("); 62 html(" (");
63 cgit_patch_link("patch", NULL, NULL, NULL, tmp); 63 cgit_patch_link("patch", NULL, NULL, NULL, tmp, prefix);
64 html(") ("); 64 html(") (");
65 if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff)) 65 if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff))
66 cgit_commit_link("unidiff", NULL, NULL, ctx.qry.head, tmp, 1); 66 cgit_commit_link("unidiff", NULL, NULL, ctx.qry.head, tmp, prefix, 1);
67 else 67 else
68 cgit_commit_link("side-by-side diff", NULL, NULL, ctx.qry.head, tmp, 1); 68 cgit_commit_link("side-by-side diff", NULL, NULL, ctx.qry.head, tmp, prefix, 1);
69 html(")</td></tr>\n"); 69 html(")</td></tr>\n");
70 html("<tr><th>tree</th><td colspan='2' class='sha1'>"); 70 html("<tr><th>tree</th><td colspan='2' class='sha1'>");
71 tmp = xstrdup(hex); 71 tmp = xstrdup(hex);
72 cgit_tree_link(sha1_to_hex(commit->tree->object.sha1), NULL, NULL, 72 cgit_tree_link(sha1_to_hex(commit->tree->object.sha1), NULL, NULL,
73 ctx.qry.head, tmp, NULL); 73 ctx.qry.head, tmp, NULL);
74 if (prefix) {
75 html(" /");
76 cgit_tree_link(prefix, NULL, NULL, ctx.qry.head, tmp, prefix);
77 }
74 html("</td></tr>\n"); 78 html("</td></tr>\n");
75 for (p = commit->parents; p ; p = p->next) { 79 for (p = commit->parents; p ; p = p->next) {
76 parent = lookup_commit_reference(p->item->object.sha1); 80 parent = lookup_commit_reference(p->item->object.sha1);
@@ -82,11 +86,15 @@ void cgit_print_commit(char *hex)
82 } 86 }
83 html("<tr><th>parent</th>" 87 html("<tr><th>parent</th>"
84 "<td colspan='2' class='sha1'>"); 88 "<td colspan='2' class='sha1'>");
85 cgit_commit_link(sha1_to_hex(p->item->object.sha1), NULL, NULL, 89 tmp = tmp2 = sha1_to_hex(p->item->object.sha1);
86 ctx.qry.head, sha1_to_hex(p->item->object.sha1), 0); 90 if (ctx.repo->enable_subject_links) {
91 parent_info = cgit_parse_commit(parent);
92 tmp2 = parent_info->subject;
93 }
94 cgit_commit_link(tmp2, NULL, NULL, ctx.qry.head, tmp, prefix, 0);
87 html(" ("); 95 html(" (");
88 cgit_diff_link("diff", NULL, NULL, ctx.qry.head, hex, 96 cgit_diff_link("diff", NULL, NULL, ctx.qry.head, hex,
89 sha1_to_hex(p->item->object.sha1), NULL, 0); 97 sha1_to_hex(p->item->object.sha1), prefix, 0);
90 html(")</td></tr>"); 98 html(")</td></tr>");
91 parents++; 99 parents++;
92 } 100 }
@@ -117,7 +125,7 @@ void cgit_print_commit(char *hex)
117 tmp = sha1_to_hex(commit->parents->item->object.sha1); 125 tmp = sha1_to_hex(commit->parents->item->object.sha1);
118 else 126 else
119 tmp = NULL; 127 tmp = NULL;
120 cgit_print_diff(ctx.qry.sha1, tmp, NULL); 128 cgit_print_diff(ctx.qry.sha1, tmp, prefix);
121 } 129 }
122 cgit_free_commitinfo(info); 130 cgit_free_commitinfo(info);
123} 131}
diff --git a/ui-commit.h b/ui-commit.h
index 40bcb31..8198b4b 100644
--- a/ui-commit.h
+++ b/ui-commit.h
@@ -1,6 +1,6 @@
1#ifndef UI_COMMIT_H 1#ifndef UI_COMMIT_H
2#define UI_COMMIT_H 2#define UI_COMMIT_H
3 3
4extern void cgit_print_commit(char *hex); 4extern void cgit_print_commit(char *hex, const char *prefix);
5 5
6#endif /* UI_COMMIT_H */ 6#endif /* UI_COMMIT_H */
diff --git a/ui-diff.c b/ui-diff.c
index a92a768..e0a72f7 100644
--- a/ui-diff.c
+++ b/ui-diff.c
@@ -127,7 +127,7 @@ static void inspect_filepair(struct diff_filepair *pair)
127 lines_added = 0; 127 lines_added = 0;
128 lines_removed = 0; 128 lines_removed = 0;
129 cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, &new_size, 129 cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, &new_size,
130 &binary, count_diff_lines); 130 &binary, 0, count_diff_lines);
131 if (files >= slots) { 131 if (files >= slots) {
132 if (slots == 0) 132 if (slots == 0)
133 slots = 4; 133 slots = 4;
@@ -154,17 +154,27 @@ static void inspect_filepair(struct diff_filepair *pair)
154} 154}
155 155
156void cgit_print_diffstat(const unsigned char *old_sha1, 156void cgit_print_diffstat(const unsigned char *old_sha1,
157 const unsigned char *new_sha1) 157 const unsigned char *new_sha1, const char *prefix)
158{ 158{
159 int i; 159 int i, save_context = ctx.qry.context;
160 160
161 html("<div class='diffstat-header'>"); 161 html("<div class='diffstat-header'>");
162 cgit_diff_link("Diffstat", NULL, NULL, ctx.qry.head, ctx.qry.sha1, 162 cgit_diff_link("Diffstat", NULL, NULL, ctx.qry.head, ctx.qry.sha1,
163 ctx.qry.sha2, NULL, 0); 163 ctx.qry.sha2, NULL, 0);
164 if (prefix)
165 htmlf(" (limited to '%s')", prefix);
166 html(" (");
167 ctx.qry.context = (save_context > 0 ? save_context : 3) << 1;
168 cgit_self_link("more", NULL, NULL, &ctx);
169 html("/");
170 ctx.qry.context = (save_context > 3 ? save_context : 3) >> 1;
171 cgit_self_link("less", NULL, NULL, &ctx);
172 ctx.qry.context = save_context;
173 html(" context)");
164 html("</div>"); 174 html("</div>");
165 html("<table summary='diffstat' class='diffstat'>"); 175 html("<table summary='diffstat' class='diffstat'>");
166 max_changes = 0; 176 max_changes = 0;
167 cgit_diff_tree(old_sha1, new_sha1, inspect_filepair, NULL); 177 cgit_diff_tree(old_sha1, new_sha1, inspect_filepair, prefix);
168 for(i = 0; i<files; i++) 178 for(i = 0; i<files; i++)
169 print_fileinfo(&items[i]); 179 print_fileinfo(&items[i]);
170 html("</table>"); 180 html("</table>");
@@ -286,7 +296,7 @@ static void filepair_cb(struct diff_filepair *pair)
286 return; 296 return;
287 } 297 }
288 if (cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, 298 if (cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size,
289 &new_size, &binary, print_line_fn)) 299 &new_size, &binary, ctx.qry.context, print_line_fn))
290 cgit_print_error("Error running diff"); 300 cgit_print_error("Error running diff");
291 if (binary) { 301 if (binary) {
292 if (use_ssdiff) 302 if (use_ssdiff)
@@ -338,7 +348,7 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefi
338 use_ssdiff = 1; 348 use_ssdiff = 1;
339 349
340 print_ssdiff_link(); 350 print_ssdiff_link();
341 cgit_print_diffstat(old_rev_sha1, new_rev_sha1); 351 cgit_print_diffstat(old_rev_sha1, new_rev_sha1, prefix);
342 352
343 if (use_ssdiff) { 353 if (use_ssdiff) {
344 html("<table summary='ssdiff' class='ssdiff'>"); 354 html("<table summary='ssdiff' class='ssdiff'>");
diff --git a/ui-log.c b/ui-log.c
index 0947604..33ec8a9 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -33,7 +33,7 @@ void inspect_files(struct diff_filepair *pair)
33 files++; 33 files++;
34 if (ctx.repo->enable_log_linecount) 34 if (ctx.repo->enable_log_linecount)
35 cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, 35 cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size,
36 &new_size, &binary, count_lines); 36 &new_size, &binary, 0, count_lines);
37} 37}
38 38
39void show_commit_decorations(struct commit *commit) 39void show_commit_decorations(struct commit *commit)
@@ -46,8 +46,9 @@ void show_commit_decorations(struct commit *commit)
46 while (deco) { 46 while (deco) {
47 if (!prefixcmp(deco->name, "refs/heads/")) { 47 if (!prefixcmp(deco->name, "refs/heads/")) {
48 strncpy(buf, deco->name + 11, sizeof(buf) - 1); 48 strncpy(buf, deco->name + 11, sizeof(buf) - 1);
49 cgit_log_link(buf, NULL, "branch-deco", buf, NULL, NULL, 49 cgit_log_link(buf, NULL, "branch-deco", buf, NULL,
50 0, NULL, NULL, ctx.qry.showmsg); 50 ctx.qry.vpath, 0, NULL, NULL,
51 ctx.qry.showmsg);
51 } 52 }
52 else if (!prefixcmp(deco->name, "tag: refs/tags/")) { 53 else if (!prefixcmp(deco->name, "tag: refs/tags/")) {
53 strncpy(buf, deco->name + 15, sizeof(buf) - 1); 54 strncpy(buf, deco->name + 15, sizeof(buf) - 1);
@@ -60,13 +61,15 @@ void show_commit_decorations(struct commit *commit)
60 else if (!prefixcmp(deco->name, "refs/remotes/")) { 61 else if (!prefixcmp(deco->name, "refs/remotes/")) {
61 strncpy(buf, deco->name + 13, sizeof(buf) - 1); 62 strncpy(buf, deco->name + 13, sizeof(buf) - 1);
62 cgit_log_link(buf, NULL, "remote-deco", NULL, 63 cgit_log_link(buf, NULL, "remote-deco", NULL,
63 sha1_to_hex(commit->object.sha1), NULL, 64 sha1_to_hex(commit->object.sha1),
64 0, NULL, NULL, ctx.qry.showmsg); 65 ctx.qry.vpath, 0, NULL, NULL,
66 ctx.qry.showmsg);
65 } 67 }
66 else { 68 else {
67 strncpy(buf, deco->name, sizeof(buf) - 1); 69 strncpy(buf, deco->name, sizeof(buf) - 1);
68 cgit_commit_link(buf, NULL, "deco", ctx.qry.head, 70 cgit_commit_link(buf, NULL, "deco", ctx.qry.head,
69 sha1_to_hex(commit->object.sha1), 0); 71 sha1_to_hex(commit->object.sha1),
72 ctx.qry.vpath, 0);
70 } 73 }
71 deco = deco->next; 74 deco = deco->next;
72 } 75 }
@@ -82,14 +85,14 @@ void print_commit(struct commit *commit)
82 htmlf("<tr%s><td>", 85 htmlf("<tr%s><td>",
83 ctx.qry.showmsg ? " class='logheader'" : ""); 86 ctx.qry.showmsg ? " class='logheader'" : "");
84 tmp = fmt("id=%s", sha1_to_hex(commit->object.sha1)); 87 tmp = fmt("id=%s", sha1_to_hex(commit->object.sha1));
85 tmp = cgit_pageurl(ctx.repo->url, "commit", tmp); 88 tmp = cgit_fileurl(ctx.repo->url, "commit", ctx.qry.vpath, tmp);
86 html_link_open(tmp, NULL, NULL); 89 html_link_open(tmp, NULL, NULL);
87 cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE); 90 cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE);
88 html_link_close(); 91 html_link_close();
89 htmlf("</td><td%s>", 92 htmlf("</td><td%s>",
90 ctx.qry.showmsg ? " class='logsubject'" : ""); 93 ctx.qry.showmsg ? " class='logsubject'" : "");
91 cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head, 94 cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head,
92 sha1_to_hex(commit->object.sha1), 0); 95 sha1_to_hex(commit->object.sha1), ctx.qry.vpath, 0);
93 show_commit_decorations(commit); 96 show_commit_decorations(commit);
94 html("</td><td>"); 97 html("</td><td>");
95 html_txt(info->author); 98 html_txt(info->author);
@@ -146,10 +149,13 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern
146 149
147 argv[1] = disambiguate_ref(tip); 150 argv[1] = disambiguate_ref(tip);
148 151
149 if (grep && pattern && (!strcmp(grep, "grep") || 152 if (grep && pattern) {
150 !strcmp(grep, "author") || 153 if (!strcmp(grep, "grep") || !strcmp(grep, "author") ||
151 !strcmp(grep, "committer"))) 154 !strcmp(grep, "committer"))
152 argv[argc++] = fmt("--%s=%s", grep, pattern); 155 argv[argc++] = fmt("--%s=%s", grep, pattern);
156 if (!strcmp(grep, "range"))
157 argv[1] = pattern;
158 }
153 159
154 if (path) { 160 if (path) {
155 argv[argc++] = "--"; 161 argv[argc++] = "--";
@@ -176,7 +182,7 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern
176 html(" ("); 182 html(" (");
177 cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL, 183 cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL,
178 NULL, ctx.qry.head, ctx.qry.sha1, 184 NULL, ctx.qry.head, ctx.qry.sha1,
179 ctx.qry.path, ctx.qry.ofs, ctx.qry.grep, 185 ctx.qry.vpath, ctx.qry.ofs, ctx.qry.grep,
180 ctx.qry.search, ctx.qry.showmsg ? 0 : 1); 186 ctx.qry.search, ctx.qry.showmsg ? 0 : 1);
181 html(")"); 187 html(")");
182 } 188 }
@@ -213,22 +219,22 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern
213 columns); 219 columns);
214 if (ofs > 0) { 220 if (ofs > 0) {
215 cgit_log_link("[prev]", NULL, NULL, ctx.qry.head, 221 cgit_log_link("[prev]", NULL, NULL, ctx.qry.head,
216 ctx.qry.sha1, ctx.qry.path, 222 ctx.qry.sha1, ctx.qry.vpath,
217 ofs - cnt, ctx.qry.grep, 223 ofs - cnt, ctx.qry.grep,
218 ctx.qry.search, ctx.qry.showmsg); 224 ctx.qry.search, ctx.qry.showmsg);
219 html("&nbsp;"); 225 html("&nbsp;");
220 } 226 }
221 if ((commit = get_revision(&rev)) != NULL) { 227 if ((commit = get_revision(&rev)) != NULL) {
222 cgit_log_link("[next]", NULL, NULL, ctx.qry.head, 228 cgit_log_link("[next]", NULL, NULL, ctx.qry.head,
223 ctx.qry.sha1, ctx.qry.path, 229 ctx.qry.sha1, ctx.qry.vpath,
224 ofs + cnt, ctx.qry.grep, 230 ofs + cnt, ctx.qry.grep,
225 ctx.qry.search, ctx.qry.showmsg); 231 ctx.qry.search, ctx.qry.showmsg);
226 } 232 }
227 html("</div>"); 233 html("</div>");
228 } else if ((commit = get_revision(&rev)) != NULL) { 234 } else if ((commit = get_revision(&rev)) != NULL) {
229 html("<tr class='nohover'><td colspan='3'>"); 235 html("<tr class='nohover'><td colspan='3'>");
230 cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL, NULL, 0, 236 cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL,
231 NULL, NULL, ctx.qry.showmsg); 237 ctx.qry.vpath, 0, NULL, NULL, ctx.qry.showmsg);
232 html("</td></tr>\n"); 238 html("</td></tr>\n");
233 } 239 }
234} 240}
diff --git a/ui-patch.c b/ui-patch.c
index 2a8f7a5..d13104c 100644
--- a/ui-patch.c
+++ b/ui-patch.c
@@ -71,13 +71,13 @@ static void filepair_cb(struct diff_filepair *pair)
71 return; 71 return;
72 } 72 }
73 if (cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, 73 if (cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size,
74 &new_size, &binary, print_line)) 74 &new_size, &binary, 0, print_line))
75 html("Error running diff"); 75 html("Error running diff");
76 if (binary) 76 if (binary)
77 html("Binary files differ\n"); 77 html("Binary files differ\n");
78} 78}
79 79
80void cgit_print_patch(char *hex) 80void cgit_print_patch(char *hex, const char *prefix)
81{ 81{
82 struct commit *commit; 82 struct commit *commit;
83 struct commitinfo *info; 83 struct commitinfo *info;
@@ -122,7 +122,9 @@ void cgit_print_patch(char *hex)
122 html("\n"); 122 html("\n");
123 } 123 }
124 html("---\n"); 124 html("---\n");
125 cgit_diff_tree(old_sha1, sha1, filepair_cb, NULL); 125 if (prefix)
126 htmlf("(limited to '%s')\n\n", prefix);
127 cgit_diff_tree(old_sha1, sha1, filepair_