GIT 1.5.6.6
authorJunio C Hamano <gitster@pobox.com>
Wed, 17 Dec 2008 06:13:36 +0000 (22:13 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 17 Dec 2008 06:13:36 +0000 (22:13 -0800)
Signed-off-by: Junio C Hamano <gitster@pobox.com>
1  2 
Documentation/RelNotes-1.5.6.6.txt
RelNotes
gitweb/gitweb.perl
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..79da23db5ac65c8d828ff2345070206336eca012
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,10 @@@
++GIT v1.5.6.6 Release Notes
++==========================
++
++Fixes since 1.5.6.5
++-------------------
++
++ * Removed support for an obsolete gitweb request URI, whose
++   implementation ran "git diff" Porcelain, instead of using plumbing,
++   which would have run an external diff command specified in the
++   repository configuration as the gitweb user.
diff --combined RelNotes
index 1c0163594aeb2a323c8a0cb8965a5e3d8947ee2c,d94e74259b6dcd8b4645425b6381b050d24646af..6ca1d5b43948525e43c3c354dd424ab054772a95
+++ b/RelNotes
@@@ -1,1 -1,1 +1,1 @@@
- Documentation/RelNotes-1.5.6.5.txt
 -Documentation/RelNotes-1.5.5.6.txt
++Documentation/RelNotes-1.5.6.6.txt
diff --combined gitweb/gitweb.perl
index 49b01d8c25b7a7d9c850b5484414bfcfa9bbf85b,f37b687acb0fedad9386f829f632d340385ab0d4..f88ce35ce8542e271a737335a116684429de2127
@@@ -369,15 -369,10 +369,15 @@@ sub filter_snapshot_fmts 
  }
  
  our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++";
 -do $GITWEB_CONFIG if -e $GITWEB_CONFIG;
 +if (-e $GITWEB_CONFIG) {
 +      do $GITWEB_CONFIG;
 +} else {
 +      our $GITWEB_CONFIG_SYSTEM = $ENV{'GITWEB_CONFIG_SYSTEM'} || "++GITWEB_CONFIG_SYSTEM++";
 +      do $GITWEB_CONFIG_SYSTEM if -e $GITWEB_CONFIG_SYSTEM;
 +}
  
  # version of the core git binary
 -our $git_version = qx($GIT --version) =~ m/git version (.*)$/ ? $1 : "unknown";
 +our $git_version = qx("$GIT" --version) =~ m/git version (.*)$/ ? $1 : "unknown";
  
  $projects_list ||= $projectroot;
  
@@@ -592,7 -587,7 +592,7 @@@ exit
  ## ======================================================================
  ## action links
  
 -sub href(%) {
 +sub href (%) {
        my %params = @_;
        # default is to use -absolute url() i.e. $my_uri
        my $href = $params{-full} ? $my_url : $my_uri;
@@@ -866,10 -861,6 +866,10 @@@ sub chop_str 
        my $add_len = shift || 10;
        my $where = shift || 'right'; # 'left' | 'center' | 'right'
  
 +      # Make sure perl knows it is utf8 encoded so we don't
 +      # cut in the middle of a utf8 multibyte char.
 +      $str = to_utf8($str);
 +
        # allow only $len chars, but don't cut a word if it would fit in $add_len
        # if it doesn't fit, cut it if it's still longer than the dots we would add
        # remove chopped character entities entirely
@@@ -1452,46 -1443,6 +1452,46 @@@ sub format_snapshot_links 
        }
  }
  
 +## ......................................................................
 +## functions returning values to be passed, perhaps after some
 +## transformation, to other functions; e.g. returning arguments to href()
 +
 +# returns hash to be passed to href to generate gitweb URL
 +# in -title key it returns description of link
 +sub get_feed_info {
 +      my $format = shift || 'Atom';
 +      my %res = (action => lc($format));
 +
 +      # feed links are possible only for project views
 +      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);
 +
 +      my $branch;
 +      # branches refs uses 'refs/heads/' prefix (fullname) to differentiate
 +      # from tag links; this also makes possible to detect branch links
 +      if ((defined $hash_base && $hash_base =~ m!^refs/heads/(.*)$!) ||
 +          (defined $hash      && $hash      =~ m!^refs/heads/(.*)$!)) {
 +              $branch = $1;
 +      }
 +      # find log type for feed description (title)
 +      my $type = 'log';
 +      if (defined $file_name) {
 +              $type  = "history of $file_name";
 +              $type .= "/" if ($action eq 'tree');
 +              $type .= " on '$branch'" if (defined $branch);
 +      } else {
 +              $type = "log of $branch" if (defined $branch);
 +      }
 +
 +      $res{-title} = $type;
 +      $res{'hash'} = (defined $branch ? "refs/heads/$branch" : undef);
 +      $res{'file_name'} = $file_name;
 +
 +      return %res;
 +}
 +
  ## ----------------------------------------------------------------------
  ## git utility subroutines, invoking git commands
  
