summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2009-12-12 11:09:47 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2009-12-12 11:09:47 (UTC)
commit547a64fbd65de293c290f4e18bbeae958d54aaa7 (patch) (unidiff)
treee35d8ae4e9408cd552e539c5af08d4bd6fdd1e8f
parent0642435fed6793a0d038e1e5097a91293ee89a05 (diff)
parentc86e206a9773f97dc6de6bbf45712bb304de3653 (diff)
downloadcgit-547a64fbd65de293c290f4e18bbeae958d54aaa7.zip
cgit-547a64fbd65de293c290f4e18bbeae958d54aaa7.tar.gz
cgit-547a64fbd65de293c290f4e18bbeae958d54aaa7.tar.bz2
Merge branch 'stable'
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--Makefile2
-rw-r--r--ui-blob.c2
-rw-r--r--ui-plain.c2
-rw-r--r--ui-tree.c2
4 files changed, 4 insertions, 4 deletions
diff --git a/Makefile b/Makefile
index f8a4d47..d39a30e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,181 +1,181 @@
1CGIT_VERSION = v0.8.3 1CGIT_VERSION = v0.8.3.1
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)
5CGIT_CONFIG = /etc/cgitrc 5CGIT_CONFIG = /etc/cgitrc
6CACHE_ROOT = /var/cache/cgit 6CACHE_ROOT = /var/cache/cgit
7SHA1_HEADER = <openssl/sha.h> 7SHA1_HEADER = <openssl/sha.h>
8GIT_VER = 1.6.4.3 8GIT_VER = 1.6.4.3
9GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2 9GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2
10INSTALL = install 10INSTALL = 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 19
20#-include config.mak 20#-include config.mak
21 21
22# 22#
23# Platform specific tweaks 23# Platform specific tweaks
24# 24#
25 25
26uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') 26uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
27uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not') 27uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
28uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not') 28uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
29 29
30ifeq ($(uname_O),Cygwin) 30ifeq ($(uname_O),Cygwin)
31 NO_STRCASESTR = YesPlease 31 NO_STRCASESTR = YesPlease
32 NEEDS_LIBICONV = YesPlease 32 NEEDS_LIBICONV = YesPlease
33endif 33endif
34 34
35# 35#
36# Let the user override the above settings. 36# Let the user override the above settings.
37# 37#
38-include cgit.conf 38-include cgit.conf
39 39
40# 40#
41# Define a way to invoke make in subdirs quietly, shamelessly ripped 41# Define a way to invoke make in subdirs quietly, shamelessly ripped
42# from git.git 42# from git.git
43# 43#
44QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir 44QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
45QUIET_SUBDIR1 = 45QUIET_SUBDIR1 =
46 46
47ifneq ($(findstring $(MAKEFLAGS),w),w) 47ifneq ($(findstring $(MAKEFLAGS),w),w)
48PRINT_DIR = --no-print-directory 48PRINT_DIR = --no-print-directory
49else # "make -w" 49else # "make -w"
50NO_SUBDIR = : 50NO_SUBDIR = :
51endif 51endif
52 52
53ifndef V 53ifndef V
54 QUIET_CC = @echo ' ' CC $@; 54 QUIET_CC = @echo ' ' CC $@;
55 QUIET_MM = @echo ' ' MM $@; 55 QUIET_MM = @echo ' ' MM $@;
56 QUIET_SUBDIR0 = +@subdir= 56 QUIET_SUBDIR0 = +@subdir=
57 QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ 57 QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
58 $(MAKE) $(PRINT_DIR) -C $$subdir 58 $(MAKE) $(PRINT_DIR) -C $$subdir
59endif 59endif
60 60
61# 61#
62# Define a pattern rule for automatic dependency building 62# Define a pattern rule for automatic dependency building
63# 63#
64%.d: %.c 64%.d: %.c
65 $(QUIET_MM)$(CC) $(CFLAGS) -MM $< | sed -e 's/\($*\)\.o:/\1.o $@:/g' >$@ 65 $(QUIET_MM)$(CC) $(CFLAGS) -MM $< | sed -e 's/\($*\)\.o:/\1.o $@:/g' >$@
66 66
67# 67#
68# Define a pattern rule for silent object building 68# Define a pattern rule for silent object building
69# 69#
70%.o: %.c 70%.o: %.c
71 $(QUIET_CC)$(CC) -o $*.o -c $(CFLAGS) $< 71 $(QUIET_CC)$(CC) -o $*.o -c $(CFLAGS) $<
72 72
73 73
74EXTLIBS = git/libgit.a git/xdiff/lib.a -lz 74EXTLIBS = git/libgit.a git/xdiff/lib.a -lz
75OBJECTS = 75OBJECTS =
76OBJECTS += cache.o 76OBJECTS += cache.o
77OBJECTS += cgit.o 77OBJECTS += cgit.o
78OBJECTS += cmd.o 78OBJECTS += cmd.o
79OBJECTS += configfile.o 79OBJECTS += configfile.o
80OBJECTS += html.o 80OBJECTS += html.o
81OBJECTS += parsing.o 81OBJECTS += parsing.o
82OBJECTS += scan-tree.o 82OBJECTS += scan-tree.o
83OBJECTS += shared.o 83OBJECTS += shared.o
84OBJECTS += ui-atom.o 84OBJECTS += ui-atom.o
85OBJECTS += ui-blob.o 85OBJECTS += ui-blob.o
86OBJECTS += ui-clone.o 86OBJECTS += ui-clone.o
87OBJECTS += ui-commit.o 87OBJECTS += ui-commit.o
88OBJECTS += ui-diff.o 88OBJECTS += ui-diff.o
89OBJECTS += ui-log.o 89OBJECTS += ui-log.o
90OBJECTS += ui-patch.o 90OBJECTS += ui-patch.o
91OBJECTS += ui-plain.o 91OBJECTS += ui-plain.o
92OBJECTS += ui-refs.o 92OBJECTS += ui-refs.o
93OBJECTS += ui-repolist.o 93OBJECTS += ui-repolist.o
94OBJECTS += ui-shared.o 94OBJECTS += ui-shared.o
95OBJECTS += ui-snapshot.o 95OBJECTS += ui-snapshot.o
96OBJECTS += ui-ssdiff.o 96OBJECTS += ui-ssdiff.o
97OBJECTS += ui-stats.o 97OBJECTS += ui-stats.o
98OBJECTS += ui-summary.o 98OBJECTS += ui-summary.o
99OBJECTS += ui-tag.o 99OBJECTS += ui-tag.o
100OBJECTS += ui-tree.o 100OBJECTS += ui-tree.o
101 101
102ifdef NEEDS_LIBICONV 102ifdef NEEDS_LIBICONV
103 EXTLIBS += -liconv 103 EXTLIBS += -liconv
104endif 104endif
105 105
106 106
107.PHONY: all libgit test install uninstall clean force-version get-git \ 107.PHONY: all libgit test install uninstall clean force-version get-git \
108 doc man-doc html-doc clean-doc 108 doc man-doc html-doc clean-doc
109 109
110all: cgit 110all: cgit
111 111
112VERSION: force-version 112VERSION: force-version
113 @./gen-version.sh "$(CGIT_VERSION)" 113 @./gen-version.sh "$(CGIT_VERSION)"
114-include VERSION 114-include VERSION
115 115
116 116
117CFLAGS += -g -Wall -Igit 117CFLAGS += -g -Wall -Igit
118CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)' 118CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)'
119CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"' 119CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"'
120CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"' 120CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"'
121CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"' 121CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"'
122CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"' 122CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"'
123 123
124ifdef NO_ICONV 124ifdef NO_ICONV
125 CFLAGS += -DNO_ICONV 125 CFLAGS += -DNO_ICONV
126endif 126endif
127ifdef NO_STRCASESTR 127ifdef NO_STRCASESTR
128 CFLAGS += -DNO_STRCASESTR 128 CFLAGS += -DNO_STRCASESTR
129endif 129endif
130ifdef NO_OPENSSL 130ifdef NO_OPENSSL
131 CFLAGS += -DNO_OPENSSL 131 CFLAGS += -DNO_OPENSSL
132 GIT_OPTIONS += NO_OPENSSL=1 132 GIT_OPTIONS += NO_OPENSSL=1
133else 133else
134 EXTLIBS += -lcrypto 134 EXTLIBS += -lcrypto
135endif 135endif
136 136
137cgit: $(OBJECTS) libgit 137cgit: $(OBJECTS) libgit
138 $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o cgit $(OBJECTS) $(EXTLIBS) 138 $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o cgit $(OBJECTS) $(EXTLIBS)
139 139
140cgit.o: VERSION 140cgit.o: VERSION
141 141
142-include $(OBJECTS:.o=.d) 142-include $(OBJECTS:.o=.d)
143 143
144libgit: 144libgit:
145 $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) libgit.a 145 $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) libgit.a
146 $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) xdiff/lib.a 146 $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) xdiff/lib.a
147 147
148test: all 148test: all
149 $(QUIET_SUBDIR0)tests $(QUIET_SUBDIR1) all 149 $(QUIET_SUBDIR0)tests $(QUIET_SUBDIR1) all
150 150
151install: all 151install: all
152 $(INSTALL) -m 0755 -d $(DESTDIR)$(CGIT_SCRIPT_PATH) 152 $(INSTALL) -m 0755 -d $(DESTDIR)$(CGIT_SCRIPT_PATH)
153 $(INSTALL) -m 0755 cgit $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) 153 $(INSTALL) -m 0755 cgit $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME)
154 $(INSTALL) -m 0755 -d $(DESTDIR)$(CGIT_DATA_PATH) 154 $(INSTALL) -m 0755 -d $(DESTDIR)$(CGIT_DATA_PATH)
155 $(INSTALL) -m 0644 cgit.css $(DESTDIR)$(CGIT_DATA_PATH)/cgit.css 155 $(INSTALL) -m 0644 cgit.css $(DESTDIR)$(CGIT_DATA_PATH)/cgit.css
156 $(INSTALL) -m 0644 cgit.png $(DESTDIR)$(CGIT_DATA_PATH)/cgit.png 156 $(INSTALL) -m 0644 cgit.png $(DESTDIR)$(CGIT_DATA_PATH)/cgit.png
157 157
158uninstall: 158uninstall:
159 rm -f $(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) 159 rm -f $(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME)
160 rm -f $(CGIT_DATA_PATH)/cgit.css 160 rm -f $(CGIT_DATA_PATH)/cgit.css
161 rm -f $(CGIT_DATA_PATH)/cgit.png 161 rm -f $(CGIT_DATA_PATH)/cgit.png
162 162
163doc: man-doc html-doc pdf-doc 163doc: man-doc html-doc pdf-doc
164 164
165man-doc: cgitrc.5.txt 165man-doc: cgitrc.5.txt
166 a2x -f manpage cgitrc.5.txt 166 a2x -f manpage cgitrc.5.txt
167 167
168html-doc: cgitrc.5.txt 168html-doc: cgitrc.5.txt
169 a2x -f xhtml --stylesheet=cgit-doc.css cgitrc.5.txt 169 a2x -f xhtml --stylesheet=cgit-doc.css cgitrc.5.txt
170 170
171pdf-doc: cgitrc.5.txt 171pdf-doc: cgitrc.5.txt
172 a2x -f pdf cgitrc.5.txt 172 a2x -f pdf cgitrc.5.txt
173 173
174clean: clean-doc 174clean: clean-doc
175 rm -f cgit VERSION *.o *.d 175 rm -f cgit VERSION *.o *.d
176 176
177clean-doc: 177clean-doc:
178 rm -f cgitrc.5 cgitrc.5.html cgitrc.5.pdf cgitrc.5.xml cgitrc.5.fo 178 rm -f cgitrc.5 cgitrc.5.html cgitrc.5.pdf cgitrc.5.xml cgitrc.5.fo
179 179
180get-git: 180get-git:
181 curl $(GIT_URL) | tar -xj && rm -rf git && mv git-$(GIT_VER) git 181 curl $(GIT_URL) | tar -xj && rm -rf git && mv git-$(GIT_VER) git
diff --git a/ui-blob.c b/ui-blob.c
index 2ccd31d..89330ce 100644
--- a/ui-blob.c
+++ b/ui-blob.c
@@ -1,79 +1,79 @@
1/* ui-blob.c: show blob content 1/* ui-blob.c: show blob content
2 * 2 *
3 * Copyright (C) 2008 Lars Hjemli 3 * Copyright (C) 2008 Lars Hjemli
4 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
10#include "html.h" 10#include "html.h"
11#include "ui-shared.h" 11#include "ui-shared.h"
12 12
13static char *match_path; 13static char *match_path;
14static unsigned char *matched_sha1; 14static unsigned char *matched_sha1;
15 15
16static int walk_tree(const unsigned char *sha1, const char *base,int baselen, 16static int walk_tree(const unsigned char *sha1, const char *base,int baselen,
17 const char *pathname, unsigned mode, int stage, void *cbdata) { 17 const char *pathname, unsigned mode, int stage, void *cbdata) {
18 if(strncmp(base,match_path,baselen) 18 if(strncmp(base,match_path,baselen)
19 || strcmp(match_path+baselen,pathname) ) 19 || strcmp(match_path+baselen,pathname) )
20 return READ_TREE_RECURSIVE; 20 return READ_TREE_RECURSIVE;
21 memmove(matched_sha1,sha1,20); 21 memmove(matched_sha1,sha1,20);
22 return 0; 22 return 0;
23} 23}
24 24
25void cgit_print_blob(const char *hex, char *path, const char *head) 25void cgit_print_blob(const char *hex, char *path, const char *head)
26{ 26{
27 27
28 unsigned char sha1[20]; 28 unsigned char sha1[20];
29 enum object_type type; 29 enum object_type type;
30 char *buf; 30 char *buf;
31 unsigned long size; 31 unsigned long size;
32 struct commit *commit; 32 struct commit *commit;
33 const char *paths[] = {path, NULL}; 33 const char *paths[] = {path, NULL};
34 34
35 if (hex) { 35 if (hex) {
36 if (get_sha1_hex(hex, sha1)){ 36 if (get_sha1_hex(hex, sha1)){
37 cgit_print_error(fmt("Bad hex value: %s", hex)); 37 cgit_print_error(fmt("Bad hex value: %s", hex));
38 return; 38 return;
39 } 39 }
40 } else { 40 } else {
41 if (get_sha1(head,sha1)) { 41 if (get_sha1(head,sha1)) {
42 cgit_print_error(fmt("Bad ref: %s", head)); 42 cgit_print_error(fmt("Bad ref: %s", head));
43 return; 43 return;
44 } 44 }
45 } 45 }
46 46
47 type = sha1_object_info(sha1, &size); 47 type = sha1_object_info(sha1, &size);
48 48
49 if((!hex) && type == OBJ_COMMIT && path) { 49 if((!hex) && type == OBJ_COMMIT && path) {
50 commit = lookup_commit_reference(sha1); 50 commit = lookup_commit_reference(sha1);
51 match_path = path; 51 match_path = path;
52 matched_sha1 = sha1; 52 matched_sha1 = sha1;
53 read_tree_recursive(commit->tree, NULL, 0, 0, paths, walk_tree, NULL); 53 read_tree_recursive(commit->tree, "", 0, 0, paths, walk_tree, NULL);
54 type = sha1_object_info(sha1,&size); 54 type = sha1_object_info(sha1,&size);
55 } 55 }
56 56
57 if (type == OBJ_BAD) { 57 if (type == OBJ_BAD) {
58 cgit_print_error(fmt("Bad object name: %s", hex)); 58 cgit_print_error(fmt("Bad object name: %s", hex));
59 return; 59 return;
60 } 60 }
61 61
62 buf = read_sha1_file(sha1, &type, &size); 62 buf = read_sha1_file(sha1, &type, &size);
63 if (!buf) { 63 if (!buf) {
64 cgit_print_error(fmt("Error reading object %s", hex)); 64 cgit_print_error(fmt("Error reading object %s", hex));
65 return; 65 return;
66 } 66 }
67 67
68 buf[size] = '\0'; 68 buf[size] = '\0';
69 ctx.page.mimetype = ctx.qry.mimetype; 69 ctx.page.mimetype = ctx.qry.mimetype;
70 if (!ctx.page.mimetype) { 70 if (!ctx.page.mimetype) {
71 if (buffer_is_binary(buf, size)) 71 if (buffer_is_binary(buf, size))
72 ctx.page.mimetype = "application/octet-stream"; 72 ctx.page.mimetype = "application/octet-stream";
73 else 73 else
74 ctx.page.mimetype = "text/plain"; 74 ctx.page.mimetype = "text/plain";
75 } 75 }
76 ctx.page.filename = path; 76 ctx.page.filename = path;
77 cgit_print_http_headers(&ctx); 77 cgit_print_http_headers(&ctx);
78 write(htmlfd, buf, size); 78 write(htmlfd, buf, size);
79} 79}
diff --git a/ui-plain.c b/ui-plain.c
index a4ce077..66cb19c 100644
--- a/ui-plain.c
+++ b/ui-plain.c
@@ -1,94 +1,94 @@
1/* ui-plain.c: functions for output of plain blobs by path 1/* ui-plain.c: functions for output of plain blobs by path
2 * 2 *
3 * Copyright (C) 2008 Lars Hjemli 3 * Copyright (C) 2008 Lars Hjemli
4 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
10#include "html.h" 10#include "html.h"
11#include "ui-shared.h" 11#include "ui-shared.h"
12 12
13char *curr_rev; 13char *curr_rev;
14char *match_path; 14char *match_path;
15int match; 15int match;
16 16
17static void print_object(const unsigned char *sha1, const char *path) 17static void print_object(const unsigned char *sha1, const char *path)
18{ 18{
19 enum object_type type; 19 enum object_type type;
20 char *buf, *ext; 20 char *buf, *ext;
21 unsigned long size; 21 unsigned long size;
22 struct string_list_item *mime; 22 struct string_list_item *mime;
23 23
24 type = sha1_object_info(sha1, &size); 24 type = sha1_object_info(sha1, &size);
25 if (type == OBJ_BAD) { 25 if (type == OBJ_BAD) {
26 html_status(404, "Not found", 0); 26 html_status(404, "Not found", 0);
27 return; 27 return;
28 } 28 }
29 29
30 buf = read_sha1_file(sha1, &type, &size); 30 buf = read_sha1_file(sha1, &type, &size);
31 if (!buf) { 31 if (!buf) {
32 html_status(404, "Not found", 0); 32 html_status(404, "Not found", 0);
33 return; 33 return;
34 } 34 }
35 ctx.page.mimetype = NULL; 35 ctx.page.mimetype = NULL;
36 ext = strrchr(path, '.'); 36 ext = strrchr(path, '.');
37 if (ext && *(++ext)) { 37 if (ext && *(++ext)) {
38 mime = string_list_lookup(ext, &ctx.cfg.mimetypes); 38 mime = string_list_lookup(ext, &ctx.cfg.mimetypes);
39 if (mime) 39 if (mime)
40 ctx.page.mimetype = (char *)mime->util; 40 ctx.page.mimetype = (char *)mime->util;
41 } 41 }
42 if (!ctx.page.mimetype) { 42 if (!ctx.page.mimetype) {
43 if (buffer_is_binary(buf, size)) 43 if (buffer_is_binary(buf, size))
44 ctx.page.mimetype = "application/octet-stream"; 44 ctx.page.mimetype = "application/octet-stream";
45 else 45 else
46 ctx.page.mimetype = "text/plain"; 46 ctx.page.mimetype = "text/plain";
47 } 47 }
48 ctx.page.filename = fmt("%s", path); 48 ctx.page.filename = fmt("%s", path);
49 ctx.page.size = size; 49 ctx.page.size = size;
50 ctx.page.etag = sha1_to_hex(sha1); 50 ctx.page.etag = sha1_to_hex(sha1);
51 cgit_print_http_headers(&ctx); 51 cgit_print_http_headers(&ctx);
52 html_raw(buf, size); 52 html_raw(buf, size);
53 match = 1; 53 match = 1;
54} 54}
55 55
56static int walk_tree(const unsigned char *sha1, const char *base, int baselen, 56static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
57 const char *pathname, unsigned mode, int stage, 57 const char *pathname, unsigned mode, int stage,
58 void *cbdata) 58 void *cbdata)
59{ 59{
60 if (S_ISDIR(mode)) 60 if (S_ISDIR(mode))
61 return READ_TREE_RECURSIVE; 61 return READ_TREE_RECURSIVE;
62 62
63 if (S_ISREG(mode) && !strncmp(base, match_path, baselen) && 63 if (S_ISREG(mode) && !strncmp(base, match_path, baselen) &&
64 !strcmp(pathname, match_path + baselen)) 64 !strcmp(pathname, match_path + baselen))
65 print_object(sha1, pathname); 65 print_object(sha1, pathname);
66 66
67 return 0; 67 return 0;
68} 68}
69 69
70void cgit_print_plain(struct cgit_context *ctx) 70void cgit_print_plain(struct cgit_context *ctx)
71{ 71{
72 const char *rev = ctx->qry.sha1; 72 const char *rev = ctx->qry.sha1;
73 unsigned char sha1[20]; 73 unsigned char sha1[20];
74 struct commit *commit; 74 struct commit *commit;
75 const char *paths[] = {ctx->qry.path, NULL}; 75 const char *paths[] = {ctx->qry.path, NULL};
76 76
77 if (!rev) 77 if (!rev)
78 rev = ctx->qry.head; 78 rev = ctx->qry.head;
79 79
80 curr_rev = xstrdup(rev); 80 curr_rev = xstrdup(rev);
81 if (get_sha1(rev, sha1)) { 81 if (get_sha1(rev, sha1)) {
82 html_status(404, "Not found", 0); 82 html_status(404, "Not found", 0);
83 return; 83 return;
84 } 84 }
85 commit = lookup_commit_reference(sha1); 85 commit = lookup_commit_reference(sha1);
86 if (!commit || parse_commit(commit)) { 86 if (!commit || parse_commit(commit)) {
87 html_status(404, "Not found", 0); 87 html_status(404, "Not found", 0);
88 return; 88 return;
89 } 89 }
90 match_path = ctx->qry.path; 90 match_path = ctx->qry.path;
91 read_tree_recursive(commit->tree, NULL, 0, 0, paths, walk_tree, NULL); 91 read_tree_recursive(commit->tree, "", 0, 0, paths, walk_tree, NULL);
92 if (!match) 92 if (!match)
93 html_status(404, "Not found", 0); 93 html_status(404, "Not found", 0);
94} 94}
diff --git a/ui-tree.c b/ui-tree.c
index f281937..94aff8f 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -1,291 +1,291 @@
1/* ui-tree.c: functions for tree output 1/* ui-tree.c: functions for tree 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 <ctype.h> 9#include <ctype.h>
10#include "cgit.h" 10#include "cgit.h"
11#include "html.h" 11#include "html.h"
12#include "ui-shared.h" 12#include "ui-shared.h"
13 13
14char *curr_rev; 14char *curr_rev;
15char *match_path; 15char *match_path;
16int header = 0; 16int header = 0;
17 17
18static void print_text_buffer(const char *name, char *buf, unsigned long size) 18static void print_text_buffer(const char *name, char *buf, unsigned long size)
19{ 19{
20 unsigned long lineno, idx; 20 unsigned long lineno, idx;
21 const char *numberfmt = 21 const char *numberfmt =
22 "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n"; 22 "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n";
23 23
24 html("<table summary='blob content' class='blob'>\n"); 24 html("<table summary='blob content' class='blob'>\n");
25 25
26 if (ctx.cfg.enable_tree_linenumbers) { 26 if (ctx.cfg.enable_tree_linenumbers) {
27 html("<tr><td class='linenumbers'><pre>"); 27 html("<tr><td class='linenumbers'><pre>");
28 idx = 0; 28 idx = 0;
29 lineno = 0; 29 lineno = 0;
30 30
31 if (size) { 31 if (size) {
32 htmlf(numberfmt, ++lineno); 32 htmlf(numberfmt, ++lineno);
33 while(idx < size - 1) { // skip absolute last newline 33 while(idx < size - 1) { // skip absolute last newline
34 if (buf[idx] == '\n') 34 if (buf[idx] == '\n')
35 htmlf(numberfmt, ++lineno); 35 htmlf(numberfmt, ++lineno);
36 idx++; 36 idx++;
37 } 37 }
38 } 38 }
39 html("</pre></td>\n"); 39 html("</pre></td>\n");
40 } 40 }
41 else { 41 else {
42 html("<tr>\n"); 42 html("<tr>\n");
43 } 43 }
44 44
45 if (ctx.repo->source_filter) { 45 if (ctx.repo->source_filter) {
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
62static void print_binary_buffer(char *buf, unsigned long size) 62static 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'>%04x</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
85static void print_object(const unsigned char *sha1, char *path, const char *basename) 85static 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 html(" ("); 105 html(" (");
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 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1)); 108 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1));
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 (%dKB) 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
123static int ls_item(const unsigned char *sha1, const char *base, int baselen, 123static 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);
136 136
137 if (!S_ISGITLINK(mode)) { 137 if (!S_ISGITLINK(mode)) {
138 type = sha1_object_info(sha1, &size); 138 type = sha1_object_info(sha1, &size);
139 if (type == OBJ_BAD) { 139 if (type == OBJ_BAD) {
140 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", 140 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>",
141 name, 141 name,
142 sha1_to_hex(sha1)); 142 sha1_to_hex(sha1));
143 return 0; 143 return 0;
144 } 144 }
145 } 145 }
146 146
147 html("<tr><td class='ls-mode'>"); 147 html("<tr><td class='ls-mode'>");
148 cgit_print_filemode(mode); 148 cgit_print_filemode(mode);
149 html("</td><td>"); 149 html("</td><td>");
150 if (S_ISGITLINK(mode)) { 150 if (S_ISGITLINK(mode)) {
151 htmlf("<a class='ls-mod' href='"); 151 htmlf("<a class='ls-mod' href='");
152 html_attr(fmt(ctx.repo->module_link, 152 html_attr(fmt(ctx.repo->module_link,
153 name, 153 name,
154 sha1_to_hex(sha1))); 154 sha1_to_hex(sha1)));
155 html("'>"); 155 html("'>");
156 html_txt(name); 156 html_txt(name);
157 html("</a>"); 157 html("</a>");
158 } else if (S_ISDIR(mode)) { 158 } else if (S_ISDIR(mode)) {
159 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, 159 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head,
160 curr_rev, fullpath); 160 curr_rev, fullpath);
161 } else { 161 } else {
162 class = strrchr(name, '.'); 162 class = strrchr(name, '.');
163 if (class != NULL) { 163 if (class != NULL) {
164 class = fmt("ls-blob %s", class + 1); 164 class = fmt("ls-blob %s", class + 1);
165 } else 165 } else
166 class = "ls-blob"; 166 class = "ls-blob";
167 cgit_tree_link(name, NULL, class, ctx.qry.head, 167 cgit_tree_link(name, NULL, class, ctx.qry.head,
168 curr_rev, fullpath); 168 curr_rev, fullpath);
169 } 169 }
170 htmlf("</td><td class='ls-size'>%li</td>", size); 170 htmlf("</td><td class='ls-size'>%li</td>", size);
171 171
172 html("<td>"); 172 html("<td>");
173 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, 173 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev,
174 fullpath, 0, NULL, NULL, ctx.qry.showmsg); 174 fullpath, 0, NULL, NULL, ctx.qry.showmsg);
175 if (ctx.repo->max_stats) 175 if (ctx.repo->max_stats)
176 cgit_stats_link("stats", NULL, "button", ctx.qry.head, 176 cgit_stats_link("stats", NULL, "button", ctx.qry.head,
177 fullpath); 177 fullpath);
178 html("</td></tr>\n"); 178 html("</td></tr>\n");
179 free(name); 179 free(name);
180 return 0; 180 return 0;
181} 181}
182 182
183static void ls_head() 183static void ls_head()
184{ 184{
185 html("<table summary='tree listing' class='list'>\n"); 185 html("<table summary='tree listing' class='list'>\n");
186 html("<tr class='nohover'>"); 186 html("<tr class='nohover'>");
187 html("<th class='left'>Mode</th>"); 187 html("<th class='left'>Mode</th>");
188 html("<th class='left'>Name</th>"); 188 html("<th class='left'>Name</th>");
189 html("<th class='right'>Size</th>"); 189 html("<th class='right'>Size</th>");
190 html("<th/>"); 190 html("<th/>");
191 html("</tr>\n"); 191 html("</tr>\n");
192 header = 1; 192 header = 1;
193} 193}
194 194
195static void ls_tail() 195static void ls_tail()
196{ 196{
197 if (!header) 197 if (!header)
198 return; 198 return;
199 html("</table>\n"); 199 html("</table>\n");
200 header = 0; 200 header = 0;
201} 201}
202 202
203static void ls_tree(const unsigned char *sha1, char *path) 203static void ls_tree(const unsigned char *sha1, char *path)
204{ 204{
205 struct tree *tree; 205 struct tree *tree;
206 206
207 tree = parse_tree_indirect(sha1); 207 tree = parse_tree_indirect(sha1);
208 if (!tree) { 208 if (!tree) {
209 cgit_print_error(fmt("Not a tree object: %s", 209 cgit_print_error(fmt("Not a tree object: %s",
210 sha1_to_hex(sha1))); 210 sha1_to_hex(sha1)));
211 return; 211 return;
212 } 212 }
213 213
214 ls_head(); 214 ls_head();
215 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL); 215 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL);
216 ls_tail(); 216 ls_tail();
217} 217}
218 218
219 219
220static int walk_tree(const unsigned char *sha1, const char *base, int baselen, 220static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
221 const char *pathname, unsigned mode, int stage, 221 const char *pathname, unsigned mode, int stage,
222 void *cbdata) 222 void *cbdata)
223{ 223{
224 static int state; 224 static int state;
225 static char buffer[PATH_MAX]; 225 static char buffer[PATH_MAX];
226 char *url; 226 char *url;
227 227
228 if (state == 0) { 228 if (state == 0) {
229 memcpy(buffer, base, baselen); 229 memcpy(buffer, base, baselen);
230 strcpy(buffer+baselen, pathname); 230 strcpy(buffer+baselen, pathname);
231 url = cgit_pageurl(ctx.qry.repo, "tree", 231 url = cgit_pageurl(ctx.qry.repo, "tree",
232 fmt("h=%s&amp;path=%s", curr_rev, buffer)); 232 fmt("h=%s&amp;path=%s", curr_rev, buffer));
233 html("/"); 233 html("/");
234 cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head, 234 cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head,
235 curr_rev, buffer); 235 curr_rev, buffer);
236 236
237 if (strcmp(match_path, buffer)) 237 if (strcmp(match_path, buffer))
238 return READ_TREE_RECURSIVE; 238 return READ_TREE_RECURSIVE;
239 239
240 if (S_ISDIR(mode)) { 240 if (S_ISDIR(mode)) {
241 state = 1; 241 state = 1;
242 ls_head(); 242 ls_head();
243 return READ_TREE_RECURSIVE; 243 return READ_TREE_RECURSIVE;
244 } else { 244 } else {
245 print_object(sha1, buffer, pathname); 245 print_object(sha1, buffer, pathname);
246 return 0; 246 return 0;
247 } 247 }
248 } 248 }
249 ls_item(sha1, base, baselen, pathname, mode, stage, NULL); 249 ls_item(sha1, base, baselen, pathname, mode, stage, NULL);
250 return 0; 250 return 0;
251} 251}
252 252
253 253
254/* 254/*
255 * Show a tree or a blob 255 * Show a tree or a blob
256 * rev: the commit pointing at the root tree object 256 * rev: the commit pointing at the root tree object
257 * path: path to tree or blob 257 * path: path to tree or blob
258 */ 258 */
259void cgit_print_tree(const char *rev, char *path) 259void cgit_print_tree(const char *rev, char *path)
260{ 260{
261 unsigned char sha1[20]; 261 unsigned char sha1[20];
262 struct commit *commit; 262 struct commit *commit;
263 const char *paths[] = {path, NULL}; 263 const char *paths[] = {path, NULL};
264 264
265 if (!rev) 265 if (!rev)
266 rev = ctx.qry.head; 266 rev = ctx.qry.head;
267 267
268 curr_rev = xstrdup(rev); 268 curr_rev = xstrdup(rev);
269 if (get_sha1(rev, sha1)) { 269 if (get_sha1(rev, sha1)) {
270 cgit_print_error(fmt("Invalid revision name: %s", rev)); 270 cgit_print_error(fmt("Invalid revision name: %s", rev));
271 return; 271 return;
272 } 272 }
273 commit = lookup_commit_reference(sha1); 273 commit = lookup_commit_reference(sha1);
274 if (!commit || parse_commit(commit)) { 274 if (!commit || parse_commit(commit)) {
275 cgit_print_error(fmt("Invalid commit reference: %s", rev)); 275 cgit_print_error(fmt("Invalid commit reference: %s", rev));
276 return; 276 return;
277 } 277 }
278 278
279 html("path: <a href='"); 279 html("path: <a href='");
280 html_attr(cgit_pageurl(ctx.qry.repo, "tree", fmt("h=%s", rev))); 280 html_attr(cgit_pageurl(ctx.qry.repo, "tree", fmt("h=%s", rev)));
281 html("'>root</a>"); 281 html("'>root</a>");
282 282
283 if (path == NULL) { 283 if (path == NULL) {
284 ls_tree(commit->tree->object.sha1, NULL); 284 ls_tree(commit->tree->object.sha1, NULL);
285 return; 285 return;
286 } 286 }
287 287
288 match_path = path; 288 match_path = path;
289 read_tree_recursive(commit->tree, NULL, 0, 0, paths, walk_tree, NULL); 289 read_tree_recursive(commit->tree, "", 0, 0, paths, walk_tree, NULL);
290 ls_tail(); 290 ls_tail();
291} 291}