Enabling `*.go` files in the syntax highlighter.
[gitweb-sgk] / gitweb.cgi
index 57b60c4..93d9600 100755 (executable)
@@ -118,10 +118,8 @@ our $favicon = "static/git-favicon.png";
 our $javascript = "static/gitweb.js";
 
 # URI and label (title) of GIT logo link
 our $javascript = "static/gitweb.js";
 
 # URI and label (title) of GIT logo link
-#our $logo_url = "http://www.kernel.org/pub/software/scm/git/docs/";
-#our $logo_label = "git documentation";
-our $logo_url = "http://git-scm.com/";
-our $logo_label = "git homepage";
+our $logo_url = "http://subgeniuskitty.com/";
+our $logo_label = "SGK Homepage";
 
 # source of projects list
 our $projects_list = "";
 
 # source of projects list
 our $projects_list = "";
@@ -277,7 +275,7 @@ our %highlight_basename = (
 our %highlight_ext = (
        # main extensions, defining name of syntax;
        # see files in /usr/share/highlight/langDefs/ directory
 our %highlight_ext = (
        # main extensions, defining name of syntax;
        # see files in /usr/share/highlight/langDefs/ directory
-       (map { $_ => $_ } qw(py rb java css js tex bib xml awk bat ini spec tcl sql)),
+       (map { $_ => $_ } qw(py rb java css js tex bib xml awk bat ini spec tcl sql go)),
        # alternate extensions, see /etc/highlight/filetypes.conf
        (map { $_ => 'c'   } qw(c h)),
        (map { $_ => 'sh'  } qw(sh bash zsh ksh)),
        # alternate extensions, see /etc/highlight/filetypes.conf
        (map { $_ => 'c'   } qw(c h)),
        (map { $_ => 'sh'  } qw(sh bash zsh ksh)),
@@ -3846,6 +3844,37 @@ sub insert_file {
        close $fd;
 }
 
        close $fd;
 }
 
+sub insert_html_file {
+       my $file_name = shift;
+       insert_file($file_name);
+}
+
+sub insert_text_file {
+       my $file_name = shift;
+
+       open my $fd, $file_name or die_error(500, "Couldn't open $file_name");
+
+       print "<pre>";
+       while (my $line = <$fd>) {
+               print to_utf8($line);
+       }
+       print "</pre>";
+}
+
+sub insert_markdown_file {
+       my $file_name = shift;
+
+       # TODO: Make this a config option?
+       my $markdown_cmd = "/usr/bin/markdown";
+
+       open my $fd, quote_command($markdown_cmd, $file_name)." |"
+               or die_error(500, "Couldn't open $file_name");
+
+       while (my $line = <$fd>) {
+               print to_utf8($line);
+       }
+}
+
 ## ......................................................................
 ## mimetype related functions
 
 ## ......................................................................
 ## mimetype related functions
 
@@ -4549,8 +4578,10 @@ sub git_print_page_path {
 
 
        print "<div class=\"page_path\">";
 
 
        print "<div class=\"page_path\">";
+       my $pretty_project = $project;
+       $pretty_project =~ s/\/\.git$//;
        print $cgi->a({-href => href(action=>"tree", hash_base=>$hb),
        print $cgi->a({-href => href(action=>"tree", hash_base=>$hb),
-                     -title => 'tree root'}, to_utf8("[$project]"));
+                     -title => 'tree root'}, to_utf8("[$pretty_project]"));
        print " / ";
        if (defined $name) {
                my @dirname = split '/', $name;
        print " / ";
        if (defined $name) {
                my @dirname = split '/', $name;
@@ -5727,9 +5758,11 @@ sub git_project_list_rows {
                        }
                        print "</td>\n";
                }
                        }
                        print "</td>\n";
                }
+               my $pretty_path = $pr->{'path'};
+               $pretty_path =~ s/\/\.git$//;
                print "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
                                        -class => "list"},
                print "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
                                        -class => "list"},
-                                      esc_html_match_hl($pr->{'path'}, $search_regexp)) .
+                                      esc_html_match_hl($pretty_path, $search_regexp)) .
                      "</td>\n" .
                      "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
                                        -class => "list",
                      "</td>\n" .
                      "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
                                        -class => "list",
@@ -6378,9 +6411,9 @@ sub git_search_files {
                                $ltext = esc_html($ltext, -nbsp=>1);
                        }
                        print "<div class=\"pre\">" .
                                $ltext = esc_html($ltext, -nbsp=>1);
                        }
                        print "<div class=\"pre\">" .
