Skip to content

Commit 161332a

Browse files
author
Kay Sievers
committed
first working version
0 parents  commit 161332a

File tree

1 file changed

+320
-0
lines changed

1 file changed

+320
-0
lines changed

gitweb.pl

Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
#!/usr/bin/perl
2+
3+
# This file is licensed under the GPL v2, or a later version
4+
# (C) 2005, Kay Sievers <kay.sievers@vrfy.org>
5+
# (C) 2005, Christian Gierke <ch@gierke.de>
6+
7+
use strict;
8+
use warnings;
9+
use CGI qw(:standard :escapeHTML);
10+
use CGI::Carp qw(fatalsToBrowser);
11+
12+
my $cgi = new CGI;
13+
my $gitbin = "/home/kay/bin";
14+
my $gitroot = "/home/kay/public_html";
15+
my $gittmp = "/tmp";
16+
my $myself = $cgi->url(-relative => 1);
17+
18+
my $project = $cgi->param("project") || "";
19+
my $action = $cgi->param("action") || "";
20+
my $hash = $cgi->param("hash") || "";
21+
my $parent = $cgi->param("parent") || "";
22+
my $view_back = $cgi->param("view_back") || 60*60*24*2;
23+
my $projectroot = "$gitroot/$project";
24+
$ENV{'SHA1_FILE_DIRECTORY'} = "$projectroot/.git/objects";
25+
26+
$hash =~ s/[^0-9a-fA-F]//g;
27+
$parent =~ s/[^0-9a-fA-F]//g;
28+
$project =~ s/[^0-9a-zA-Z\-\._]//g;
29+
30+
sub header {
31+
print $cgi->header(-type => 'text/html; charset: utf-8');
32+
print <<EOF;
33+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
34+
<html>
35+
<head>
36+
<title>GIT</title>
37+
<style type="text/css">
38+
body { font-family: sans-serif; font-size: 12px; margin:25px; }
39+
div.main { border-width:1px; border-style:solid; border-color:#D9D8D1; }
40+
div.head1 { font-size:20px; padding:8px; background-color: #D9D8D1; font-weight:bold; }
41+
div.head2 { padding:8px; }
42+
td { padding:8px; margin:0px; font-family: sans-serif; font-size: 12px; }
43+
td.head1 { background-color: #D9D8D1; font-weight:bold; }
44+
td.head2 { background-color: #EDECE6; font-family: monospace; font-size:12px; }
45+
table.log { padding:0px; margin:0px; width:100%; }
46+
tr { vertical-align:top; }
47+
a { color:#0000cc; }
48+
a:hover { color:#880000; }
49+
a:visited { color:#880000; }
50+
a:active { color:#880000; }
51+
</style>
52+
</head>
53+
<body>
54+
EOF
55+
if ($project ne "") {
56+
print "<div class=\"main\">\n";
57+
print "<div class=\"head1\">" . $project . "</div>\n";
58+
print "<div class=\"head2\">\n";
59+
print $cgi->a({-href => "$myself?project=$project&action=show_tree"}, "Browse Project") . "<br/>\n";
60+
print "Show Log ";
61+
print $cgi->a({-href => "$myself?project=$project&action=show_log&view_back=" . 60*60*24}, "day") . "\n";
62+
print $cgi->a({-href => "$myself?project=$project&action=show_log&view_back=" . 60*60*24*7}, "week") . "\n";
63+
print $cgi->a({-href => "$myself?project=$project&action=show_log&view_back=" . 60*60*24*30}, "month") . "\n";
64+
print $cgi->a({-href => "$myself?project=$project&action=show_log&view_back=" . 60*60*24*365}, "year") . "<br/>\n";
65+
print "</div>\n";
66+
print "<br/><br/>\n";
67+
}
68+
}
69+
70+
sub footer {
71+
print "</div>";
72+
print $cgi->end_html();
73+
}
74+
75+
if ($project eq "") {
76+
open my $fd, "-|", "ls", "-1", $gitroot;
77+
my (@path) = map { chomp; $_ } <$fd>;
78+
close $fd;
79+
header();
80+
print "Projects:<br/><br/>\n";
81+
foreach my $line (@path) {
82+
if (-e "$gitroot/$line/.git/HEAD") {
83+
print $cgi->a({-href => "$myself?project=$line"}, $line) . "<br/>\n";
84+
}
85+
}
86+
footer();
87+
exit;
88+
}
89+
90+
if ($action eq "") {
91+
print $cgi->redirect("$myself?project=$project&action=show_log&view_back=$view_back");
92+
exit;
93+
}
94+
95+
if ($action eq "show_file") {
96+
header();
97+
print "<pre>\n";
98+
open my $fd, "-|", "$gitbin/cat-file", "blob", $hash;
99+
my $nr;
100+
while (my $line = <$fd>) {
101+
$nr++;
102+
print "$nr\t" . escapeHTML($line);;
103+
}
104+
close $fd;
105+
print "</pre>\n";
106+
footer();
107+
} elsif ($action eq "show_tree") {
108+
if ($hash eq "") {
109+
open my $fd, "$projectroot/.git/HEAD";
110+
my $head = <$fd>;
111+
chomp $head;
112+
close $fd;
113+
114+
open $fd, "-|", "$gitbin/cat-file", "commit", $head;
115+
my $tree = <$fd>;
116+
chomp $tree;
117+
$tree =~ s/tree //;
118+
close $fd;
119+
$hash = $tree;
120+
}
121+
open my $fd, "-|", "$gitbin/ls-tree", $hash;
122+
my (@entries) = map { chomp; $_ } <$fd>;
123+
close $fd;
124+
header();
125+
print "<pre>\n";
126+
foreach my $line (@entries) {
127+
$line =~ m/^([0-9]+)\t(.*)\t(.*)\t(.*)$/;
128+
my $t_type = $2;
129+
my $t_hash = $3;
130+
my $t_name = $4;
131+
if ($t_type eq "blob") {
132+
print "FILE\t" . $cgi->a({-href => "$myself?project=$project&action=show_file&hash=$3"}, $4) . "\n";
133+
} elsif ($t_type eq "tree") {
134+
print "DIR\t" . $cgi->a({-href => "$myself?project=$project&action=show_tree&hash=$3"}, $4) . "\n";
135+
}
136+
}
137+
print "</pre>\n";
138+
footer();
139+
} elsif ($action eq "show_log") {
140+
open my $fd, "$projectroot/.git/HEAD";
141+
my $head = <$fd>;
142+
chomp $head;
143+
close $fd;
144+
open my $fd, "-|", "$gitbin/rev-tree", $head;
145+
my (@revtree) = map { chomp; $_ } <$fd>;
146+
close $fd;
147+
header();
148+
print "<table cellspacing=\"0\" class=\"log\">\n";
149+
foreach my $rev (reverse sort @revtree) {
150+
if (!($rev =~ m/^([0-9]+) ([0-9a-fA-F]+).* ([0-9a-fA-F]+)/)) {
151+
last;
152+
}
153+
my $time = $1;
154+
my $commit = $2;
155+
my $parent = $3;
156+
my @parents;
157+
my $author;
158+
my $author_name;
159+
my $author_time;
160+
my $author_timezone;
161+
my $committer;
162+
my $committer_time;
163+
my $committer_timezone;
164+
my $tree;
165+
my $comment;
166+
my $shortlog;
167+
open my $fd, "-|", "$gitbin/cat-file", "commit", $commit;
168+
while (my $line = <$fd>) {
169+
chomp($line);
170+
if ($line eq "") {
171+
last;
172+
}
173+
if ($line =~ m/^tree (.*)$/) {
174+
$tree = $1;
175+
} elsif ($line =~ m/^parent (.*)$/) {
176+
push @parents, $1;
177+
} elsif ($line =~ m/^committer (.*>) ([0-9]+) (.*)$/) {
178+
$committer = $1;
179+
$committer_time = $2;
180+
$committer_timezone = $3;
181+
} elsif ($line =~ m/^author (.*>) ([0-9]+) (.*)$/) {
182+
$author = $1;
183+
$author_time = $2;
184+
$author_timezone = $3;
185+
$author =~ m/^(.*) </;
186+
$author_name = $1;
187+
}
188+
}
189+
$shortlog = <$fd>;
190+
$shortlog = escapeHTML($shortlog);
191+
$comment = $shortlog . "<br/>";
192+
while (my $line = <$fd>) {
193+
chomp($line);
194+
$comment .= escapeHTML($line) . "<br/>\n";
195+
}
196+
close $fd;
197+
my $age = time-$author_time;
198+
if ($view_back > 0 && $age > $view_back) {
199+
last;
200+
}
201+
202+
my $age_string;
203+
if ($age > 60*60*24*365*2) {
204+
$age_string = int $age/60/60/24/365;
205+
$age_string .= " years ago";
206+
} elsif ($age > 60*60*24*365/12*2) {
207+
$age_string = int $age/60/60/24/365/12;
208+
$age_string .= " months ago";
209+
} elsif ($age > 60*60*24*7*2) {
210+
$age_string = int $age/60/60/24/7;
211+
$age_string .= " weeks ago";
212+
} elsif ($age > 60*60*24*2) {
213+
$age_string = int $age/60/60/24;
214+
$age_string .= " days ago";
215+
} elsif ($age > 60*60*2) {
216+
$age_string = int $age/60/60;
217+
$age_string .= " hours ago";
218+
} elsif ($age > 60*2) {
219+
$age_string = int $age/60;
220+
$age_string .= " minutes ago";
221+
}
222+
print "<tr>\n";
223+
print "<td class=\"head1\">" . $age_string . "</td>\n";
224+
print "<td class=\"head1\"><a href=\"$myself?project=$project&amp;action=show_cset&amp;hash=$commit&amp;parent=$parent\">" . $shortlog . "</a></td>";
225+
print "</tr>\n";
226+
print "<tr>\n";
227+
print "<td class=\"head2\"></td>\n";
228+
print "<td class=\"head2\">\n";
229+
print "author &nbsp; &nbsp;" . escapeHTML($author) . " [" . gmtime($author_time) . " " . $author_timezone . "]<br/>\n";
230+
print "committer " . escapeHTML($committer) . " [" . gmtime($committer_time) . " " . $committer_timezone . "]<br/>\n";
231+
print "commit &nbsp; &nbsp;<a href=\"$myself?project=$project&amp;action=show_cset&amp;hash=$commit&amp;parent=$parent\">$commit</a><br/>\n";
232+
print "tree &nbsp; &nbsp; &nbsp;<a href=\"$myself?project=$project&amp;action=show_tree&amp;hash=$tree\">$tree</a><br/>\n";
233+
foreach my $par (@parents) {
234+
print "parent &nbsp; &nbsp;$par<br/>\n";
235+
}
236+
print "</td>";
237+
print "</tr>\n";
238+
print "<tr>\n";
239+
print "<td></td>\n";
240+
print "<td>\n";
241+
print "$comment<br/><br/>\n";
242+
print "</td>";
243+
print "</tr>\n";
244+
}
245+
print "</table>\n";
246+
footer();
247+
} elsif ($action eq "show_cset") {
248+
open my $fd, "-|", "$gitbin/cat-file", "commit", $hash;
249+
my $tree = <$fd>;
250+
chomp $tree;
251+
$tree =~ s/tree //;
252+
close $fd;
253+
254+
open my $fd, "-|", "$gitbin/cat-file", "commit", $parent;
255+
my $parent_tree = <$fd>;
256+
chomp $parent_tree;
257+
$parent_tree =~ s/tree //;
258+
close $fd;
259+
260+
open my $fd, "-|", "$gitbin/diff-tree", "-r", $parent_tree, $tree;
261+
my (@difftree) = map { chomp; $_ } <$fd>;
262+
close $fd;
263+
264+
header();
265+
print "<pre>\n";
266+
foreach my $line (@difftree) {
267+
$line =~ m/^(.)(.*)\t(.*)\t(.*)\t(.*)$/;
268+
my $op = $1;
269+
my $mode = $2;
270+
my $type = $3;
271+
my $id = $4;
272+
my $file = $5;
273+
if ($type eq "blob") {
274+
if ($op eq "+") {
275+
print "NEW\t" . $cgi->a({-href => "$myself?project=$project&action=show_file&hash=$id"}, $file) . "\n";
276+
} elsif ($op eq "-") {
277+
print "DEL\t" . $cgi->a({-href => "$myself?project=$project&action=show_file&hash=$id"}, $file) . "\n";
278+
} elsif ($op eq "*") {
279+
$id =~ m/([0-9a-fA-F]+)->([0-9a-fA-F]+)/;
280+
my $old = $1;
281+
my $new = $2;
282+
print "DIFF\t" . $cgi->a({-href => "$myself?project=$project&action=show_diff&hash=$old&parent=$new"}, $file) . "\n";
283+
}
284+
}
285+
}
286+
print "</pre>\n";
287+
footer();
288+
} elsif ($action eq "show_diff") {
289+
open my $fd2, "> $gittmp/$hash";
290+
open my $fd, "-|", "$gitbin/cat-file", "blob", $hash;
291+
while (my $line = <$fd>) {
292+
print $fd2 $line;
293+
}
294+
close $fd2;
295+
close $fd;
296+
297+
open my $fd2, "> $gittmp/$parent";
298+
open my $fd, "-|", "$gitbin/cat-file", "blob", $parent;
299+
while (my $line = <$fd>) {
300+
print $fd2 $line;
301+
}
302+
close $fd2;
303+
close $fd;
304+
305+
header();
306+
print "<pre>\n";
307+
open my $fd, "-|", "/usr/bin/diff", "-L", "$hash", "-L", "$parent", "-u", "-p", "$gittmp/$hash", "$gittmp/$parent";
308+
while (my $line = <$fd>) {
309+
print escapeHTML($line);
310+
}
311+
close $fd;
312+
unlink("$gittmp/$hash");
313+
unlink("$gittmp/$parent");
314+
print "</pre>\n";
315+
footer();
316+
} else {
317+
header();
318+
print "unknown action\n";
319+
footer();
320+
}

0 commit comments

Comments
 (0)