]> Lady’s Gitweb - Gitweb/blobdiff - gitweb.perl
gitweb: add project_filter to limit project list to a subdirectory
[Gitweb] / gitweb.perl
index fb4cf84d591c40e9071c26ca7d1b0262bec5802088a2bedbf97eaff60701952a..a1bf9f5e3f8a8773c721c6caa9b6c393d9239b4a31a9cf76858e692f8795e4eb 100755 (executable)
@@ -761,6 +761,7 @@ our @cgi_param_mapping = (
        search_use_regexp => "sr",
        ctag => "by_tag",
        diff_style => "ds",
        search_use_regexp => "sr",
        ctag => "by_tag",
        diff_style => "ds",
+       project_filter => "pf",
        # this must be last entry (for manipulation from JavaScript)
        javascript => "js"
 );
        # 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,
 
 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) {
 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)) {
        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);
        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");
                } 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 {
                } elsif (defined $project) {
                        $action = 'summary';
                } else {
@@ -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 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
 
        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 || '';
 
 sub git_get_projects_list {
        my $filter = shift || '';
+       my $paranoid = shift;
        my @list;
 
        my @list;
 
-       $filter =~ s/\.git$//;
-
        if (-d $projects_list) {
                # search in directory
                my $dir = $projects_list;
                # remove the trailing "/"
                $dir =~ s!/+$!!;
        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
                # when filtering, search only given subdirectory
-               if ($filter) {
+               if ($filter && !$paranoid) {
                        $dir .= "/$filter";
                        $dir =~ s!/+$!!;
                }
                        $dir .= "/$filter";
                        $dir =~ s!/+$!!;
                }
@@ -2865,6 +2874,10 @@ sub git_get_projects_list {
                                }
 
                                my $path = substr($File::Find::name, $pfxlen + 1);
                                }
 
                                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 };
                                # 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);
 
 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);
        $title .= " - " . to_utf8($project);
 
        return $title unless (defined $action);
@@ -5837,7 +5855,7 @@ sub git_search_files {
        my %co = @_;
 
        local $/ = "\n";
        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");
                $search_use_regexp ? ('-E', '-i') : '-F',
                $searchtext, $co{'tree'}
                        or die_error(500, "Open git-grep failed");
@@ -5853,13 +5871,14 @@ sub git_search_files {
        my $lastfile = '';
        while (my $line = <$fd>) {
                chomp $line;
        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 {
                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";
                }
                if ($file ne $lastfile) {
                        $lastfile and print "</td></tr>\n";
@@ -5868,10 +5887,10 @@ sub git_search_files {
                        } else {
                                print "<tr class=\"light\">\n";
                        }
                        } else {
                                print "<tr class=\"light\">\n";
                        }
+                       $file_href = href(action=>"blob", hash_base=>$co{'id'},
+                                         file_name=>$file);
                        print "<td class=\"list\">".
                        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;
                }
                        print "</td><td>\n";
                        $lastfile = $file;
                }
@@ -5889,10 +5908,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 => 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) {
                }
        }
        if ($lastfile) {
@@ -5980,7 +5998,7 @@ sub git_project_list {
                die_error(400, "Unknown order parameter");
        }
 
                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");
        }
        if (!@list) {
                die_error(404, "No projects found");
        }
@@ -6006,7 +6024,9 @@ sub git_forks {
                die_error(400, "Unknown order parameter");
        }
 
                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");
        }
        if (!@list) {
                die_error(404, "No forks found");
        }
@@ -6019,7 +6039,7 @@ sub git_forks {
 }
 
 sub git_project_index {
 }
 
 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");
        }
        if (!@projects) {
                die_error(404, "No projects found");
        }
@@ -6065,7 +6085,9 @@ sub git_summary {
 
        if ($check_forks) {
                # find forks of a project
 
        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);
                # filter out forks of forks
                @forklist = filter_forks_from_projects_list(\@forklist)
                        if (@forklist);
@@ -7856,7 +7878,7 @@ sub git_atom {
 }
 
 sub git_opml {
 }
 
 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");
        }
        if (!@list) {
                die_error(404, "No projects found");
        }
@@ -7867,11 +7889,17 @@ sub git_opml {
                -content_disposition => 'inline; filename="opml.xml"');
 
        my $title = esc_html($site_name);
                -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>
        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">
 </head>
 <body>
 <outline text="git RSS feeds">
This page took 0.29299 seconds and 4 git commands to generate.