@@@ -1500,13 -1451,9 +1500,13 @@@ sub git_cmd 
        return $GIT, '--git-dir='.$git_dir;
  }
  
 -# returns path to the core git executable and the --git-dir parameter as string
 -sub git_cmd_str {
 -      return join(' ', git_cmd());
 +# quote the given arguments for passing them to the shell
 +# quote_command("command", "arg 1", "arg with ' and ! characters")
 +# => "'command' 'arg 1' 'arg with '\'' and '\!' characters'"
 +# Try to avoid using this function wherever possible.
 +sub quote_command {
 +      return join(' ',
 +                  map( { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ ));
  }
  
  # get HEAD ref of given project as hash
@@@ -2162,6 -2109,49 +2162,6 @@@ sub parse_commits 
        return wantarray ? @cos : \@cos;
  }
  
 -# parse ref from ref_file, given by ref_id, with given type
 -sub parse_ref {
 -      my $ref_file = shift;
 -      my $ref_id = shift;
 -      my $type = shift || git_get_type($ref_id);
 -      my %ref_item;
 -
 -      $ref_item{'type'} = $type;
 -      $ref_item{'id'} = $ref_id;
 -      $ref_item{'epoch'} = 0;
 -      $ref_item{'age'} = "unknown";
 -      if ($type eq "tag") {
 -              my %tag = parse_tag($ref_id);
 -              $ref_item{'comment'} = $tag{'comment'};
 -              if ($tag{'type'} eq "commit") {
 -                      my %co = parse_commit($tag{'object'});
 -                      $ref_item{'epoch'} = $co{'committer_epoch'};
 -                      $ref_item{'age'} = $co{'age_string'};
 -              } elsif (defined($tag{'epoch'})) {
 -                      my $age = time - $tag{'epoch'};
 -                      $ref_item{'epoch'} = $tag{'epoch'};
 -                      $ref_item{'age'} = age_string($age);
 -              }
 -              $ref_item{'reftype'} = $tag{'type'};
 -              $ref_item{'name'} = $tag{'name'};
 -              $ref_item{'refid'} = $tag{'object'};
 -      } elsif ($type eq "commit"){
 -              my %co = parse_commit($ref_id);
 -              $ref_item{'reftype'} = "commit";
 -              $ref_item{'name'} = $ref_file;
 -              $ref_item{'title'} = $co{'title'};
 -              $ref_item{'refid'} = $ref_id;
 -              $ref_item{'epoch'} = $co{'committer_epoch'};
 -              $ref_item{'age'} = $co{'age_string'};
 -      } else {
 -              $ref_item{'reftype'} = $type;
 -              $ref_item{'name'} = $ref_file;
 -              $ref_item{'refid'} = $ref_id;
 -      }
 -
 -      return %ref_item;
 -}
 -
  # parse line of git-diff-tree "raw" output
  sub parse_difftree_raw_line {
        my $line = shift;
@@@ -2442,7 -2432,8 +2442,7 @@@ sub blob_mimetype 
        return $default_blob_plain_mimetype unless $fd;
  
        if (-T $fd) {
 -              return 'text/plain' .
 -                     ($default_text_plain_charset ? '; charset='.$default_text_plain_charset : '');
 +              return 'text/plain';
        } elsif (! $filename) {
                return 'application/octet-stream';
        } elsif ($filename =~ m/\.png$/i) {
        }
  }
  
 +sub blob_contenttype {
 +      my ($fd, $file_name, $type) = @_;
 +
 +      $type ||= blob_mimetype($fd, $file_name);
 +      if ($type eq 'text/plain' && defined $default_text_plain_charset) {
 +              $type .= "; charset=$default_text_plain_charset";
 +      }
 +
 +      return $type;
 +}
 +
  ## ======================================================================
  ## functions printing HTML: header, footer, error page
  
                }
        }
        if (defined $project) {
 -              printf('<link rel="alternate" title="%s log RSS feed" '.
 -                     'href="%s" type="application/rss+xml" />'."\n",
 -                     esc_param($project), href(action=>"rss"));
 -              printf('<link rel="alternate" title="%s log RSS feed (no merges)" '.
 -                     'href="%s" type="application/rss+xml" />'."\n",
 -                     esc_param($project), href(action=>"rss",
 -                                               extra_options=>"--no-merges"));
 -              printf('<link rel="alternate" title="%s log Atom feed" '.
 -                     'href="%s" type="application/atom+xml" />'."\n",
 -                     esc_param($project), href(action=>"atom"));
 -              printf('<link rel="alternate" title="%s log Atom feed (no merges)" '.
 -                     'href="%s" type="application/atom+xml" />'."\n",
 -                     esc_param($project), href(action=>"atom",
 -                                               extra_options=>"--no-merges"));
 +              my %href_params = get_feed_info();
 +              if (!exists $href_params{'-title'}) {
 +                      $href_params{'-title'} = 'log';
 +              }
 +
 +              foreach my $format qw(RSS Atom) {
 +                      my $type = lc($format);
 +                      my %link_attr = (
 +                              '-rel' => 'alternate',
 +                              '-title' => "$project - $href_params{'-title'} - $format feed",
 +                              '-type' => "application/$type+xml"
 +                      );
 +
 +                      $href_params{'action'} = $type;
 +                      $link_attr{'-href'} = href(%href_params);
 +                      print "<link ".
 +                            "rel=\"$link_attr{'-rel'}\" ".
 +                            "title=\"$link_attr{'-title'}\" ".
 +                            "href=\"$link_attr{'-href'}\" ".
 +                            "type=\"$link_attr{'-type'}\" ".
 +                            "/>\n";
 +
 +                      $href_params{'extra_options'} = '--no-merges';
 +                      $link_attr{'-href'} = href(%href_params);
 +                      $link_attr{'-title'} .= ' (no merges)';
 +                      print "<link ".
 +                            "rel=\"$link_attr{'-rel'}\" ".
 +                            "title=\"$link_attr{'-title'}\" ".
 +                            "href=\"$link_attr{'-href'}\" ".
 +                            "type=\"$link_attr{'-type'}\" ".
 +                            "/>\n";
 +              }
 +
        } else {
                printf('<link rel="alternate" title="%s projects list" '.
 -                     'href="%s" type="text/plain; charset=utf-8"/>'."\n",
 +                     'href="%s" type="text/plain; charset=utf-8" />'."\n",
                       $site_name, href(project=>undef, action=>"project_index"));
                printf('<link rel="alternate" title="%s projects feeds" '.
 -                     'href="%s" type="text/x-opml"/>'."\n",
 +                     'href="%s" type="text/x-opml" />'."\n",
                       $site_name, href(project=>undef, action=>"opml"));
        }
        if (defined $favicon) {
 -              print qq(<link rel="shortcut icon" href="$favicon" type="image/png"/>\n);
 +              print qq(<link rel="shortcut icon" href="$favicon" type="image/png" />\n);
        }
  
        print "</head>\n" .
        print "</div>\n";
  
        my ($have_search) = gitweb_check_feature('search');
 -      if ((defined $project) && ($have_search)) {
 +      if (defined $project && $have_search) {
                if (!defined $searchtext) {
                        $searchtext = "";
                }
                my ($use_pathinfo) = gitweb_check_feature('pathinfo');
                if ($use_pathinfo) {
                        $action .= "/".esc_url($project);
 -              } else {
 -                      $cgi->param("p", $project);
                }
 -              $cgi->param("a", "search");
 -              $cgi->param("h", $search_hash);
                print $cgi->startform(-method => "get", -action => $action) .
                      "<div class=\"search\">\n" .
 -                    (!$use_pathinfo && $cgi->hidden(-name => "p") . "\n") .
 -                    $cgi->hidden(-name => "a") . "\n" .
 -                    $cgi->hidden(-name => "h") . "\n" .
 +                    (!$use_pathinfo &&
 +                    $cgi->input({-name=>"p", -value=>$project, -type=>"hidden"}) . "\n") .
 +                    $cgi->input({-name=>"a", -value=>"search", -type=>"hidden"}) . "\n" .
 +                    $cgi->input({-name=>"h", -value=>$search_hash, -type=>"hidden"}) . "\n" .
                      $cgi->popup_menu(-name => 'st', -default => 'commit',
                                       -values => ['commit', 'grep', 'author', 'committer', 'pickaxe']) .
                      $cgi->sup($cgi->a({-href => href(action=>"search_help")}, "?")) .
  }
  
  sub git_footer_html {
 +      my $feed_class = 'rss_logo';
 +
        print "<div class=\"page_footer\">\n";
        if (defined $project) {
                my $descr = git_get_project_description($project);
                if (defined $descr) {
                        print "<div class=\"page_footer_text\">" . esc_html($descr) . "</div>\n";
                }
 -              print $cgi->a({-href => href(action=>"rss"),
 -                            -class => "rss_logo"}, "RSS") . " ";
 -              print $cgi->a({-href => href(action=>"atom"),
 -                            -class => "rss_logo"}, "Atom") . "\n";
 +
 +              my %href_params = get_feed_info();
 +              if (!%href_params) {
 +                      $feed_class .= ' generic';
 +              }
 +              $href_params{'-title'} ||= 'log';
 +
 +              foreach my $format qw(RSS Atom) {
 +                      $href_params{'action'} = lc($format);
 +                      print $cgi->a({-href => href(%href_params),
 +                                    -title => "$href_params{'-title'} $format feed",
 +                                    -class => $feed_class}, $format)."\n";
 +              }
 +
        } else {
                print $cgi->a({-href => href(project=>undef, action=>"opml"),
 -                            -class => "rss_logo"}, "OPML") . " ";
 +                            -class => $feed_class}, "OPML") . " ";
                print $cgi->a({-href => href(project=>undef, action=>"project_index"),
 -                            -class => "rss_logo"}, "TXT") . "\n";
 +                            -class => $feed_class}, "TXT") . "\n";
        }
 -      print "</div>\n" ;
 +      print "</div>\n"; # class="page_footer"
  
        if (-f $site_footer) {
                open (my $fd, $site_footer);
@@@ -4345,7 -4297,6 +4345,7 @@@ sub git_heads 
  }
  
  sub git_blob_plain {
 +      my $type = shift;
        my $expires;
  
        if (!defined $hash) {
                $expires = "+1d";
        }
  
 -      my $type = shift;
        open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash
 -              or die_error(undef, "Couldn't cat $file_name, $hash");
 +              or die_error(undef, "Open git-cat-file blob '$hash' failed");
  
 -      $type ||= blob_mimetype($fd, $file_name);
 +      # content-type (can include charset)
 +      $type = blob_contenttype($fd, $file_name, $type);
  
 -      # save as filename, even when no $file_name is given
 +      # "save as" filename, even when no $file_name is given
        my $save_as = "$hash";
        if (defined $file_name) {
                $save_as = $file_name;
        }
  
        print $cgi->header(
 -              -type => "$type",
 -              -expires=>$expires,
 -              -content_disposition => 'inline; filename="' . "$save_as" . '"');
 +              -type => $type,
 +              -expires => $expires,
 +              -content_disposition => 'inline; filename="' . $save_as . '"');
        undef $/;
        binmode STDOUT, ':raw';
        print <$fd>;
