author | Mark Lodato <lodatom@gmail.com> | 2010-09-04 15:30:18 (UTC) |
---|---|---|
committer | Mark Lodato <lodatom@gmail.com> | 2010-09-04 15:35:38 (UTC) |
commit | e4ddc8f72b5a7d8c55a6c2042c7b7f945ba4b1a2 (patch) (unidiff) | |
tree | 2ade0bb45e15ad5466ca4d3433201477f0c9214e | |
parent | a4c58d92bfee0cf2e35ab1c5e828a6d790108a69 (diff) | |
download | cgit-e4ddc8f72b5a7d8c55a6c2042c7b7f945ba4b1a2.zip cgit-e4ddc8f72b5a7d8c55a6c2042c7b7f945ba4b1a2.tar.gz cgit-e4ddc8f72b5a7d8c55a6c2042c7b7f945ba4b1a2.tar.bz2 |
fix errors in printf-style format strings
There were many places where the arguments to a printf-like function did
not match the format string. Mostly, these were a missing 'l' flag, but
there were three exceptions:
- In ui-stats.c, a size_t argument must be printed. C99 has the "%zu"
flag for this purpose, but not all compilers support this. Therefore,
we mimic what git does - use a NO_C99_FORMAT Makefile variable.
- In ui-stats.c, cgit_print_error() was called with a pointer instead of
a character.
- In ui-log.c, the "columns" argument was never used.
Signed-off-by: Mark Lodato <lodatom@gmail.com>
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | cgit.c | 2 | ||||
-rw-r--r-- | ui-diff.c | 2 | ||||
-rw-r--r-- | ui-log.c | 3 | ||||
-rw-r--r-- | ui-stats.c | 18 | ||||
-rw-r--r-- | ui-tree.c | 4 |
6 files changed, 25 insertions, 12 deletions
@@ -1,42 +1,47 @@ | |||
1 | CGIT_VERSION = v0.8.3.3 | 1 | CGIT_VERSION = v0.8.3.3 |
2 | CGIT_SCRIPT_NAME = cgit.cgi | 2 | CGIT_SCRIPT_NAME = cgit.cgi |
3 | CGIT_SCRIPT_PATH = /var/www/htdocs/cgit | 3 | CGIT_SCRIPT_PATH = /var/www/htdocs/cgit |
4 | CGIT_DATA_PATH = $(CGIT_SCRIPT_PATH) | 4 | CGIT_DATA_PATH = $(CGIT_SCRIPT_PATH) |
5 | CGIT_CONFIG = /etc/cgitrc | 5 | CGIT_CONFIG = /etc/cgitrc |
6 | CACHE_ROOT = /var/cache/cgit | 6 | CACHE_ROOT = /var/cache/cgit |
7 | SHA1_HEADER = <openssl/sha.h> | 7 | SHA1_HEADER = <openssl/sha.h> |
8 | GIT_VER = 1.7.2.2 | 8 | GIT_VER = 1.7.2.2 |
9 | GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2 | 9 | GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2 |
10 | INSTALL = install | 10 | INSTALL = install |
11 | 11 | ||
12 | # Define NO_STRCASESTR if you don't have strcasestr. | 12 | # Define NO_STRCASESTR if you don't have strcasestr. |
13 | # | 13 | # |
14 | # Define NO_OPENSSL to disable linking with OpenSSL and use bundled SHA1 | 14 | # Define NO_OPENSSL to disable linking with OpenSSL and use bundled SHA1 |
15 | # implementation (slower). | 15 | # implementation (slower). |
16 | # | 16 | # |
17 | # Define NEEDS_LIBICONV if linking with libc is not enough (eg. Darwin). | 17 | # Define NEEDS_LIBICONV if linking with libc is not enough (eg. Darwin). |
18 | # | 18 | # |
19 | # Define NO_C99_FORMAT if your formatted IO functions (printf/scanf et.al.) | ||
20 | # do not support the 'size specifiers' introduced by C99, namely ll, hh, | ||
21 | # j, z, t. (representing long long int, char, intmax_t, size_t, ptrdiff_t). | ||
22 | # some C compilers supported these specifiers prior to C99 as an extension. | ||
23 | # | ||
19 | 24 | ||
20 | #-include config.mak | 25 | #-include config.mak |
21 | 26 | ||
22 | # | 27 | # |
23 | # Platform specific tweaks | 28 | # Platform specific tweaks |
24 | # | 29 | # |
25 | 30 | ||
26 | uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') | 31 | uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') |
27 | uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not') | 32 | uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not') |
28 | uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not') | 33 | uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not') |
29 | 34 | ||
30 | ifeq ($(uname_O),Cygwin) | 35 | ifeq ($(uname_O),Cygwin) |
31 | NO_STRCASESTR = YesPlease | 36 | NO_STRCASESTR = YesPlease |
32 | NEEDS_LIBICONV = YesPlease | 37 | NEEDS_LIBICONV = YesPlease |
33 | endif | 38 | endif |
34 | 39 | ||
35 | # | 40 | # |
36 | # Let the user override the above settings. | 41 | # Let the user override the above settings. |
37 | # | 42 | # |
38 | -include cgit.conf | 43 | -include cgit.conf |
39 | 44 | ||
40 | # | 45 | # |
41 | # Define a way to invoke make in subdirs quietly, shamelessly ripped | 46 | # Define a way to invoke make in subdirs quietly, shamelessly ripped |
42 | # from git.git | 47 | # from git.git |
@@ -106,48 +111,51 @@ endif | |||
106 | 111 | ||
107 | .PHONY: all libgit test install uninstall clean force-version get-git \ | 112 | .PHONY: all libgit test install uninstall clean force-version get-git \ |
108 | doc man-doc html-doc clean-doc | 113 | doc man-doc html-doc clean-doc |
109 | 114 | ||
110 | all: cgit | 115 | all: cgit |
111 | 116 | ||
112 | VERSION: force-version | 117 | VERSION: force-version |
113 | @./gen-version.sh "$(CGIT_VERSION)" | 118 | @./gen-version.sh "$(CGIT_VERSION)" |
114 | -include VERSION | 119 | -include VERSION |
115 | 120 | ||
116 | 121 | ||
117 | CFLAGS += -g -Wall -Igit | 122 | CFLAGS += -g -Wall -Igit |
118 | CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)' | 123 | CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)' |
119 | CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"' | 124 | CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"' |
120 | CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"' | 125 | CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"' |
121 | CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"' | 126 | CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"' |
122 | CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"' | 127 | CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"' |
123 | 128 | ||
124 | ifdef NO_ICONV | 129 | ifdef NO_ICONV |
125 | CFLAGS += -DNO_ICONV | 130 | CFLAGS += -DNO_ICONV |
126 | endif | 131 | endif |
127 | ifdef NO_STRCASESTR | 132 | ifdef NO_STRCASESTR |
128 | CFLAGS += -DNO_STRCASESTR | 133 | CFLAGS += -DNO_STRCASESTR |
129 | endif | 134 | endif |
135 | ifdef NO_C99_FORMAT | ||
136 | CFLAGS += -DNO_C99_FORMAT | ||
137 | endif | ||
130 | ifdef NO_OPENSSL | 138 | ifdef NO_OPENSSL |
131 | CFLAGS += -DNO_OPENSSL | 139 | CFLAGS += -DNO_OPENSSL |
132 | GIT_OPTIONS += NO_OPENSSL=1 | 140 | GIT_OPTIONS += NO_OPENSSL=1 |
133 | else | 141 | else |
134 | EXTLIBS += -lcrypto | 142 | EXTLIBS += -lcrypto |
135 | endif | 143 | endif |
136 | 144 | ||
137 | cgit: $(OBJECTS) libgit | 145 | cgit: $(OBJECTS) libgit |
138 | $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o cgit $(OBJECTS) $(EXTLIBS) | 146 | $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o cgit $(OBJECTS) $(EXTLIBS) |
139 | 147 | ||
140 | cgit.o: VERSION | 148 | cgit.o: VERSION |
141 | 149 | ||
142 | ifneq "$(MAKECMDGOALS)" "clean" | 150 | ifneq "$(MAKECMDGOALS)" "clean" |
143 | -include $(OBJECTS:.o=.d) | 151 | -include $(OBJECTS:.o=.d) |
144 | endif | 152 | endif |
145 | 153 | ||
146 | libgit: | 154 | libgit: |
147 | $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) libgit.a | 155 | $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) libgit.a |
148 | $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) xdiff/lib.a | 156 | $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) xdiff/lib.a |
149 | 157 | ||
150 | test: all | 158 | test: all |
151 | $(QUIET_SUBDIR0)tests $(QUIET_SUBDIR1) all | 159 | $(QUIET_SUBDIR0)tests $(QUIET_SUBDIR1) all |
152 | 160 | ||
153 | install: all | 161 | install: all |
@@ -589,49 +589,49 @@ static int generate_cached_repolist(const char *path, const char *cached_rc) | |||
589 | } | 589 | } |
590 | idx = cgit_repolist.count; | 590 | idx = cgit_repolist.count; |
591 | if (ctx.cfg.project_list) | 591 | if (ctx.cfg.project_list) |
592 | scan_projects(path, ctx.cfg.project_list, repo_config); | 592 | scan_projects(path, ctx.cfg.project_list, repo_config); |
593 | else | 593 | else |
594 | scan_tree(path, repo_config); | 594 | scan_tree(path, repo_config); |
595 | print_repolist(f, &cgit_repolist, idx); | 595 | print_repolist(f, &cgit_repolist, idx); |
596 | if (rename(locked_rc, cached_rc)) | 596 | if (rename(locked_rc, cached_rc)) |
597 | fprintf(stderr, "[cgit] Error renaming %s to %s: %s (%d)\n", | 597 | fprintf(stderr, "[cgit] Error renaming %s to %s: %s (%d)\n", |
598 | locked_rc, cached_rc, strerror(errno), errno); | 598 | locked_rc, cached_rc, strerror(errno), errno); |
599 | fclose(f); | 599 | fclose(f); |
600 | return 0; | 600 | return 0; |
601 | } | 601 | } |
602 | 602 | ||
603 | static void process_cached_repolist(const char *path) | 603 | static void process_cached_repolist(const char *path) |
604 | { | 604 | { |
605 | struct stat st; | 605 | struct stat st; |
606 | char *cached_rc; | 606 | char *cached_rc; |
607 | time_t age; | 607 | time_t age; |
608 | unsigned long hash; | 608 | unsigned long hash; |
609 | 609 | ||
610 | hash = hash_str(path); | 610 | hash = hash_str(path); |
611 | if (ctx.cfg.project_list) | 611 | if (ctx.cfg.project_list) |
612 | hash += hash_str(ctx.cfg.project_list); | 612 | hash += hash_str(ctx.cfg.project_list); |
613 | cached_rc = xstrdup(fmt("%s/rc-%8x", ctx.cfg.cache_root, hash)); | 613 | cached_rc = xstrdup(fmt("%s/rc-%8lx", ctx.cfg.cache_root, hash)); |
614 | 614 | ||
615 | if (stat(cached_rc, &st)) { | 615 | if (stat(cached_rc, &st)) { |
616 | /* Nothing is cached, we need to scan without forking. And | 616 | /* Nothing is cached, we need to scan without forking. And |
617 | * if we fail to generate a cached repolist, we need to | 617 | * if we fail to generate a cached repolist, we need to |
618 | * invoke scan_tree manually. | 618 | * invoke scan_tree manually. |
619 | */ | 619 | */ |
620 | if (generate_cached_repolist(path, cached_rc)) { | 620 | if (generate_cached_repolist(path, cached_rc)) { |
621 | if (ctx.cfg.project_list) | 621 | if (ctx.cfg.project_list) |
622 | scan_projects(path, ctx.cfg.project_list, | 622 | scan_projects(path, ctx.cfg.project_list, |
623 | repo_config); | 623 | repo_config); |
624 | else | 624 | else |
625 | scan_tree(path, repo_config); | 625 | scan_tree(path, repo_config); |
626 | } | 626 | } |
627 | return; | 627 | return; |
628 | } | 628 | } |
629 | 629 | ||
630 | parse_configfile(cached_rc, config_cb); | 630 | parse_configfile(cached_rc, config_cb); |
631 | 631 | ||
632 | /* If the cached configfile hasn't expired, lets exit now */ | 632 | /* If the cached configfile hasn't expired, lets exit now */ |
633 | age = time(NULL) - st.st_mtime; | 633 | age = time(NULL) - st.st_mtime; |
634 | if (age <= (ctx.cfg.cache_scanrc_ttl * 60)) | 634 | if (age <= (ctx.cfg.cache_scanrc_ttl * 60)) |
635 | return; | 635 | return; |
636 | 636 | ||
637 | /* The cached repolist has been parsed, but it was old. So lets | 637 | /* The cached repolist has been parsed, but it was old. So lets |
@@ -71,49 +71,49 @@ static void print_fileinfo(struct fileinfo *info) | |||
71 | html("<tr>"); | 71 | html("<tr>"); |
72 | htmlf("<td class='mode'>"); | 72 | htmlf("<td class='mode'>"); |
73 | if (is_null_sha1(info->new_sha1)) { | 73 | if (is_null_sha1(info->new_sha1)) { |
74 | cgit_print_filemode(info->old_mode); | 74 | cgit_print_filemode(info->old_mode); |
75 | } else { | 75 | } else { |
76 | cgit_print_filemode(info->new_mode); | 76 | cgit_print_filemode(info->new_mode); |
77 | } | 77 | } |
78 | 78 | ||
79 | if (info->old_mode != info->new_mode && | 79 | if (info->old_mode != info->new_mode && |
80 | !is_null_sha1(info->old_sha1) && | 80 | !is_null_sha1(info->old_sha1) && |
81 | !is_null_sha1(info->new_sha1)) { | 81 | !is_null_sha1(info->new_sha1)) { |
82 | html("<span class='modechange'>["); | 82 | html("<span class='modechange'>["); |
83 | cgit_print_filemode(info->old_mode); | 83 | cgit_print_filemode(info->old_mode); |
84 | html("]</span>"); | 84 | html("]</span>"); |
85 | } | 85 | } |
86 | htmlf("</td><td class='%s'>", class); | 86 | htmlf("</td><td class='%s'>", class); |
87 | cgit_diff_link(info->new_path, NULL, NULL, ctx.qry.head, ctx.qry.sha1, | 87 | cgit_diff_link(info->new_path, NULL, NULL, ctx.qry.head, ctx.qry.sha1, |
88 | ctx.qry.sha2, info->new_path, 0); | 88 | ctx.qry.sha2, info->new_path, 0); |
89 | if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED) | 89 | if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED) |
90 | htmlf(" (%s from %s)", | 90 | htmlf(" (%s from %s)", |
91 | info->status == DIFF_STATUS_COPIED ? "copied" : "renamed", | 91 | info->status == DIFF_STATUS_COPIED ? "copied" : "renamed", |
92 | info->old_path); | 92 | info->old_path); |
93 | html("</td><td class='right'>"); | 93 | html("</td><td class='right'>"); |
94 | if (info->binary) { | 94 | if (info->binary) { |
95 | htmlf("bin</td><td class='graph'>%d -> %d bytes", | 95 | htmlf("bin</td><td class='graph'>%ld -> %ld bytes", |
96 | info->old_size, info->new_size); | 96 | info->old_size, info->new_size); |
97 | return; | 97 | return; |
98 | } | 98 | } |
99 | htmlf("%d", info->added + info->removed); | 99 | htmlf("%d", info->added + info->removed); |
100 | html("</td><td class='graph'>"); | 100 | html("</td><td class='graph'>"); |
101 | htmlf("<table summary='file diffstat' width='%d%%'><tr>", (max_changes > 100 ? 100 : max_changes)); | 101 | htmlf("<table summary='file diffstat' width='%d%%'><tr>", (max_changes > 100 ? 100 : max_changes)); |
102 | htmlf("<td class='add' style='width: %.1f%%;'/>", | 102 | htmlf("<td class='add' style='width: %.1f%%;'/>", |
103 | info->added * 100.0 / max_changes); | 103 | info->added * 100.0 / max_changes); |
104 | htmlf("<td class='rem' style='width: %.1f%%;'/>", | 104 | htmlf("<td class='rem' style='width: %.1f%%;'/>", |
105 | info->removed * 100.0 / max_changes); | 105 | info->removed * 100.0 / max_changes); |
106 | htmlf("<td class='none' style='width: %.1f%%;'/>", | 106 | htmlf("<td class='none' style='width: %.1f%%;'/>", |
107 | (max_changes - info->removed - info->added) * 100.0 / max_changes); | 107 | (max_changes - info->removed - info->added) * 100.0 / max_changes); |
108 | html("</tr></table></td></tr>\n"); | 108 | html("</tr></table></td></tr>\n"); |
109 | } | 109 | } |
110 | 110 | ||
111 | static void count_diff_lines(char *line, int len) | 111 | static void count_diff_lines(char *line, int len) |
112 | { | 112 | { |
113 | if (line && (len > 0)) { | 113 | if (line && (len > 0)) { |
114 | if (line[0] == '+') | 114 | if (line[0] == '+') |
115 | lines_added++; | 115 | lines_added++; |
116 | else if (line[0] == '-') | 116 | else if (line[0] == '-') |
117 | lines_removed++; | 117 | lines_removed++; |
118 | } | 118 | } |
119 | } | 119 | } |
@@ -207,47 +207,46 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern | |||
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 | htmlf("</table><div class='pager'>", | 231 | html("</table><div class='pager'>"); |
232 | columns); | ||
233 | if (ofs > 0) { | 232 | if (ofs > 0) { |
234 | cgit_log_link("[prev]", NULL, NULL, ctx.qry.head, | 233 | cgit_log_link("[prev]", NULL, NULL, ctx.qry.head, |
235 | ctx.qry.sha1, ctx.qry.vpath, | 234 | ctx.qry.sha1, ctx.qry.vpath, |
236 | ofs - cnt, ctx.qry.grep, | 235 | ofs - cnt, ctx.qry.grep, |
237 | ctx.qry.search, ctx.qry.showmsg); | 236 | ctx.qry.search, ctx.qry.showmsg); |
238 | html(" "); | 237 | html(" "); |
239 | } | 238 | } |
240 | if ((commit = get_revision(&rev)) != NULL) { | 239 | if ((commit = get_revision(&rev)) != NULL) { |
241 | cgit_log_link("[next]", NULL, NULL, ctx.qry.head, | 240 | cgit_log_link("[next]", NULL, NULL, ctx.qry.head, |
242 | ctx.qry.sha1, ctx.qry.vpath, | 241 | ctx.qry.sha1, ctx.qry.vpath, |
243 | ofs + cnt, ctx.qry.grep, | 242 | ofs + cnt, ctx.qry.grep, |
244 | ctx.qry.search, ctx.qry.showmsg); | 243 | ctx.qry.search, ctx.qry.showmsg); |
245 | } | 244 | } |
246 | html("</div>"); | 245 | html("</div>"); |
247 | } else if ((commit = get_revision(&rev)) != NULL) { | 246 | } else if ((commit = get_revision(&rev)) != NULL) { |
248 | html("<tr class='nohover'><td colspan='3'>"); | 247 | html("<tr class='nohover'><td colspan='3'>"); |
249 | cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL, | 248 | cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL, |
250 | ctx.qry.vpath, 0, NULL, NULL, ctx.qry.showmsg); | 249 | ctx.qry.vpath, 0, NULL, NULL, ctx.qry.showmsg); |
251 | html("</td></tr>\n"); | 250 | html("</td></tr>\n"); |
252 | } | 251 | } |
253 | } | 252 | } |
@@ -1,31 +1,37 @@ | |||
1 | #include <string-list.h> | 1 | #include <string-list.h> |
2 | 2 | ||
3 | #include "cgit.h" | 3 | #include "cgit.h" |
4 | #include "html.h" | 4 | #include "html.h" |
5 | #include "ui-shared.h" | 5 | #include "ui-shared.h" |
6 | #include "ui-stats.h" | 6 | #include "ui-stats.h" |
7 | 7 | ||
8 | #ifdef NO_C99_FORMAT | ||
9 | #define SZ_FMT "%u" | ||
10 | #else | ||
11 | #define SZ_FMT "%zu" | ||
12 | #endif | ||
13 | |||
8 | #define MONTHS 6 | 14 | #define MONTHS 6 |
9 | 15 | ||
10 | struct authorstat { | 16 | struct authorstat { |
11 | long total; | 17 | long total; |
12 | struct string_list list; | 18 | struct string_list list; |
13 | }; | 19 | }; |
14 | 20 | ||
15 | #define DAY_SECS (60 * 60 * 24) | 21 | #define DAY_SECS (60 * 60 * 24) |
16 | #define WEEK_SECS (DAY_SECS * 7) | 22 | #define WEEK_SECS (DAY_SECS * 7) |
17 | 23 | ||
18 | static void trunc_week(struct tm *tm) | 24 | static void trunc_week(struct tm *tm) |
19 | { | 25 | { |
20 | time_t t = timegm(tm); | 26 | time_t t = timegm(tm); |
21 | t -= ((tm->tm_wday + 6) % 7) * DAY_SECS; | 27 | t -= ((tm->tm_wday + 6) % 7) * DAY_SECS; |
22 | gmtime_r(&t, tm); | 28 | gmtime_r(&t, tm); |
23 | } | 29 | } |
24 | 30 | ||
25 | static void dec_week(struct tm *tm) | 31 | static void dec_week(struct tm *tm) |
26 | { | 32 | { |
27 | time_t t = timegm(tm); | 33 | time_t t = timegm(tm); |
28 | t -= WEEK_SECS; | 34 | t -= WEEK_SECS; |
29 | gmtime_r(&t, tm); | 35 | gmtime_r(&t, tm); |
30 | } | 36 | } |
31 | 37 | ||
@@ -262,133 +268,133 @@ void print_combined_authorrow(struct string_list *authors, int from, int to, | |||
262 | struct tm *tm; | 268 | struct tm *tm; |
263 | char *tmp; | 269 | char *tmp; |
264 | 270 | ||
265 | time(&now); | 271 | time(&now); |
266 | tm = gmtime(&now); | 272 | tm = gmtime(&now); |
267 | period->trunc(tm); | 273 | period->trunc(tm); |
268 | for (i = 1; i < period->count; i++) | 274 | for (i = 1; i < period->count; i++) |
269 | period->dec(tm); | 275 | period->dec(tm); |
270 | 276 | ||
271 | total = 0; | 277 | total = 0; |
272 | htmlf("<tr><td class='%s'>%s</td>", leftclass, | 278 | htmlf("<tr><td class='%s'>%s</td>", leftclass, |
273 | fmt(name, to - from + 1)); | 279 | fmt(name, to - from + 1)); |
274 | for (j = 0; j < period->count; j++) { | 280 | for (j = 0; j < period->count; j++) { |
275 | tmp = period->pretty(tm); | 281 | tmp = period->pretty(tm); |
276 | period->inc(tm); | 282 | period->inc(tm); |
277 | subtotal = 0; | 283 | subtotal = 0; |
278 | for (i = from; i <= to; i++) { | 284 | for (i = from; i <= to; i++) { |
279 | author = &authors->items[i]; | 285 | author = &authors->items[i]; |
280 | authorstat = author->util; | 286 | authorstat = author->util; |
281 | items = &authorstat->list; | 287 | items = &authorstat->list; |
282 | date = string_list_lookup(items, tmp); | 288 | date = string_list_lookup(items, tmp); |
283 | if (date) | 289 | if (date) |
284 | subtotal += (size_t)date->util; | 290 | subtotal += (size_t)date->util; |
285 | } | 291 | } |
286 | htmlf("<td class='%s'>%d</td>", centerclass, subtotal); | 292 | htmlf("<td class='%s'>%ld</td>", centerclass, subtotal); |
287 | total += subtotal; | 293 | total += subtotal; |
288 | } | 294 | } |
289 | htmlf("<td class='%s'>%d</td></tr>", rightclass, total); | 295 | htmlf("<td class='%s'>%ld</td></tr>", rightclass, total); |
290 | } | 296 | } |
291 | 297 | ||
292 | void print_authors(struct string_list *authors, int top, | 298 | void print_authors(struct string_list *authors, int top, |
293 | struct cgit_period *period) | 299 | struct cgit_period *period) |
294 | { | 300 | { |
295 | struct string_list_item *author; | 301 | struct string_list_item *author; |
296 | struct authorstat *authorstat; | 302 | struct authorstat *authorstat; |
297 | struct string_list *items; | 303 | struct string_list *items; |
298 | struct string_list_item *date; | 304 | struct string_list_item *date; |
299 | time_t now; | 305 | time_t now; |
300 | long i, j, total; | 306 | long i, j, total; |
301 | struct tm *tm; | 307 | struct tm *tm; |
302 | char *tmp; | 308 | char *tmp; |
303 | 309 | ||
304 | time(&now); | 310 | time(&now); |
305 | tm = gmtime(&now); | 311 | tm = gmtime(&now); |
306 | period->trunc(tm); | 312 | period->trunc(tm); |
307 | for (i = 1; i < period->count; i++) | 313 | for (i = 1; i < period->count; i++) |
308 | period->dec(tm); | 314 | period->dec(tm); |
309 | 315 | ||
310 | html("<table class='stats'><tr><th>Author</th>"); | 316 | html("<table class='stats'><tr><th>Author</th>"); |
311 | for (j = 0; j < period->count; j++) { | 317 | for (j = 0; j < period->count; j++) { |
312 | tmp = period->pretty(tm); | 318 | tmp = period->pretty(tm); |
313 | htmlf("<th>%s</th>", tmp); | 319 | htmlf("<th>%s</th>", tmp); |
314 | period->inc(tm); | 320 | period->inc(tm); |
315 | } | 321 | } |
316 | html("<th>Total</th></tr>\n"); | 322 | html("<th>Total</th></tr>\n"); |
317 | 323 | ||
318 | if (top <= 0 || top > authors->nr) | 324 | if (top <= 0 || top > authors->nr) |
319 | top = authors->nr; | 325 | top = authors->nr; |
320 | 326 | ||
321 | for (i = 0; i < top; i++) { | 327 | for (i = 0; i < top; i++) { |
322 | author = &authors->items[i]; | 328 | author = &authors->items[i]; |
323 | html("<tr><td class='left'>"); | 329 | html("<tr><td class='left'>"); |
324 | html_txt(author->string); | 330 | html_txt(author->string); |
325 | html("</td>"); | 331 | html("</td>"); |
326 | authorstat = author->util; | 332 | authorstat = author->util; |
327 | items = &authorstat->list; | 333 | items = &authorstat->list; |
328 | total = 0; | 334 | total = 0; |
329 | for (j = 0; j < period->count; j++) | 335 | for (j = 0; j < period->count; j++) |
330 | period->dec(tm); | 336 | period->dec(tm); |
331 | for (j = 0; j < period->count; j++) { | 337 | for (j = 0; j < period->count; j++) { |
332 | tmp = period->pretty(tm); | 338 | tmp = period->pretty(tm); |
333 | period->inc(tm); | 339 | period->inc(tm); |
334 | date = string_list_lookup(items, tmp); | 340 | date = string_list_lookup(items, tmp); |
335 | if (!date) | 341 | if (!date) |
336 | html("<td>0</td>"); | 342 | html("<td>0</td>"); |
337 | else { | 343 | else { |
338 | htmlf("<td>%d</td>", date->util); | 344 | htmlf("<td>"SZ_FMT"</td>", (size_t)date->util); |
339 | total += (size_t)date->util; | 345 | total += (size_t)date->util; |
340 | } | 346 | } |
341 | } | 347 | } |
342 | htmlf("<td class='sum'>%d</td></tr>", total); | 348 | htmlf("<td class='sum'>%ld</td></tr>", total); |
343 | } | 349 | } |
344 | 350 | ||
345 | if (top < authors->nr) | 351 | if (top < authors->nr) |
346 | print_combined_authorrow(authors, top, authors->nr - 1, | 352 | print_combined_authorrow(authors, top, authors->nr - 1, |
347 | "Others (%d)", "left", "", "sum", period); | 353 | "Others (%ld)", "left", "", "sum", period); |
348 | 354 | ||
349 | print_combined_authorrow(authors, 0, authors->nr - 1, "Total", | 355 | print_combined_authorrow(authors, 0, authors->nr - 1, "Total", |
350 | "total", "sum", "sum", period); | 356 | "total", "sum", "sum", period); |
351 | html("</table>"); | 357 | html("</table>"); |
352 | } | 358 | } |
353 | 359 | ||
354 | /* Create a sorted string_list with one entry per author. The util-field | 360 | /* Create a sorted string_list with one entry per author. The util-field |
355 | * for each author is another string_list which is used to calculate the | 361 | * for each author is another string_list which is used to calculate the |
356 | * number of commits per time-interval. | 362 | * number of commits per time-interval. |
357 | */ | 363 | */ |
358 | void cgit_show_stats(struct cgit_context *ctx) | 364 | void cgit_show_stats(struct cgit_context *ctx) |
359 | { | 365 | { |
360 | struct string_list authors; | 366 | struct string_list authors; |
361 | struct cgit_period *period; | 367 | struct cgit_period *period; |
362 | int top, i; | 368 | int top, i; |
363 | const char *code = "w"; | 369 | const char *code = "w"; |
364 | 370 | ||
365 | if (ctx->qry.period) | 371 | if (ctx->qry.period) |
366 | code = ctx->qry.period; | 372 | code = ctx->qry.period; |
367 | 373 | ||
368 | i = cgit_find_stats_period(code, &period); | 374 | i = cgit_find_stats_period(code, &period); |
369 | if (!i) { | 375 | if (!i) { |
370 | cgit_print_error(fmt("Unknown statistics type: %c", code)); | 376 | cgit_print_error(fmt("Unknown statistics type: %c", code[0])); |
371 | return; | 377 | return; |
372 | } | 378 | } |
373 | if (i > ctx->repo->max_stats) { | 379 | if (i > ctx->repo->max_stats) { |
374 | cgit_print_error(fmt("Statistics type disabled: %s", | 380 | cgit_print_error(fmt("Statistics type disabled: %s", |
375 | period->name)); | 381 | period->name)); |
376 | return; | 382 | return; |
377 | } | 383 | } |
378 | authors = collect_stats(ctx, period); | 384 | authors = collect_stats(ctx, period); |
379 | qsort(authors.items, authors.nr, sizeof(struct string_list_item), | 385 | qsort(authors.items, authors.nr, sizeof(struct string_list_item), |
380 | cmp_total_commits); | 386 | cmp_total_commits); |
381 | 387 | ||
382 | top = ctx->qry.ofs; | 388 | top = ctx->qry.ofs; |
383 | if (!top) | 389 | if (!top) |
384 | top = 10; | 390 | top = 10; |
385 | htmlf("<h2>Commits per author per %s", period->name); | 391 | htmlf("<h2>Commits per author per %s", period->name); |
386 | if (ctx->qry.path) { | 392 | if (ctx->qry.path) { |
387 | html(" (path '"); | 393 | html(" (path '"); |
388 | html_txt(ctx->qry.path); | 394 | html_txt(ctx->qry.path); |
389 | html("')"); | 395 | html("')"); |
390 | } | 396 | } |
391 | html("</h2>"); | 397 | html("</h2>"); |
392 | 398 | ||
393 | html("<form method='get' action='' style='float: right; text-align: right;'>"); | 399 | html("<form method='get' action='' style='float: right; text-align: right;'>"); |
394 | cgit_add_hidden_formfields(1, 0, "stats"); | 400 | cgit_add_hidden_formfields(1, 0, "stats"); |
@@ -46,90 +46,90 @@ static void print_text_buffer(const char *name, char *buf, unsigned long size) | |||
46 | html("<td class='lines'><pre><code>"); | 46 | html("<td class='lines'><pre><code>"); |
47 | ctx.repo->source_filter->argv[1] = xstrdup(name); | 47 | ctx.repo->source_filter->argv[1] = xstrdup(name); |
48 | cgit_open_filter(ctx.repo->source_filter); | 48 | cgit_open_filter(ctx.repo->source_filter); |
49 | write(STDOUT_FILENO, buf, size); | 49 | write(STDOUT_FILENO, buf, size); |
50 | cgit_close_filter(ctx.repo->source_filter); | 50 | cgit_close_filter(ctx.repo->source_filter); |
51 | html("</code></pre></td></tr></table>\n"); | 51 | html("</code></pre></td></tr></table>\n"); |
52 | return; | 52 | return; |
53 | } | 53 | } |
54 | 54 | ||
55 | html("<td class='lines'><pre><code>"); | 55 | html("<td class='lines'><pre><code>"); |
56 | html_txt(buf); | 56 | html_txt(buf); |
57 | html("</code></pre></td></tr></table>\n"); | 57 | html("</code></pre></td></tr></table>\n"); |
58 | } | 58 | } |
59 | 59 | ||
60 | #define ROWLEN 32 | 60 | #define ROWLEN 32 |
61 | 61 | ||
62 | static void print_binary_buffer(char *buf, unsigned long size) | 62 | static void print_binary_buffer(char *buf, unsigned long size) |
63 | { | 63 | { |
64 | unsigned long ofs, idx; | 64 | unsigned long ofs, idx; |
65 | static char ascii[ROWLEN + 1]; | 65 | static char ascii[ROWLEN + 1]; |
66 | 66 | ||
67 | html("<table summary='blob content' class='bin-blob'>\n"); | 67 | html("<table summary='blob content' class='bin-blob'>\n"); |
68 | html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>"); | 68 | html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>"); |
69 | for (ofs = 0; ofs < size; ofs += ROWLEN, buf += ROWLEN) { | 69 | for (ofs = 0; ofs < size; ofs += ROWLEN, buf += ROWLEN) { |
70 | htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs); | 70 | htmlf("<tr><td class='right'>%04lx</td><td class='hex'>", ofs); |
71 | for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) | 71 | for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) |
72 | htmlf("%*s%02x", | 72 | htmlf("%*s%02x", |
73 | idx == 16 ? 4 : 1, "", | 73 | idx == 16 ? 4 : 1, "", |
74 | buf[idx] & 0xff); | 74 | buf[idx] & 0xff); |
75 | html(" </td><td class='hex'>"); | 75 | html(" </td><td class='hex'>"); |
76 | for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) | 76 | for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) |
77 | ascii[idx] = isgraph(buf[idx]) ? buf[idx] : '.'; | 77 | ascii[idx] = isgraph(buf[idx]) ? buf[idx] : '.'; |
78 | ascii[idx] = '\0'; | 78 | ascii[idx] = '\0'; |
79 | html_txt(ascii); | 79 | html_txt(ascii); |
80 | html("</td></tr>\n"); | 80 | html("</td></tr>\n"); |
81 | } | 81 | } |
82 | html("</table>\n"); | 82 | html("</table>\n"); |
83 | } | 83 | } |
84 | 84 | ||
85 | static void print_object(const unsigned char *sha1, char *path, const char *basename) | 85 | static void print_object(const unsigned char *sha1, char *path, const char *basename) |
86 | { | 86 | { |
87 | enum object_type type; | 87 | enum object_type type; |
88 | char *buf; | 88 | char *buf; |
89 | unsigned long size; | 89 | unsigned long size; |
90 | 90 | ||
91 | type = sha1_object_info(sha1, &size); | 91 | type = sha1_object_info(sha1, &size); |
92 | if (type == OBJ_BAD) { | 92 | if (type == OBJ_BAD) { |
93 | cgit_print_error(fmt("Bad object name: %s", | 93 | cgit_print_error(fmt("Bad object name: %s", |
94 | sha1_to_hex(sha1))); | 94 | sha1_to_hex(sha1))); |
95 | return; | 95 | return; |
96 | } | 96 | } |
97 | 97 | ||
98 | buf = read_sha1_file(sha1, &type, &size); | 98 | buf = read_sha1_file(sha1, &type, &size); |
99 | if (!buf) { | 99 | if (!buf) { |
100 | cgit_print_error(fmt("Error reading object %s", | 100 | cgit_print_error(fmt("Error reading object %s", |
101 | sha1_to_hex(sha1))); | 101 | sha1_to_hex(sha1))); |
102 | return; | 102 | return; |
103 | } | 103 | } |
104 | 104 | ||
105 | htmlf("blob: %s (", sha1_to_hex(sha1)); | 105 | htmlf("blob: %s (", sha1_to_hex(sha1)); |
106 | cgit_plain_link("plain", NULL, NULL, ctx.qry.head, | 106 | cgit_plain_link("plain", NULL, NULL, ctx.qry.head, |
107 | curr_rev, path); | 107 | curr_rev, path); |
108 | html(")\n"); | 108 | html(")\n"); |
109 | 109 | ||
110 | if (ctx.cfg.max_blob_size && size / 1024 > ctx.cfg.max_blob_size) { | 110 | if (ctx.cfg.max_blob_size && size / 1024 > ctx.cfg.max_blob_size) { |
111 | htmlf("<div class='error'>blob size (%dKB) exceeds display size limit (%dKB).</div>", | 111 | htmlf("<div class='error'>blob size (%ldKB) exceeds display size limit (%dKB).</div>", |
112 | size / 1024, ctx.cfg.max_blob_size); | 112 | size / 1024, ctx.cfg.max_blob_size); |
113 | return; | 113 | return; |
114 | } | 114 | } |
115 | 115 | ||
116 | if (buffer_is_binary(buf, size)) | 116 | if (buffer_is_binary(buf, size)) |
117 | print_binary_buffer(buf, size); | 117 | print_binary_buffer(buf, size); |
118 | else | 118 | else |
119 | print_text_buffer(basename, buf, size); | 119 | print_text_buffer(basename, buf, size); |
120 | } | 120 | } |
121 | 121 | ||
122 | 122 | ||
123 | static int ls_item(const unsigned char *sha1, const char *base, int baselen, | 123 | static int ls_item(const unsigned char *sha1, const char *base, int baselen, |
124 | const char *pathname, unsigned int mode, int stage, | 124 | const char *pathname, unsigned int mode, int stage, |
125 | void *cbdata) | 125 | void *cbdata) |
126 | { | 126 | { |
127 | char *name; | 127 | char *name; |
128 | char *fullpath; | 128 | char *fullpath; |
129 | char *class; | 129 | char *class; |
130 | enum object_type type; | 130 | enum object_type type; |
131 | unsigned long size = 0; | 131 | unsigned long size = 0; |
132 | 132 | ||
133 | name = xstrdup(pathname); | 133 | name = xstrdup(pathname); |
134 | fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", | 134 | fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", |
135 | ctx.qry.path ? "/" : "", name); | 135 | ctx.qry.path ? "/" : "", name); |