-                               $cgi->a({-href => $file_href.'#l'.$lno,
-                                       -class => "linenr"}, sprintf('%4i', $lno)) .
-                               ' ' .  $ltext . "</div>\n";
+                               "<a href=\"" . $file_href.'#l'.$lno . "\" " .
+                               "class=\"linenr\" unselectable-linenr=\"" . sprintf('%4i', $lno) . " \">" .
+                               "</a>" .  $ltext . "</div>\n";
                }
        }
        if ($lastfile) {
                }
        }
        if ($lastfile) {
@@ -6550,37 +6583,57 @@ sub git_summary {
        my @forklist;
        my $check_forks = gitweb_check_feature('forks');
 
        my @forklist;
        my $check_forks = gitweb_check_feature('forks');
 
-       if ($check_forks) {
-               # find forks of a project
-               my $filter = $project;
-               $filter =~ s/\.git$//;
-               @forklist = git_get_projects_list($filter);
-               # filter out forks of forks
-               @forklist = filter_forks_from_projects_list(\@forklist)
-                       if (@forklist);
+
+       if (!defined $hash_base) {
+               $hash_base = "HEAD";
+       }
+       if (!defined $hash) {
+               if (defined $file_name) {
+                       $hash = git_get_hash_by_path($hash_base, $file_name, "tree");
+               } else {
+                       $hash = $hash_base;
+               }
+       }
+       die_error(404, "No such tree") unless defined($hash);
+
+       my $show_sizes = gitweb_check_feature('show-sizes');
+       my $have_blame = gitweb_check_feature('blame');
+
+       my @entries = ();
+       {
+               local $/ = "\0";
+               open my $fd, "-|", git_cmd(), "ls-tree", '-z',
+                       ($show_sizes ? '-l' : ()), @extra_options, $hash
+                       or die_error(500, "Open git-ls-tree failed");
+               @entries = map { chomp; $_ } <$fd>;
+               close $fd
+                       or die_error(404, "Reading tree failed");
        }
 
        }
 
+       my $refs = git_get_references();
+       my $ref = format_ref_marker($refs, $hash_base);
        git_header_html();
        git_print_page_nav('summary','', $head);
        git_header_html();
        git_print_page_nav('summary','', $head);
+       my $basedir = '';
 
 
-       print "<div class=\"title\">&nbsp;</div>\n";
        print "<table class=\"projects_list\">\n" .
        print "<table class=\"projects_list\">\n" .
-             "<tr id=\"metadata_desc\"><td>description</td><td>" . esc_html($descr) . "</td></tr>\n";
+             "<tr id=\"metadata_desc\"><td>Description</td><td>" . esc_html($descr) . "</td></tr>\n";
         if ($owner and not $omit_owner) {
         if ($owner and not $omit_owner) {
-               print  "<tr id=\"metadata_owner\"><td>owner</td><td>" . esc_html($owner) . "</td></tr>\n";
+               print  "<tr id=\"metadata_owner\"><td>Owner</td><td>" . esc_html($owner) . "</td></tr>\n";
         }
        if (defined $cd{'rfc2822'}) {
         }
        if (defined $cd{'rfc2822'}) {
-               print "<tr id=\"metadata_lchange\"><td>last change</td>" .
+               print "<tr id=\"metadata_lchange\"><td>Last Change</td>" .
                      "<td>".format_timestamp_html(\%cd)."</td></tr>\n";
        }
 
        # use per project git URL list in $projectroot/$project/cloneurl
        # or make project git URL from git base URL and project name
                      "<td>".format_timestamp_html(\%cd)."</td></tr>\n";
        }
 
        # use per project git URL list in $projectroot/$project/cloneurl
        # or make project git URL from git base URL and project name
-       my $url_tag = "clone URL";
+       my $url_tag = "Clone URL";
        my @url_list = git_get_project_url_list($project);
        @url_list = map { "$_/$project" } @git_base_url_list unless @url_list;
        foreach my $git_url (@url_list) {
                next unless $git_url;
        my @url_list = git_get_project_url_list($project);
        @url_list = map { "$_/$project" } @git_base_url_list unless @url_list;
        foreach my $git_url (@url_list) {
                next unless $git_url;
+               $git_url =~ s/\.git$//;
                print format_repo_url($url_tag, $git_url);
                $url_tag = "";
        }
                print format_repo_url($url_tag, $git_url);
                $url_tag = "";
        }
@@ -6601,50 +6654,73 @@ sub git_summary {
 
        print "</table>\n";
 
 
        print "</table>\n";
 
-       # If XSS prevention is on, we don't include README.html.
-       # TODO: Allow a readme in some safe format.
-       if (!$prevent_xss && -s "$projectroot/$project/README.html") {
-               print "<div class=\"title\">readme</div>\n" .
-                     "<div class=\"readme\">\n";
-               insert_file("$projectroot/$project/README.html");
-               print "\n</div>\n"; # class="readme"
-       }
+       print "<div class=\"page_body\">\n";
+       print "<table class=\"tree\">\n";
+       my $alternate = 1;
+       # '..' (top directory) link if possible
+       if (defined $hash_base &&
+           defined $file_name && $file_name =~ m![^/]+$!) {
+               if ($alternate) {
+                       print "<tr class=\"dark\">\n";
+               } else {
+                       print "<tr class=\"light\">\n";
+               }
+               $alternate ^= 1;
 
 
-       # we need to request one more than 16 (0..15) to check if
-       # those 16 are all
-       my @commitlist = $head ? parse_commits($head, 17) : ();
-       if (@commitlist) {
-               git_print_header_div('shortlog');
-               git_shortlog_body(\@commitlist, 0, 15, $refs,
-                                 $#commitlist <=  15 ? undef :
-                                 $cgi->a({-href => href(action=>"shortlog")}, "..."));
-       }
+               my $up = $file_name;
+               $up =~ s!/?[^/]+$!!;
+               undef $up unless $up;
+               # based on git_print_tree_entry
+               print '<td class="mode">' . mode_str('040000') . "</td>\n";
+               print '<td class="size">&nbsp;</td>'."\n" if $show_sizes;
+               print '<td class="list">';
+               print $cgi->a({-href => href(action=>"tree",
+                                            hash_base=>$hash_base,
+                                            file_name=>$up)},
+                             "..");
+               print "</td>\n";
+               print "<td class=\"link\"></td>\n";
 
 
-       if (@taglist) {
-               git_print_header_div('tags');
-               git_tags_body(\@taglist, 0, 15,
-                             $#taglist <=  15 ? undef :
-                             $cgi->a({-href => href(action=>"tags")}, "..."));
+               print "</tr>\n";
        }
        }
+       foreach my $line (@entries) {
+               my %t = parse_ls_tree_line($line, -z => 1, -l => $show_sizes);
 
 
-       if (@headlist) {
-               git_print_header_div('heads');
-               git_heads_body(\@headlist, $head, 0, 15,
-                              $#headlist <= 15 ? undef :
-                              $cgi->a({-href => href(action=>"heads")}, "..."));
-       }
+               if ($alternate) {
+                       print "<tr class=\"dark\">\n";
+               } else {
+                       print "<tr class=\"light\">\n";
+               }
+               $alternate ^= 1;
+
+               git_print_tree_entry(\%t, $basedir, $hash_base, $have_blame);
 
 
-       if (%remotedata) {
-               git_print_header_div('remotes');
-               git_remotes_body(\%remotedata, 15, $head);
+               print "</tr>\n";
        }
        }
+       print "</table>\n" .
+             "</div>";
 
 
-       if (@forklist) {
-               git_print_header_div('forks');
-               git_project_list_body(\@forklist, 'age', 0, 15,
-                                     $#forklist <= 15 ? undef :
-                                     $cgi->a({-href => href(action=>"forks")}, "..."),
-                                     'no_header');
+       # If present, print one of the following, in order:
+       #       README.md, README.txt, README, README.html.
+       my $cwd_path = "$projectroot/$project";
+       $cwd_path =~ s/\.git$//;
+       $cwd_path = $cwd_path . $basedir;
+       if (!$prevent_xss && -s $cwd_path . "README.md") {
+               print "<div class=\"readme\">\n";
+               insert_markdown_file($cwd_path . "README.md");
+               print "\n</div>\n"; # class="readme"
+       } elsif (!$prevent_xss && -s $cwd_path . "README.txt") {
+               print "<div class=\"readme\">\n";
+               insert_text_file($cwd_path . "README.txt");
+               print "\n</div>\n"; # class="readme"
+       } elsif (!$prevent_xss && -s $cwd_path . "README") {
+               print "<div class=\"readme\">\n";
+               insert_text_file($cwd_path . "README");
+               print "\n</div>\n"; # class="readme"
+       } elsif (!$prevent_xss && -s $cwd_path . "README.html") {
+               print "<div class=\"readme\">\n";
+               insert_html_file($cwd_path . "README.html");
+               print "\n</div>\n"; # class="readme"
        }
 
        git_footer_html();
        }
 
        git_footer_html();
@@ -7126,13 +7202,20 @@ sub git_blob {
                      href(action=>"blob_plain", hash=>$hash,
                           hash_base=>$hash_base, file_name=>$file_name) .
                      qq!" />\n!;
                      href(action=>"blob_plain", hash=>$hash,
                           hash_base=>$hash_base, file_name=>$file_name) .
                      qq!" />\n!;
+       } elsif ($file_name =~ /\.md$/) {
+               my $absolute_file_name = "$projectroot/$project";
+               $absolute_file_name =~ s/\.git$//;
+               $absolute_file_name = $absolute_file_name . $file_name;
+               print "<div class=\"readme\">";
+               insert_markdown_file($absolute_file_name);
+               print "</div>";
        } else {
                my $nr;
                while (my $line = <$fd>) {
                        chomp $line;
                        $nr++;
                        $line = untabify($line);
        } else {
                my $nr;
                while (my $line = <$fd>) {
                        chomp $line;
                        $nr++;
                        $line = untabify($line);
-                       printf qq!<div class="pre"><a id="l%i" href="%s#l%i" class="linenr">%4i</a> %s</div>\n!,
+                       printf qq!<div class="pre"><a id="l%i" href="%s#l%i" class="linenr" unselectable-linenr="%4i "></a>%s</div>\n!,
                               $nr, esc_attr(href(-replay => 1)), $nr, $nr,
                               $highlight ? sanitize($line) : esc_html($line, -nbsp=>1);
                }
                               $nr, esc_attr(href(-replay => 1)), $nr, $nr,
                               $highlight ? sanitize($line) : esc_html($line, -nbsp=>1);
                }
@@ -7191,7 +7274,7 @@ sub git_tree {
                }
                git_print_page_nav('tree','', $hash_base, undef, undef,
                                   join(' | ', @views_nav));
                }
                git_print_page_nav('tree','', $hash_base, undef, undef,
                                   join(' | ', @views_nav));
-               git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash_base);
+               #git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash_base);
        } else {
                undef $hash_base;
                print "<div class=\"page_nav\">\n";
        } else {
                undef $hash_base;
                print "<div class=\"page_nav\">\n";
@@ -7250,6 +7333,30 @@ sub git_tree {
        }
        print "</table>\n" .
              "</div>";
        }
        print "</table>\n" .
              "</div>";
+
+       # If present, print one of the following, in order:
+       #       README.md, README.txt, README, README.html.
+       my $cwd_path = "$projectroot/$project";
+       $cwd_path =~ s/\.git$//;
+       $cwd_path = $cwd_path . $basedir;
+       if (!$prevent_xss && -s $cwd_path . "README.md") {
+               print "<div class=\"readme\">\n";
+               insert_markdown_file($cwd_path . "README.md");
+               print "\n</div>\n"; # class="readme"
+       } elsif (!$prevent_xss && -s $cwd_path . "README.txt") {
+               print "<div class=\"readme\">\n";
+               insert_text_file($cwd_path . "README.txt");
+               print "\n</div>\n"; # class="readme"
+       } elsif (!$prevent_xss && -s $cwd_path . "README") {
+               print "<div class=\"readme\">\n";
+               insert_text_file($cwd_path . "README");
+               print "\n</div>\n"; # class="readme"
+       } elsif (!$prevent_xss && -s $cwd_path . "README.html") {
+               print "<div class=\"readme\">\n";
+               insert_html_file($cwd_path . "README.html");
+               print "\n</div>\n"; # class="readme"
+       }
+
        git_footer_html();
 }
 
        git_footer_html();
 }
 
@@ -7631,7 +7738,7 @@ sub git_object {
 
 sub git_blobdiff {
        my $format = shift || 'html';
 
 sub git_blobdiff {
        my $format = shift || 'html';
-       my $diff_style = $input_params{'diff_style'} || 'inline';
+       my $diff_style = $input_params{'diff_style'} || 'sidebyside';
 
        my $fd;
        my @difftree;
 
        my $fd;
        my @difftree;
@@ -7792,7 +7899,7 @@ sub diff_style_nav {
 sub git_commitdiff {
        my %params = @_;
        my $format = $params{-format} || 'html';
 sub git_commitdiff {
        my %params = @_;
        my $format = $params{-format} || 'html';
-       my $diff_style = $input_params{'diff_style'} || 'inline';
+       my $diff_style = $input_params{'diff_style'} || 'sidebyside';
 
        my ($patch_max) = gitweb_get_feature('patches');
        if ($format eq 'patch') {
 
        my ($patch_max) = gitweb_get_feature('patches');
        if ($format eq 'patch') {