@@@ -4594,6 -4545,7 +4594,6 @@@ sub git_snapshot 
                $hash = git_get_head_hash($project);
        }
  
 -      my $git_command = git_cmd_str();
        my $name = $project;
        $name =~ s,([^/])/*\.git$,$1,;
        $name = basename($name);
        $name =~ s/\047/\047\\\047\047/g;
        my $cmd;
        $filename .= "-$hash$known_snapshot_formats{$format}{'suffix'}";
 -      $cmd = "$git_command archive " .
 -              "--format=$known_snapshot_formats{$format}{'format'} " .
 -              "--prefix=\'$name\'/ $hash";
 +      $cmd = quote_command(
 +              git_cmd(), 'archive',
 +              "--format=$known_snapshot_formats{$format}{'format'}",
 +              "--prefix=$name/", $hash);
        if (exists $known_snapshot_formats{$format}{'compressor'}) {
 -              $cmd .= ' | ' . join ' ', @{$known_snapshot_formats{$format}{'compressor'}};
 +              $cmd .= ' | ' . quote_command(@{$known_snapshot_formats{$format}{'compressor'}});
        }
  
        print $cgi->header(
@@@ -4819,8 -4770,8 +4819,8 @@@ sub git_object 
        if ($hash || ($hash_base && !defined $file_name)) {
                my $object_id = $hash || $hash_base;
  
 -              my $git_command = git_cmd_str();
 -              open my $fd, "-|", "$git_command cat-file -t $object_id 2>/dev/null"
 +              open my $fd, "-|", quote_command(
 +                      git_cmd(), 'cat-file', '-t', $object_id) . ' 2> /dev/null'
                        or die_error('404 Not Found', "Object does not exist");
                $type = <$fd>;
                chomp $type;
@@@ -4926,43 -4877,9 +4926,9 @@@ sub git_blobdiff 
                        or die_error(undef, "Open git-diff-tree failed");
        }
  
-       # old/legacy style URI
-       if (!%diffinfo && # if new style URI failed
-           defined $hash && defined $hash_parent) {
-               # fake git-diff-tree raw output
-               $diffinfo{'from_mode'} = $diffinfo{'to_mode'} = "blob";
-               $diffinfo{'from_id'} = $hash_parent;
-               $diffinfo{'to_id'}   = $hash;
-               if (defined $file_name) {
-                       if (defined $file_parent) {
-                               $diffinfo{'status'} = '2';
-                               $diffinfo{'from_file'} = $file_parent;
-                               $diffinfo{'to_file'}   = $file_name;
-                       } else { # assume not renamed
-                               $diffinfo{'status'} = '1';
-                               $diffinfo{'from_file'} = $file_name;
-                               $diffinfo{'to_file'}   = $file_name;
-                       }
-               } else { # no filename given
-                       $diffinfo{'status'} = '2';
-                       $diffinfo{'from_file'} = $hash_parent;
-                       $diffinfo{'to_file'}   = $hash;
-               }
-               # non-textual hash id's can be cached
-               if ($hash =~ m/^[0-9a-fA-F]{40}$/ &&
-                   $hash_parent =~ m/^[0-9a-fA-F]{40}$/) {
-                       $expires = '+1d';
-               }
-               # open patch output
-               open $fd, "-|", git_cmd(), "diff", @diff_opts,
-                       '-p', ($format eq 'html' ? "--full-index" : ()),
-                       $hash_parent, $hash, "--"
-                       or die_error(undef, "Open git-diff failed");
-       } else  {
+       # old/legacy style URI -- not generated anymore since 1.4.3.
+       if (!%diffinfo) {
                die_error('404 Not Found', "Missing one of the blob diff parameters")
-                       unless %diffinfo;
        }
  
        # header