]> Lady’s Gitweb - Gitweb/blobdiff - gitweb.perl
gitweb: show active project_filter in project_list page header
[Gitweb] / gitweb.perl
index 0dbca9d055cf5f67cba476952780d4cd05f0e1d0b96efd080751cd1f1462f179..c242588ce5b89870ed5addf6f9f26b3eab6a46c134fc496e440782c0dc0a23e7 100755 (executable)
@@ -761,6 +761,7 @@ our @cgi_param_mapping = (
        search_use_regexp => "sr",
        ctag => "by_tag",
        diff_style => "ds",
+       project_filter => "pf",
        # this must be last entry (for manipulation from JavaScript)
        javascript => "js"
 );
@@ -977,7 +978,7 @@ sub evaluate_path_info {
 
 our ($action, $project, $file_name, $file_parent, $hash, $hash_parent, $hash_base,
      $hash_parent_base, @extra_options, $page, $searchtype, $search_use_regexp,
-     $searchtext, $search_regexp);
+     $searchtext, $search_regexp, $project_filter);
 sub evaluate_and_validate_params {
        our $action = $input_params{'action'};
        if (defined $action) {
@@ -995,6 +996,13 @@ sub evaluate_and_validate_params {
                }
        }
 
+       our $project_filter = $input_params{'project_filter'};
+       if (defined $project_filter) {
+               if (!validate_pathname($project_filter)) {
+                       die_error(404, "Invalid project_filter parameter");
+               }
+       }
+
        our $file_name = $input_params{'file_name'};
        if (defined $file_name) {
                if (!validate_pathname($file_name)) {
@@ -1124,8 +1132,10 @@ sub dispatch {
        if (!defined $action) {
                if (defined $hash) {
                        $action = git_get_type($hash);
+                       $action or die_error(404, "Object does not exist");
                } elsif (defined $hash_base && defined $file_name) {
                        $action = git_get_type("$hash_base:$file_name");
+                       $action or die_error(404, "File or directory does not exist");
                } elsif (defined $project) {
                        $action = 'summary';
                } else {
@@ -1444,8 +1454,8 @@ sub validate_refname {
 sub to_utf8 {
        my $str = shift;
        return undef unless defined $str;
-       if (utf8::valid($str)) {
-               utf8::decode($str);
+
+       if (utf8::is_utf8($str) || utf8::decode($str)) {
                return $str;
        } else {
                return decode($fallback_encoding, $str, Encode::FB_DEFAULT);
@@ -2392,7 +2402,7 @@ sub get_feed_info {
        return unless (defined $project);
        # some views should link to OPML, or to generic project feed,
        # or don't have specific feed yet (so they should use generic)
-       return if ($action =~ /^(?:tags|heads|forks|tag|search)$/x);
+       return if (!$action || $action =~ /^(?:tags|heads|forks|tag|search)$/x);
 
        my $branch;
        # branches refs uses 'refs/heads/' prefix (fullname) to differentiate
@@ -2828,19 +2838,18 @@ sub git_get_project_url_list {
 
 sub git_get_projects_list {
        my $filter = shift || '';
+       my $paranoid = shift;
        my @list;
 
-       $filter =~ s/\.git$//;
-
        if (-d $projects_list) {
                # search in directory
                my $dir = $projects_list;
                # remove the trailing "/"
                $dir =~ s!/+$!!;
-               my $pfxlen = length("$projects_list");
-               my $pfxdepth = ($projects_list =~ tr!/!!);
+               my $pfxlen = length("$dir");
+               my $pfxdepth = ($dir =~ tr!/!!);
                # when filtering, search only given subdirectory
-               if ($filter) {
+               if ($filter && !$paranoid) {
                        $dir .= "/$filter";
                        $dir =~ s!/+$!!;
                }
@@ -2865,6 +2874,10 @@ sub git_get_projects_list {
                                }
 
                                my $path = substr($File::Find::name, $pfxlen + 1);
+                               # paranoidly only filter here
+                               if ($paranoid && $filter && $path !~ m!^\Q$filter\E/!) {
+                                       next;
+                               }
                                # we check related file in $projectroot
                                if (check_export_ok("$projectroot/$path")) {
                                        push @list, { path => $path };
@@ -3730,7 +3743,12 @@ sub run_highlighter {
 sub get_page_title {
        my $title = to_utf8($site_name);
 
-       return $title unless (defined $project);
+       unless (defined $project) {
+               if (defined $project_filter) {
+                       $title .= " - " . to_utf8($project_filter);
+               }
+               return $title;
+       }
        $title .= " - " . to_utf8($project);
 
        return $title unless (defined $action);
@@ -3824,6 +3842,18 @@ sub print_header_links {
        }
 }
 
+sub print_nav_breadcrumbs_path {
+       my $dirprefix = undef;
+       while (my $part = shift) {
+               $dirprefix .= "/" if defined $dirprefix;
+               $dirprefix .= $part;
+               print $cgi->a({-href => href(project => undef,
+                                            project_filter => $dirprefix,
+                                            action => "project_list")},
+                             esc_html($part)) . " / ";
+       }
+}
+
 sub print_nav_breadcrumbs {
        my %opts = @_;
 
@@ -3842,6 +3872,8 @@ sub print_nav_breadcrumbs {
                        print " / $opts{-action_extra}";
                }
                print "\n";
+       } elsif (defined $project_filter) {
+               print_nav_breadcrumbs_path(split '/', $project_filter);
        }
 }
 
@@ -3964,9 +3996,11 @@ sub git_footer_html {
                }
 
        } else {
-               print $cgi->a({-href => href(project=>undef, action=>"opml"),
+               print $cgi->a({-href => href(project=>undef, action=>"opml",
+                                            project_filter => $project_filter),
                              -class => $feed_class}, "OPML") . " ";
-               print $cgi->a({-href => href(project=>undef, action=>"project_index"),
+               print $cgi->a({-href => href(project=>undef, action=>"project_index",
+                                            project_filter => $project_filter),
                              -class => $feed_class}, "TXT") . "\n";
        }
        print "</div>\n"; # class="page_footer"
@@ -5837,7 +5871,7 @@ sub git_search_files {
        my %co = @_;
 
        local $/ = "\n";
-       open my $fd, "-|", git_cmd(), 'grep', '-n',
+       open my $fd, "-|", git_cmd(), 'grep', '-n', '-z',
                $search_use_regexp ? ('-E', '-i') : '-F',
                $searchtext, $co{'tree'}
                        or die_error(500, "Open git-grep failed");
@@ -5853,13 +5887,14 @@ sub git_search_files {
        my $lastfile = '';
        while (my $line = <$fd>) {
                chomp $line;
-               my ($file, $lno, $ltext, $binary);
+               my ($file, $file_href, $lno, $ltext, $binary);
                last if ($matches++ > 1000);
                if ($line =~ /^Binary file (.+) matches$/) {
                        $file = $1;
                        $binary = 1;
                } else {
-                       (undef, $file, $lno, $ltext) = split(/:/, $line, 4);
+                       ($file, $lno, $ltext) = split(/\0/, $line, 3);
+                       $file =~ s/^$co{'tree'}://;
                }
                if ($file ne $lastfile) {
                        $lastfile and print "</td></tr>\n";
@@ -5868,10 +5903,10 @@ sub git_search_files {
                        } else {
                                print "<tr class=\"light\">\n";
                        }
+                       $file_href = href(action=>"blob", hash_base=>$co{'id'},
+                                         file_name=>$file);
                        print "<td class=\"list\">".
-                               $cgi->a({-href => href(action=>"blob", hash=>$co{'hash'},
-                                                      file_name=>"$file"),
-                                       -class => "list"}, esc_path($file));
+                               $cgi->a({-href => $file_href, -class => "list"}, esc_path($file));
                        print "</td><td>\n";
                        $lastfile = $file;
                }
@@ -5889,10 +5924,9 @@ sub git_search_files {
                                $ltext = esc_html($ltext, -nbsp=>1);
                        }
                        print "<div class=\"pre\">" .
-                               $cgi->a({-href => href(action=>"blob", hash=>$co{'hash'},
-                                                      file_name=>"$file").'#l'.$lno,
-                                       -class => "linenr"}, sprintf('%4i', $lno))
-                               . ' ' .  $ltext . "</div>\n";
+                               $cgi->a({-href => $file_href.'#l'.$lno,
+                                       -class => "linenr"}, sprintf('%4i', $lno)) .
+                               ' ' .  $ltext . "</div>\n";
                }
        }
        if ($lastfile) {
@@ -5980,7 +6014,7 @@ sub git_project_list {
                die_error(400, "Unknown order parameter");
        }
 
-       my @list = git_get_projects_list();
+       my @list = git_get_projects_list($project_filter, $strict_export);
        if (!@list) {
                die_error(404, "No projects found");
        }
@@ -6006,7 +6040,9 @@ sub git_forks {
                die_error(400, "Unknown order parameter");
        }
 
-       my @list = git_get_projects_list($project);
+       my $filter = $project;
+       $filter =~ s/\.git$//;
+       my @list = git_get_projects_list($filter);
        if (!@list) {
                die_error(404, "No forks found");
        }
@@ -6019,7 +6055,7 @@ sub git_forks {
 }
 
 sub git_project_index {
-       my @projects = git_get_projects_list();
+       my @projects = git_get_projects_list($project_filter, $strict_export);
        if (!@projects) {
                die_error(404, "No projects found");
        }
@@ -6065,7 +6101,9 @@ sub git_summary {
 
        if ($check_forks) {
                # find forks of a project
-               @forklist = git_get_projects_list($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);
@@ -7856,7 +7894,7 @@ sub git_atom {
 }
 
 sub git_opml {
-       my @list = git_get_projects_list();
+       my @list = git_get_projects_list($project_filter, $strict_export);
        if (!@list) {
                die_error(404, "No projects found");
        }
@@ -7867,11 +7905,17 @@ sub git_opml {
                -content_disposition => 'inline; filename="opml.xml"');
 
        my $title = esc_html($site_name);
+       my $filter = " within subdirectory ";
+       if (defined $project_filter) {
+               $filter .= esc_html($project_filter);
+       } else {
+               $filter = "";
+       }
        print <<XML;
 <?xml version="1.0" encoding="utf-8"?>
 <opml version="1.0">
 <head>
-  <title>$title OPML Export</title>
+  <title>$title OPML Export$filter</title>
 </head>
 <body>
 <outline text="git RSS feeds">
This page took 0.438002 seconds and 4 git commands to generate.