Code

gitweb: fix another use of undefined value
[git.git] / gitweb / gitweb.perl
index c0e2473b40775b37a29adb666d43be06337dd790..6f5df9174ec80d4decf4be8111f84e79411a156d 100755 (executable)
@@ -102,10 +102,13 @@ our %feature = (
        #       'override' => allow-override (boolean),
        #       'default' => [ default options...] (array reference)}
        #
-       # if feature is overridable (it means that allow-override has true value,
+       # if feature is overridable (it means that allow-override has true value),
        # then feature-sub will be called with default options as parameters;
        # return value of feature-sub indicates if to enable specified feature
        #
+       # if there is no 'sub' key (no feature-sub), then feature cannot be
+       # overriden
+       #
        # use gitweb_check_feature(<feature>) to check if <feature> is enabled
 
        # Enable the 'blame' blob view, showing the last commit that modified
@@ -138,6 +141,7 @@ our %feature = (
 
        # Enable text search, which will list the commits which match author,
        # committer or commit text to a given string.  Enabled by default.
+       # Project specific override is not supported.
        'search' => {
                'override' => 0,
                'default' => [1]},
@@ -361,6 +365,7 @@ if (defined $page) {
 }
 
 our $searchtext = $cgi->param('s');
+our $search_regexp;
 if (defined $searchtext) {
        if ($searchtext =~ m/[^a-zA-Z0-9_\.\/\-\+\:\@ ]/) {
                die_error(undef, "Invalid search parameter");
@@ -368,7 +373,7 @@ if (defined $searchtext) {
        if (length($searchtext) < 2) {
                die_error(undef, "At least two characters are required for search parameter");
        }
-       $searchtext = quotemeta $searchtext;
+       $search_regexp = quotemeta $searchtext;
 }
 
 our $searchtype = $cgi->param('st');
@@ -458,10 +463,16 @@ my %actions = (
        "project_index" => \&git_project_index,
 );
 
-if (defined $project) {
-       $action ||= 'summary';
-} else {
-       $action ||= 'project_list';
+if (!defined $action) {
+       if (defined $hash) {
+               $action = git_get_type($hash);
+       } elsif (defined $hash_base && defined $file_name) {
+               $action = git_get_type("$hash_base:$file_name");
+       } elsif (defined $project) {
+               $action = 'summary';
+       } else {
+               $action = 'project_list';
+       }
 }
 if (!defined($actions{$action})) {
        die_error(undef, "Unknown action");
@@ -722,7 +733,9 @@ sub chop_str {
 sub age_class {
        my $age = shift;
 
-       if ($age < 60*60*2) {
+       if (!defined $age) {
+               return "noage";
+       } elsif ($age < 60*60*2) {
                return "age0";
        } elsif ($age < 60*60*24*2) {
                return "age1";
@@ -1054,6 +1067,11 @@ sub git_get_hash_by_path {
        my $line = <$fd>;
        close $fd or return undef;
 
+       if (!defined $line) {
+               # there is no tree or hash given by $path at $base
+               return undef;
+       }
+
        #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa  panic.c'
        $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t/;
        if (defined $type && $type ne $2) {
@@ -1096,7 +1114,9 @@ sub git_get_project_description {
        open my $fd, "$projectroot/$path/description" or return undef;
        my $descr = <$fd>;
        close $fd;
-       chomp $descr;
+       if (defined $descr) {
+               chomp $descr;
+       }
        return $descr;
 }
 
@@ -1247,7 +1267,8 @@ sub git_get_last_activity {
             'refs/heads') or return;
        my $most_recent = <$fd>;
        close $fd or return;
-       if ($most_recent =~ / (\d+) [-+][01]\d\d\d$/) {
+       if (defined $most_recent &&
+           $most_recent =~ / (\d+) [-+][01]\d\d\d$/) {
                my $timestamp = $1;
                my $age = time - $timestamp;
                return ($age, age_string($age));
@@ -1370,8 +1391,12 @@ sub parse_commit_text {
 
        pop @commit_lines; # Remove '\0'
 
+       if (! @commit_lines) {
+               return;
+       }
+
        my $header = shift @commit_lines;
-       if (!($header =~ m/^[0-9a-fA-F]{40}/)) {
+       if ($header !~ m/^[0-9a-fA-F]{40}/) {
                return;
        }
        ($co{'id'}, my @parents) = split ' ', $header;
@@ -2654,9 +2679,10 @@ sub git_patchset_body {
                # check if current patch belong to current raw line
                # and parse raw git-diff line if needed
                if (defined $diffinfo &&
+                   defined $from_id && defined $to_id &&
                    from_ids_eq($diffinfo->{'from_id'}, $from_id) &&
                    $diffinfo->{'to_id'} eq $to_id) {
-                       # this is split patch
+                       # this is continuation of a split patch
                        print "<div class=\"patch cont\">\n";
                } else {
                        # advance raw git-diff output if needed
@@ -2853,7 +2879,14 @@ sub git_patchset_body {
        } continue {
                print "</div>\n"; # class="patch"
        }
-       print "<div class=\"diff nodifferences\">No differences found</div>\n" if (!$patch_number);
+
+       if ($patch_number == 0) {
+               if (@hash_parents > 1) {
+                       print "<div class=\"diff nodifferences\">Trivial merge</div>\n";
+               } else {
+                       print "<div class=\"diff nodifferences\">No differences found</div>\n";
+               }
+       }
 
        print "</div>\n"; # class="patchset"
 }
@@ -2967,7 +3000,7 @@ sub git_project_list_body {
                                        esc_html($pr->{'descr'})) . "</td>\n" .
                      "<td><i>" . chop_str($pr->{'owner'}, 15) . "</i></td>\n";
                print "<td class=\"". age_class($pr->{'age'}) . "\">" .
-                     $pr->{'age_string'} . "</td>\n" .
+                     (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "</td>\n" .
                      "<td class=\"link\">" .
                      $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary")}, "summary")   . " | " .
                      $cgi->a({-href => href(project=>$pr->{'path'}, action=>"shortlog")}, "shortlog") . " | " .
@@ -3221,7 +3254,7 @@ sub git_search_grep_body {
                               esc_html(chop_str($co{'title'}, 50)) . "<br/>");
                my $comment = $co{'comment'};
                foreach my $line (@$comment) {
-                       if ($line =~ m/^(.*)($searchtext)(.*)$/i) {
+                       if ($line =~ m/^(.*)($search_regexp)(.*)$/i) {
                                my $lead = esc_html($1) || "";
                                $lead = chop_str($lead, 30, 10);
                                my $match = esc_html($2) || "";
@@ -3319,7 +3352,7 @@ sub git_project_index {
 sub git_summary {
        my $descr = git_get_project_description($project) || "none";
        my %co = parse_commit("HEAD");
-       my %cd = parse_date($co{'committer_epoch'}, $co{'committer_tz'});
+       my %cd = %co ? parse_date($co{'committer_epoch'}, $co{'committer_tz'}) : ();
        my $head = $co{'id'};
 
        my $owner = git_get_project_owner($project);
@@ -3342,8 +3375,11 @@ sub git_summary {
        print "<div class=\"title\">&nbsp;</div>\n";
        print "<table cellspacing=\"0\">\n" .
              "<tr><td>description</td><td>" . esc_html($descr) . "</td></tr>\n" .
-             "<tr><td>owner</td><td>$owner</td></tr>\n" .
-             "<tr><td>last change</td><td>$cd{'rfc2822'}</td></tr>\n";
+             "<tr><td>owner</td><td>$owner</td></tr>\n";
+       if (defined $cd{'rfc2822'}) {
+               print "<tr><td>last change</td><td>$cd{'rfc2822'}</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 = "URL";
@@ -3366,11 +3402,13 @@ sub git_summary {
 
        # we need to request one more than 16 (0..15) to check if
        # those 16 are all
-       my @commitlist = parse_commits($head, 17);
-       git_print_header_div('shortlog');
-       git_shortlog_body(\@commitlist, 0, 15, $refs,
-                         $#commitlist <=  15 ? undef :
-                         $cgi->a({-href => href(action=>"shortlog")}, "..."));
+       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")}, "..."));
+       }
 
        if (@taglist) {
                git_print_header_div('tags');
@@ -3402,6 +3440,11 @@ sub git_tag {
        git_header_html();
        git_print_page_nav('','', $head,undef,$head);
        my %tag = parse_tag($hash);
+
+       if (! %tag) {
+               die_error(undef, "Unknown tag object");
+       }
+
        git_print_header_div('commit', esc_html($tag{'name'}), $hash);
        print "<div class=\"title_text\">\n" .
              "<table cellspacing=\"0\">\n" .
@@ -4026,14 +4069,13 @@ sub git_commit {
                $parent = "--root";
        }
        my @difftree;
-       if (@$parents <= 1) {
-               # difftree output is not printed for merges
-               open my $fd, "-|", git_cmd(), "diff-tree", '-r', "--no-commit-id",
-                       @diff_opts, $parent, $hash, "--"
-                       or die_error(undef, "Open git-diff-tree failed");
-               @difftree = map { chomp; $_ } <$fd>;
-               close $fd or die_error(undef, "Reading git-diff-tree failed");
-       }
+       open my $fd, "-|", git_cmd(), "diff-tree", '-r', "--no-commit-id",
+               @diff_opts,
+               (@$parents <= 1 ? $parent : '-c'),
+               $hash, "--"
+               or die_error(undef, "Open git-diff-tree failed");
+       @difftree = map { chomp; $_ } <$fd>;
+       close $fd or die_error(undef, "Reading git-diff-tree failed");
 
        # non-textual hash id's can be cached
        my $expires;
@@ -4111,10 +4153,7 @@ sub git_commit {
        git_print_log($co{'comment'});
        print "</div>\n";
 
-       if (@$parents <= 1) {
-               # do not output difftree/whatchanged for merges
-               git_difftree_body(\@difftree, $hash, $parent);
-       }
+       git_difftree_body(\@difftree, $hash, @$parents);
 
        git_footer_html();
 }
@@ -4597,7 +4636,7 @@ sub git_search {
                } elsif ($searchtype eq 'committer') {
                        $greptype = "--committer=";
                }
-               $greptype .= $searchtext;
+               $greptype .= $search_regexp;
                my @commitlist = parse_commits($hash, 101, (100 * $page), $greptype);
 
                my $paging_nav = '';