diff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi index 5eabe06daf..035e76d0a3 100755 --- a/gitweb/gitweb.cgi +++ b/gitweb/gitweb.cgi @@ -17,30 +17,50 @@ use Fcntl ':mode'; binmode STDOUT, ':utf8'; my $cgi = new CGI; -my $version = "267"; -my $my_url = $cgi->url(); -my $my_uri = $cgi->url(-absolute => 1); -my $rss_link = ""; - -# absolute fs-path which will be prepended to the project path -#my $projectroot = "/pub/scm"; -my $projectroot = "/home/kay/public_html/pub/scm"; +my $version = "267"; +my $my_url = $cgi->url(); +my $my_uri = $cgi->url(-absolute => 1); +my $rss_link = ""; # location of the git-core binaries -my $gitbin = "/usr/bin"; +my $gitbin = "/usr/bin"; + +# absolute fs-path which will be prepended to the project path +#my $projectroot = "/pub/scm"; +my $projectroot = "/home/kay/public_html/pub/scm"; + +# version of the git-core binaries +my $git_version = qx($gitbin/git --version); +if ($git_version =~ m/git version (.*)$/) { + $git_version = $1; +} else { + $git_version = "unknown"; +} # location for temporary files needed for diffs -my $git_temp = "/tmp/gitweb"; +my $git_temp = "/tmp/gitweb"; # target of the home link on top of all pages -my $home_link = $my_uri; +my $home_link = $my_uri; # html text to include at home page -my $home_text = "indextext.html"; +my $home_text = "indextext.html"; + +# URI of default stylesheet +my $stylesheet = "gitweb.css"; # source of projects list -#my $projects_list = $projectroot; -my $projects_list = "index/index.aux"; +#my $projects_list = $projectroot; +my $projects_list = "index/index.aux"; + +# default blob_plain mimetype and default charset for text/plain blob +my $default_blob_plain_mimetype = 'text/plain'; +my $default_text_plain_charset = undef; + +# file to use for guessing MIME types before trying /etc/mime.types +# (relative to the current git repository) +my $mimetypes_file = undef; + # input validation and dispatch my $action = $cgi->param('a'); @@ -66,8 +86,9 @@ if (defined $order) { } } -my $project = $cgi->param('p'); +my $project = ($cgi->param('p') || $ENV{'PATH_INFO'}); if (defined $project) { + $project =~ s|^/||; $project =~ s|/$||; $project = validate_input($project); if (!defined($project)) { die_error(undef, "Invalid project parameter."); @@ -240,6 +261,19 @@ sub unquote { return $str; } +# CSS class for given age value (in seconds) +sub age_class { + my $age = shift; + + if ($age < 60*60*2) { + return "age0"; + } elsif ($age < 60*60*24*2) { + return "age1"; + } else { + return "age2"; + } +} + sub git_header_html { my $status = shift || "200 OK"; my $expires = shift; @@ -249,6 +283,12 @@ sub git_header_html { $title .= " - $project"; if (defined $action) { $title .= "/$action"; + if (defined $file_name) { + $title .= " - $file_name"; + if ($action eq "tree" && $file_name !~ m|/$|) { + $title .= "/"; + } + } } } print $cgi->header(-type=>'text/html', -charset => 'utf-8', -status=> $status, -expires => $expires); @@ -257,71 +297,13 @@ sub git_header_html { +
" . $cgi->a({-href => "$my_uri?" . esc_param("p=$pr->{'path'};a=summary"), -class => "list"}, esc_html($pr->{'path'})) . " | \n" . "$pr->{'descr'} | \n" . "" . chop_str($pr->{'owner'}, 15) . " | \n"; - my $colored_age; - if ($pr->{'commit'}{'age'} < 60*60*2) { - $colored_age = "$pr->{'commit'}{'age_string'}"; - } elsif ($pr->{'commit'}{'age'} < 60*60*24*2) { - $colored_age = "$pr->{'commit'}{'age_string'}"; - } else { - $colored_age = "$pr->{'commit'}{'age_string'}"; - } - print "$colored_age | \n" . + print "{'commit'}{'age'}) . "\">" . $pr->{'commit'}{'age_string'} . " | \n" . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$pr->{'path'};a=summary")}, "summary") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$pr->{'path'};a=shortlog")}, "shortlog") . @@ -1102,7 +1078,7 @@ sub git_summary { " | "; if (length($co{'title_short'}) < length($co{'title'})) { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit"), -class => "list", -title => "$co{'title'}"}, - "" . esc_html($co{'title_short'}) . "$ref"); + "" . esc_html($co{'title_short'}) . "$ref"); } else { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit"), -class => "list"}, "" . esc_html($co{'title'}) . "$ref"); @@ -1160,7 +1136,7 @@ sub git_summary { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=$tag{'reftype'};h=$tag{'refid'}")}, $tag{'reftype'}); if ($tag{'reftype'} eq "commit") { print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$tag{'name'}")}, "shortlog") . - " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$tag{'refid'}")}, "log"); + " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$tag{'refid'}")}, "log"); } print " | \n" . "
Commit | Age | @@ -1302,7 +1278,7 @@ HTML my $data; my $age; my $age_str; - my $age_style; + my $age_class; chomp $line; $line_class_num = ($line_class_num + 1) % $line_class_len; @@ -1314,16 +1290,14 @@ HTML $lineno = $4; $data = $5; } else { - print qq(|||
---|---|---|---|---|
Unable to parse: $line | ||||
Unable to parse: $line | $short_rev.. | -$age_str | +$short_rev.. | +$age_str | $author | -$lineno | -$data | +$lineno | +$data | HTML } # while (my $line = <$fd>) @@ -1401,7 +1374,7 @@ sub git_tags { print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=$tag{'reftype'};h=$tag{'refid'}")}, $tag{'reftype'}); if ($tag{'reftype'} eq "commit") { print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$tag{'name'}")}, "shortlog") . - " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$tag{'refid'}")}, "log"); + " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$tag{'refid'}")}, "log"); } print "\n" . ""; @@ -1538,15 +1511,85 @@ sub git_blob { git_footer_html(); } +sub mimetype_guess_file { + my $filename = shift; + my $mimemap = shift; + -r $mimemap or return undef; + + my %mimemap; + open(MIME, $mimemap) or return undef; + while (
" . mode_str($t_mode) . " | \n"; + print "" . mode_str($t_mode) . " | \n"; if ($t_type eq "blob") { print "" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$t_hash$base_key;f=$base$t_name"), -class => "list"}, esc_html($t_name)) .
@@ -1724,8 +1767,8 @@ sub git_opml {
}
my $path = esc_html(chop_str($proj{'path'}, 25, 5));
- my $rss = "$my_url?p=$proj{'path'};a=rss";
- my $html = "$my_url?p=$proj{'path'};a=summary";
+ my $rss = "$my_url?p=$proj{'path'};a=rss";
+ my $html = "$my_url?p=$proj{'path'};a=summary";
print " | ||
$ad{'rfc2822'}"; if ($ad{'hour_local'} < 6) { - printf(" (%02d:%02d %s)", $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}); + printf(" (%02d:%02d %s)", $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}); } else { printf(" (%02d:%02d %s)", $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}); } @@ -1891,27 +1934,27 @@ sub git_commit { " | ||||
committer | " . esc_html($co{'committer'}) . " | |||
$cd{'rfc2822'}" . sprintf(" (%02d:%02d %s)", $cd{'hour_local'}, $cd{'minute_local'}, $cd{'tz_local'}) . " | ||||
commit | $co{'id'} | |||
commit | $co{'id'} | |||
tree | " . - "" . + " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash"), class => "list"}, $co{'tree'}) . " | " . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash")}, "tree") . " | " . "|
parent | " . - "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$par"), class => "list"}, $par) . " | " . + "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$par"), class => "list"}, $par) . " | " . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$par")}, "commit") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash;hp=$par")}, "commitdiff") . " | " . "
" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$to_id;hb=$hash;f=$file"), -class => "list"}, esc_html($file)) . " | \n" . - "[new " . file_type($to_mode) . "$mode_chng] | \n" . + "[new " . file_type($to_mode) . "$mode_chng] | \n" . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$to_id;hb=$hash;f=$file")}, "blob") . " | \n"; } elsif ($status eq "D") { print "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$from_id;hb=$hash;f=$file"), -class => "list"}, esc_html($file)) . " | \n" . - "[deleted " . file_type($from_mode). "] | \n" . + "[deleted " . file_type($from_mode). "] | \n" . "" . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$from_id;hb=$hash;f=$file")}, "blob") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;h=$hash;f=$file")}, "history") . @@ -1982,7 +2025,7 @@ sub git_commit { } elsif ($status eq "M" || $status eq "T") { my $mode_chnge = ""; if ($from_mode != $to_mode) { - $mode_chnge = " [changed"; + $mode_chnge = " [changed"; if (((oct $from_mode) & S_IFMT) != ((oct $to_mode) & S_IFMT)) { $mode_chnge .= " from " . file_type($from_mode) . " to " . file_type($to_mode); } @@ -2018,7 +2061,7 @@ sub git_commit { } print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$to_id;hb=$hash;f=$to_file"), -class => "list"}, esc_html($to_file)) . " | \n" . - "[moved from " . + " | [moved from " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$from_id;hb=$hash;f=$from_file"), -class => "list"}, esc_html($from_file)) . " with " . (int $similarity) . "% similarity$mode_chng] | \n" . "" .
@@ -2378,7 +2421,7 @@ sub git_search {
my $match = esc_html($2) || "";
my $trail = esc_html($3) || "";
$trail = chop_str($trail, 30, 10);
- my $text = "$lead$match$trail";
+ my $text = "$lead$match$trail";
print chop_str($text, 80, 5) . " \n"; } } @@ -2427,7 +2470,7 @@ sub git_search { while (my $setref = shift @files) { my %set = %$setref; print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$set{'id'};hb=$co{'id'};f=$set{'file'}"), class => "list"}, - "" . esc_html($set{'file'}) . "") . + "" . esc_html($set{'file'}) . "") . " \n"; } print " | \n" .
diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css
new file mode 100644
index 0000000000..98410f5b6c
--- /dev/null
+++ b/gitweb/gitweb.css
@@ -0,0 +1,320 @@
+body {
+ font-family: sans-serif;
+ font-size: 12px;
+ border: solid #d9d8d1;
+ border-width: 1px;
+ margin: 10px;
+ background-color: #ffffff;
+ color: #000000;
+}
+
+a {
+ color: #0000cc;
+}
+
+a:hover, a:visited, a:active {
+ color: #880000;
+}
+
+div.page_header {
+ height: 25px;
+ padding: 8px;
+ font-size: 18px;
+ font-weight: bold;
+ background-color: #d9d8d1;
+}
+
+div.page_header a:visited, a.header {
+ color: #0000cc;
+}
+
+div.page_header a:hover {
+ color: #880000;
+}
+
+div.page_nav {
+ padding: 8px;
+}
+
+div.page_nav a:visited {
+ color: #0000cc;
+}
+
+div.page_path {
+ padding: 8px;
+ border: solid #d9d8d1;
+ border-width: 0px 0px 1px;
+}
+
+div.page_footer {
+ height: 17px;
+ padding: 4px 8px;
+ background-color: #d9d8d1;
+}
+
+div.page_footer_text {
+ float: left;
+ color: #555555;
+ font-style: italic;
+}
+
+div.page_body {
+ padding: 8px;
+}
+
+div.title, a.title {
+ display: block;
+ padding: 6px 8px;
+ font-weight: bold;
+ background-color: #edece6;
+ text-decoration: none;
+ color: #000000;
+}
+
+a.title:hover {
+ background-color: #d9d8d1;
+}
+
+div.title_text {
+ padding: 6px 0px;
+ border: solid #d9d8d1;
+ border-width: 0px 0px 1px;
+}
+
+div.log_body {
+ padding: 8px 8px 8px 150px;
+}
+
+span.age {
+ position: relative;
+ float: left;
+ width: 142px;
+ font-style: italic;
+}
+
+div.page_body span.signoff {
+ color: #888888;
+}
+
+div.log_link {
+ padding: 0px 8px;
+ font-size: 10px;
+ font-family: sans-serif;
+ font-style: normal;
+ position: relative;
+ float: left;
+ width: 136px;
+}
+
+div.list_head {
+ padding: 6px 8px 4px;
+ border: solid #d9d8d1;
+ border-width: 1px 0px 0px;
+ font-style: italic;
+}
+
+a.list {
+ text-decoration: none;
+ color: #000000;
+}
+
+a.list:hover {
+ text-decoration: underline;
+ color: #880000;
+}
+
+a.text {
+ text-decoration: none;
+ color: #0000cc;
+}
+
+a.text:visited {
+ text-decoration: none;
+ color: #880000;
+}
+
+a.text:hover {
+ text-decoration: underline;
+ color: #880000;
+}
+
+table {
+ padding: 8px 4px;
+}
+
+table.project_list, table.diff_tree {
+ border-spacing: 0;
+}
+
+table.blame {
+ border-collapse: collapse;
+}
+
+th {
+ padding: 2px 5px;
+ font-size: 12px;
+ text-align: left;
+}
+
+tr.light:hover {
+ background-color: #edece6;
+}
+
+tr.dark {
+ background-color: #f6f6f0;
+}
+
+tr.dark:hover {
+ background-color: #edece6;
+}
+
+td {
+ padding: 2px 5px;
+ font-size: 12px;
+ vertical-align: top;
+}
+
+td.link {
+ padding: 2px 5px;
+ font-family: sans-serif;
+ font-size: 10px;
+}
+
+td.sha1 {
+ font-family: monospace;
+}
+
+td.error {
+ color: red;
+ background-color: yellow;
+}
+
+table.diff_tree span.file_status.new {
+ color: #008000;
+}
+
+table.diff_tree span.file_status.deleted {
+ color: #c00000;
+}
+
+table.diff_tree span.file_status.moved,
+table.diff_tree span.file_status.mode_chnge {
+ color: #777777;
+}
+
+/* age2: 60*60*24*2 <= age */
+table.project_list td.age2, table.blame td.age2 {
+ font-style: italic;
+}
+
+/* age1: 60*60*2 <= age < 60*60*24*2 */
+table.project_list td.age1 {
+ color: #009900;
+ font-style: italic;
+}
+
+table.blame td.age1 {
+ color: #009900;
+ background: transparent;
+}
+
+/* age0: age < 60*60*2 */
+table.project_list td.age0 {
+ color: #009900;
+ font-style: italic;
+ font-weight: bold;
+}
+
+table.blame td.age0 {
+ color: #009900;
+ background: transparent;
+ font-weight: bold;
+}
+
+td.pre, div.pre, div.diff {
+ font-family: monospace;
+ font-size: 12px;
+ white-space: pre;
+}
+
+td.mode {
+ font-family: monospace;
+}
+
+div.diff.add {
+ color: #008800;
+}
+
+div.diff.rem {
+ color: #cc0000;
+}
+
+div.diff.chunk_header {
+ color: #990099;
+}
+
+div.diff_info {
+ font-family: monospace;
+ color: #000099;
+ background-color: #edece6;
+ font-style: italic;
+}
+
+div.index_include {
+ border: solid #d9d8d1;
+ border-width: 0px 0px 1px;
+ padding: 12px 8px;
+}
+
+div.search {
+ margin: 4px 8px;
+ position: absolute;
+ top: 56px;
+ right: 12px
+}
+
+td.linenr {
+ text-align: right;
+}
+
+a.linenr {
+ color: #999999;
+ text-decoration: none
+}
+
+a.rss_logo {
+ float: right;
+ padding: 3px 0px;
+ width: 35px;
+ line-height: 10px;
+ border: 1px solid;
+ border-color: #fcc7a5 #7d3302 #3e1a01 #ff954e;
+ color: #ffffff;
+ background-color: #ff6600;
+ font-weight: bold;
+ font-family: sans-serif;
+ font-size: 10px;
+ text-align: center;
+ text-decoration: none;
+}
+
+a.rss_logo:hover {
+ background-color: #ee5500;
+}
+
+span.tag {
+ padding: 0px 4px;
+ font-size: 10px;
+ font-weight: normal;
+ background-color: #ffffaa;
+ border: 1px solid;
+ border-color: #ffffcc #ffee00 #ffee00 #ffffcc;
+}
+
+span.atnight {
+ color: #cc0000;
+}
+
+span.match {
+ color: #e00000;
+}