summaryrefslogtreecommitdiffabout
path: root/ui-log.c
authorJohan Herland <johan@herland.net>2010-09-30 18:15:14 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2010-11-09 15:37:39 (UTC)
commit1415f3f3e017d0123e850707c55cb7e5e5887406 (patch) (unidiff)
tree9036ea6ce534e40ff35394359332a9a628276c0f /ui-log.c
parente0c6f23789e4893781bcd5af2281d468991ccf3a (diff)
downloadcgit-1415f3f3e017d0123e850707c55cb7e5e5887406.zip
cgit-1415f3f3e017d0123e850707c55cb7e5e5887406.tar.gz
cgit-1415f3f3e017d0123e850707c55cb7e5e5887406.tar.bz2
ui-log: Fix filecount/linecount when path limit is in effect
When using ui-log with path limits, the listing of commits enables parent rewriting in Git's internal log machinery. This did not work well together with cgit_diff_commit() which is used to generate the filecount and linecount numbers for each commit in the log view. cgit_diff_commit() would operate without any path limits, and would therefore process the full diff between the commits shown (which, because of parent rewriting, is not the same as processing the diff for the commit itself). Additionally, the bottom commit in the log view would (again, because of parent rewriting) have zero parents, causing us to process the entire diff between the empty tree and that commit. Since path limits were not in effect, this would (in large projects) reports thousands of files and millions of lines changed in that bottom commit. This patch fixes the issue by applying the same path limit to cgit_diff_commit() as is applied to the rest of the log view. The result is that the filecount/linecount now only reflects the diff as it pertains to the given path limit. Signed-off-by: Johan Herland <johan@herland.net> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'ui-log.c') (more/less context) (ignore whitespace changes)
-rw-r--r--ui-log.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/ui-log.c b/ui-log.c
index 41b5225..bc0c02c 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -1,232 +1,232 @@
1/* ui-log.c: functions for log output 1/* ui-log.c: functions for log output
2 * 2 *
3 * Copyright (C) 2006 Lars Hjemli 3 * Copyright (C) 2006 Lars Hjemli
4 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
10#include "html.h" 10#include "html.h"
11#include "ui-shared.h" 11#include "ui-shared.h"
12 12
13int files, add_lines, rem_lines; 13int files, add_lines, rem_lines;
14 14
15void count_lines(char *line, int size) 15void count_lines(char *line, int size)
16{ 16{
17 if (size <= 0) 17 if (size <= 0)
18 return; 18 return;
19 19
20 if (line[0] == '+') 20 if (line[0] == '+')
21 add_lines++; 21 add_lines++;
22 22
23 else if (line[0] == '-') 23 else if (line[0] == '-')
24 rem_lines++; 24 rem_lines++;
25} 25}
26 26
27void inspect_files(struct diff_filepair *pair) 27void inspect_files(struct diff_filepair *pair)
28{ 28{
29 unsigned long old_size = 0; 29 unsigned long old_size = 0;
30 unsigned long new_size = 0; 30 unsigned long new_size = 0;
31 int binary = 0; 31 int binary = 0;
32 32
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, 0, ctx.qry.ignorews, 36 &new_size, &binary, 0, ctx.qry.ignorews,
37 count_lines); 37 count_lines);
38} 38}
39 39
40void show_commit_decorations(struct commit *commit) 40void show_commit_decorations(struct commit *commit)
41{ 41{
42 struct name_decoration *deco; 42 struct name_decoration *deco;
43 static char buf[1024]; 43 static char buf[1024];
44 44
45 buf[sizeof(buf) - 1] = 0; 45 buf[sizeof(buf) - 1] = 0;
46 deco = lookup_decoration(&name_decoration, &commit->object); 46 deco = lookup_decoration(&name_decoration, &commit->object);
47 while (deco) { 47 while (deco) {
48 if (!prefixcmp(deco->name, "refs/heads/")) { 48 if (!prefixcmp(deco->name, "refs/heads/")) {
49 strncpy(buf, deco->name + 11, sizeof(buf) - 1); 49 strncpy(buf, deco->name + 11, sizeof(buf) - 1);
50 cgit_log_link(buf, NULL, "branch-deco", buf, NULL, 50 cgit_log_link(buf, NULL, "branch-deco", buf, NULL,
51 ctx.qry.vpath, 0, NULL, NULL, 51 ctx.qry.vpath, 0, NULL, NULL,
52 ctx.qry.showmsg); 52 ctx.qry.showmsg);
53 } 53 }
54 else if (!prefixcmp(deco->name, "tag: refs/tags/")) { 54 else if (!prefixcmp(deco->name, "tag: refs/tags/")) {
55 strncpy(buf, deco->name + 15, sizeof(buf) - 1); 55 strncpy(buf, deco->name + 15, sizeof(buf) - 1);
56 cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf); 56 cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf);
57 } 57 }
58 else if (!prefixcmp(deco->name, "refs/tags/")) { 58 else if (!prefixcmp(deco->name, "refs/tags/")) {
59 strncpy(buf, deco->name + 10, sizeof(buf) - 1); 59 strncpy(buf, deco->name + 10, sizeof(buf) - 1);
60 cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf); 60 cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf);
61 } 61 }
62 else if (!prefixcmp(deco->name, "refs/remotes/")) { 62 else if (!prefixcmp(deco->name, "refs/remotes/")) {
63 strncpy(buf, deco->name + 13, sizeof(buf) - 1); 63 strncpy(buf, deco->name + 13, sizeof(buf) - 1);
64 cgit_log_link(buf, NULL, "remote-deco", NULL, 64 cgit_log_link(buf, NULL, "remote-deco", NULL,
65 sha1_to_hex(commit->object.sha1), 65 sha1_to_hex(commit->object.sha1),
66 ctx.qry.vpath, 0, NULL, NULL, 66 ctx.qry.vpath, 0, NULL, NULL,
67 ctx.qry.showmsg); 67 ctx.qry.showmsg);
68 } 68 }
69 else { 69 else {
70 strncpy(buf, deco->name, sizeof(buf) - 1); 70 strncpy(buf, deco->name, sizeof(buf) - 1);
71 cgit_commit_link(buf, NULL, "deco", ctx.qry.head, 71 cgit_commit_link(buf, NULL, "deco", ctx.qry.head,
72 sha1_to_hex(commit->object.sha1), 72 sha1_to_hex(commit->object.sha1),
73 ctx.qry.vpath, 0); 73 ctx.qry.vpath, 0);
74 } 74 }
75 deco = deco->next; 75 deco = deco->next;
76 } 76 }
77} 77}
78 78
79void print_commit(struct commit *commit) 79void print_commit(struct commit *commit)
80{ 80{
81 struct commitinfo *info; 81 struct commitinfo *info;
82 char *tmp; 82 char *tmp;
83 int cols = 2; 83 int cols = 2;
84 84
85 info = cgit_parse_commit(commit); 85 info = cgit_parse_commit(commit);
86 htmlf("<tr%s><td>", 86 htmlf("<tr%s><td>",
87 ctx.qry.showmsg ? " class='logheader'" : ""); 87 ctx.qry.showmsg ? " class='logheader'" : "");
88 tmp = fmt("id=%s", sha1_to_hex(commit->object.sha1)); 88 tmp = fmt("id=%s", sha1_to_hex(commit->object.sha1));
89 tmp = cgit_fileurl(ctx.repo->url, "commit", ctx.qry.vpath, tmp); 89 tmp = cgit_fileurl(ctx.repo->url, "commit", ctx.qry.vpath, tmp);
90 html_link_open(tmp, NULL, NULL); 90 html_link_open(tmp, NULL, NULL);
91 cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE); 91 cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE);
92 html_link_close(); 92 html_link_close();
93 htmlf("</td><td%s>", 93 htmlf("</td><td%s>",
94 ctx.qry.showmsg ? " class='logsubject'" : ""); 94 ctx.qry.showmsg ? " class='logsubject'" : "");
95 cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head, 95 cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head,
96 sha1_to_hex(commit->object.sha1), ctx.qry.vpath, 0); 96 sha1_to_hex(commit->object.sha1), ctx.qry.vpath, 0);
97 show_commit_decorations(commit); 97 show_commit_decorations(commit);
98 html("</td><td>"); 98 html("</td><td>");
99 html_txt(info->author); 99 html_txt(info->author);
100 if (ctx.repo->enable_log_filecount) { 100 if (ctx.repo->enable_log_filecount) {
101 files = 0; 101 files = 0;
102 add_lines = 0; 102 add_lines = 0;
103 rem_lines = 0; 103 rem_lines = 0;
104 cgit_diff_commit(commit, inspect_files); 104 cgit_diff_commit(commit, inspect_files, ctx.qry.vpath);
105 html("</td><td>"); 105 html("</td><td>");
106 htmlf("%d", files); 106 htmlf("%d", files);
107 if (ctx.repo->enable_log_linecount) { 107 if (ctx.repo->enable_log_linecount) {
108 html("</td><td>"); 108 html("</td><td>");
109 htmlf("-%d/+%d", rem_lines, add_lines); 109 htmlf("-%d/+%d", rem_lines, add_lines);
110 } 110 }
111 } 111 }
112 html("</td></tr>\n"); 112 html("</td></tr>\n");
113 if (ctx.qry.showmsg) { 113 if (ctx.qry.showmsg) {
114 struct strbuf notes = STRBUF_INIT; 114 struct strbuf notes = STRBUF_INIT;
115 format_note(NULL, commit->object.sha1, &notes, PAGE_ENCODING, 0); 115 format_note(NULL, commit->object.sha1, &notes, PAGE_ENCODING, 0);
116 116
117 if (ctx.repo->enable_log_filecount) { 117 if (ctx.repo->enable_log_filecount) {
118 cols++; 118 cols++;
119 if (ctx.repo->enable_log_linecount) 119 if (ctx.repo->enable_log_linecount)
120 cols++; 120 cols++;
121 } 121 }
122 htmlf("<tr class='nohover'><td/><td colspan='%d' class='logmsg'>", 122 htmlf("<tr class='nohover'><td/><td colspan='%d' class='logmsg'>",
123 cols); 123 cols);
124 html_txt(info->msg); 124 html_txt(info->msg);
125 html("</td></tr>\n"); 125 html("</td></tr>\n");
126 if (notes.len != 0) { 126 if (notes.len != 0) {
127 html("<tr class='nohover'>"); 127 html("<tr class='nohover'>");
128 html("<td class='lognotes-label'>Notes:</td>"); 128 html("<td class='lognotes-label'>Notes:</td>");
129 htmlf("<td colspan='%d' class='lognotes'>", 129 htmlf("<td colspan='%d' class='lognotes'>",
130 cols); 130 cols);
131 html_txt(notes.buf); 131 html_txt(notes.buf);
132 html("</td></tr>\n"); 132 html("</td></tr>\n");
133 } 133 }
134 strbuf_release(&notes); 134 strbuf_release(&notes);
135 } 135 }
136 cgit_free_commitinfo(info); 136 cgit_free_commitinfo(info);
137} 137}
138 138
139static const char *disambiguate_ref(const char *ref) 139static const char *disambiguate_ref(const char *ref)
140{ 140{
141 unsigned char sha1[20]; 141 unsigned char sha1[20];
142 const char *longref; 142 const char *longref;
143 143
144 longref = fmt("refs/heads/%s", ref); 144 longref = fmt("refs/heads/%s", ref);
145 if (get_sha1(longref, sha1) == 0) 145 if (get_sha1(longref, sha1) == 0)
146 return longref; 146 return longref;
147 147
148 return ref; 148 return ref;
149} 149}
150 150
151void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern, 151void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern,
152 char *path, int pager) 152 char *path, int pager)
153{ 153{
154 struct rev_info rev; 154 struct rev_info rev;
155 struct commit *commit; 155 struct commit *commit;
156 const char *argv[] = {NULL, NULL, NULL, NULL, NULL}; 156 const char *argv[] = {NULL, NULL, NULL, NULL, NULL};
157 int argc = 2; 157 int argc = 2;
158 int i, columns = 3; 158 int i, columns = 3;
159 159
160 if (!tip) 160 if (!tip)
161 tip = ctx.qry.head; 161 tip = ctx.qry.head;
162 162
163 argv[1] = disambiguate_ref(tip); 163 argv[1] = disambiguate_ref(tip);
164 164
165 if (grep && pattern) { 165 if (grep && pattern) {
166 if (!strcmp(grep, "grep") || !strcmp(grep, "author") || 166 if (!strcmp(grep, "grep") || !strcmp(grep, "author") ||
167 !strcmp(grep, "committer")) 167 !strcmp(grep, "committer"))
168 argv[argc++] = fmt("--%s=%s", grep, pattern); 168 argv[argc++] = fmt("--%s=%s", grep, pattern);
169 if (!strcmp(grep, "range")) 169 if (!strcmp(grep, "range"))
170 argv[1] = pattern; 170 argv[1] = pattern;
171 } 171 }
172 172
173 if (path) { 173 if (path) {
174 argv[argc++] = "--"; 174 argv[argc++] = "--";
175 argv[argc++] = path; 175 argv[argc++] = path;
176 } 176 }
177 init_revisions(&rev, NULL); 177 init_revisions(&rev, NULL);
178 rev.abbrev = DEFAULT_ABBREV; 178 rev.abbrev = DEFAULT_ABBREV;
179 rev.commit_format = CMIT_FMT_DEFAULT; 179 rev.commit_format = CMIT_FMT_DEFAULT;
180 rev.verbose_header = 1; 180 rev.verbose_header = 1;
181 rev.show_root_diff = 0; 181 rev.show_root_diff = 0;
182 setup_revisions(argc, argv, &rev, NULL); 182 setup_revisions(argc, argv, &rev, NULL);
183 load_ref_decorations(DECORATE_FULL_REFS); 183 load_ref_decorations(DECORATE_FULL_REFS);
184 rev.show_decorations = 1; 184 rev.show_decorations = 1;
185 rev.grep_filter.regflags |= REG_ICASE; 185 rev.grep_filter.regflags |= REG_ICASE;
186 compile_grep_patterns(&rev.grep_filter); 186 compile_grep_patterns(&rev.grep_filter);
187 prepare_revision_walk(&rev); 187 prepare_revision_walk(&rev);
188 188
189 if (pager) 189 if (pager)
190 html("<table class='list nowrap'>"); 190 html("<table class='list nowrap'>");
191 191
192 html("<tr class='nohover'><th class='left'>Age</th>" 192 html("<tr class='nohover'><th class='left'>Age</th>"
193 "<th class='left'>Commit message"); 193 "<th class='left'>Commit message");
194 if (pager) { 194 if (pager) {
195 html(" ("); 195 html(" (");
196 cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL, 196 cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL,
197 NULL, ctx.qry.head, ctx.qry.sha1, 197 NULL, ctx.qry.head, ctx.qry.sha1,
198 ctx.qry.vpath, ctx.qry.ofs, ctx.qry.grep, 198 ctx.qry.vpath, ctx.qry.ofs, ctx.qry.grep,
199 ctx.qry.search, ctx.qry.showmsg ? 0 : 1); 199 ctx.qry.search, ctx.qry.showmsg ? 0 : 1);
200 html(")"); 200 html(")");
201 } 201 }
202 html("</th><th class='left'>Author</th>"); 202 html("</th><th class='left'>Author</th>");
203 if (ctx.repo->enable_log_filecount) { 203 if (ctx.repo->enable_log_filecount) {
204 html("<th class='left'>Files</th>"); 204 html("<th class='left'>Files</th>");
205 columns++; 205 columns++;
206 if (ctx.repo->enable_log_linecount) { 206 if (ctx.repo->enable_log_linecount) {
207 html("<th class='left'>Lines</th>"); 207 html("<th class='left'>Lines</th>");
208 columns++; 208 columns++;
209 } 209 }
210 } 210 }
211 html("</tr>\n"); 211 html("</tr>\n");
212 212
213 if (ofs<0) 213 if (ofs<0)
214 ofs = 0; 214 ofs = 0;
215 215
216 for (i = 0; i < ofs && (commit = get_revision(&rev)) != NULL; i++) { 216 for (i = 0; i < ofs && (commit = get_revision(&rev)) != NULL; i++) {
217 free(commit->buffer); 217 free(commit->buffer);
218 commit->buffer = NULL; 218 commit->buffer = NULL;
219 free_commit_list(commit->parents); 219 free_commit_list(commit->parents);
220 commit->parents = NULL; 220 commit->parents = NULL;
221 } 221 }
222 222
223 for (i = 0; i < cnt && (commit = get_revision(&rev)) != NULL; i++) { 223 for (i = 0; i < cnt && (commit = get_revision(&rev)) != NULL; i++) {
224 print_commit(commit); 224 print_commit(commit);
225 free(commit->buffer); 225 free(commit->buffer);
226 commit->buffer = NULL; 226 commit->buffer = NULL;
227 free_commit_list(commit->parents); 227 free_commit_list(commit->parents);
228 commit->parents = NULL; 228 commit->parents = NULL;
229 } 229 }
230 if (pager) { 230 if (pager) {
231 html("</table><div class='pager'>"); 231 html("</table><div class='pager'>");
232 if (ofs > 0) { 232 if (ofs > 0) {