#
# use gitweb_check_feature(<feature>) to check if <feature> is enabled
+ # Enable the 'blame' blob view, showing the last commit that modified
+ # each line in the file. This can be very CPU-intensive.
+
+ # To enable system wide have in $GITWEB_CONFIG
+ # $feature{'blame'}{'default'} = [1];
+ # To have project specific config enable override in $GITWEB_CONFIG
+ # $feature{'blame'}{'override'} = 1;
+ # and in project config gitweb.blame = 0|1;
'blame' => {
'sub' => \&feature_blame,
'override' => 0,
'default' => [0]},
+ # Enable the 'snapshot' link, providing a compressed tarball of any
+ # tree. This can potentially generate high traffic if you have large
+ # project.
+
+ # To disable system wide have in $GITWEB_CONFIG
+ # $feature{'snapshot'}{'default'} = [undef];
+ # To have project specific config enable override in $GITWEB_CONFIG
+ # $feature{'blame'}{'override'} = 1;
+ # and in project config gitweb.snapshot = none|gzip|bzip2;
'snapshot' => {
'sub' => \&feature_snapshot,
'override' => 0,
# => [content-encoding, suffix, program]
'default' => ['x-gzip', 'gz', 'gzip']},
+ # Enable the pickaxe search, which will list the commits that modified
+ # a given string in a file. This can be practical and quite faster
+ # alternative to 'blame', but still potentially CPU-intensive.
+
+ # To enable system wide have in $GITWEB_CONFIG
+ # $feature{'pickaxe'}{'default'} = [1];
+ # To have project specific config enable override in $GITWEB_CONFIG
+ # $feature{'pickaxe'}{'override'} = 1;
+ # and in project config gitweb.pickaxe = 0|1;
'pickaxe' => {
'sub' => \&feature_pickaxe,
'override' => 0,
'default' => [1]},
+
+ # Make gitweb use an alternative format of the URLs which can be
+ # more readable and natural-looking: project name is embedded
+ # directly in the path and the query string contains other
+ # auxiliary information. All gitweb installations recognize
+ # URL in either format; this configures in which formats gitweb
+ # generates links.
+
+ # To enable system wide have in $GITWEB_CONFIG
+ # $feature{'pathinfo'}{'default'} = [1];
+ # Project specific override is not supported.
+
+ # Note that you will need to change the default location of CSS,
+ # favicon, logo and possibly other files to an absolute URL. Also,
+ # if gitweb.cgi serves as your indexfile, you will need to force
+ # $my_uri to contain the script name in your $GITWEB_CONFIG.
+ 'pathinfo' => {
+ 'override' => 0,
+ 'default' => [0]},
);
sub gitweb_check_feature {
$feature{$name}{'override'},
@{$feature{$name}{'default'}});
if (!$override) { return @defaults; }
+ if (!defined $sub) {
+ warn "feature $name is not overrideable";
+ return @defaults;
+ }
return $sub->(@defaults);
}
-# To enable system wide have in $GITWEB_CONFIG
-# $feature{'blame'}{'default'} = [1];
-# To have project specific config enable override in $GITWEB_CONFIG
-# $feature{'blame'}{'override'} = 1;
-# and in project config gitweb.blame = 0|1;
-
sub feature_blame {
my ($val) = git_get_project_config('blame', '--bool');
return $_[0];
}
-# To disable system wide have in $GITWEB_CONFIG
-# $feature{'snapshot'}{'default'} = [undef];
-# To have project specific config enable override in $GITWEB_CONFIG
-# $feature{'blame'}{'override'} = 1;
-# and in project config gitweb.snapshot = none|gzip|bzip2
-
sub feature_snapshot {
my ($ctype, $suffix, $command) = @_;
return $have_snapshot;
}
-# To enable system wide have in $GITWEB_CONFIG
-# $feature{'pickaxe'}{'default'} = [1];
-# To have project specific config enable override in $GITWEB_CONFIG
-# $feature{'pickaxe'}{'override'} = 1;
-# and in project config gitweb.pickaxe = 0|1;
-
sub feature_pickaxe {
my ($val) = git_get_project_config('pickaxe', '--bool');
sub href(%) {
my %params = @_;
+ my $href = $my_uri;
+
+ # XXX: Warning: If you touch this, check the search form for updating,
+ # too.
my @mapping = (
project => "p",
$params{'project'} = $project unless exists $params{'project'};
+ my ($use_pathinfo) = gitweb_check_feature('pathinfo');
+ if ($use_pathinfo) {
+ # use PATH_INFO for project name
+ $href .= "/$params{'project'}" if defined $params{'project'};
+ delete $params{'project'};
+
+ # Summary just uses the project path URL
+ if (defined $params{'action'} && $params{'action'} eq 'summary') {
+ delete $params{'action'};
+ }
+ }
+
+ # now encode the parameters explicitly
my @result = ();
for (my $i = 0; $i < @mapping; $i += 2) {
my ($name, $symbol) = ($mapping[$i], $mapping[$i+1]);
push @result, $symbol . "=" . esc_param($params{$name});
}
}
- return "$my_uri?" . join(';', @result);
+ $href .= "?" . join(';', @result) if scalar @result;
+
+ return $href;
}
if (defined $commit_text) {
@commit_lines = @$commit_text;
} else {
- $/ = "\0";
+ local $/ = "\0";
open my $fd, "-|", git_cmd(), "rev-list", "--header", "--parents", "--max-count=1", $commit_id
or return;
@commit_lines = split '\n', <$fd>;
close $fd or return;
- $/ = "\n";
pop @commit_lines;
}
my $header = shift @commit_lines;
}
$cgi->param("a", "search");
$cgi->param("h", $search_hash);
+ $cgi->param("p", $project);
print $cgi->startform(-method => "get", -action => $my_uri) .
"<div class=\"search\">\n" .
$cgi->hidden(-name => "p") . "\n" .
my $type = shift;
my $hb = shift;
- if (!defined $name) {
- print "<div class=\"page_path\">/</div>\n";
- } else {
+
+ print "<div class=\"page_path\">";
+ print $cgi->a({-href => href(action=>"tree", hash_base=>$hb),
+ -title => 'tree root'}, "[$project]");
+ print " / ";
+ if (defined $name) {
my @dirname = split '/', $name;
my $basename = pop @dirname;
my $fullname = '';
- print "<div class=\"page_path\">";
- print $cgi->a({-href => href(action=>"tree", hash_base=>$hb),
- -title => 'tree root'}, "[$project]");
- print " / ";
foreach my $dir (@dirname) {
$fullname .= ($fullname ? '/' : '') . $dir;
print $cgi->a({-href => href(action=>"tree", file_name=>$fullname,
print $cgi->a({-href => href(action=>"tree", file_name=>$file_name,
hash_base=>$hb),
-title => $name}, esc_html($basename));
+ print " / ";
} else {
print esc_html($basename);
}
- print "<br/></div>\n";
}
+ print "<br/></div>\n";
}
# sub git_print_log (\@;%) {
if ($t->{'type'} eq "blob") {
print "<td class=\"list\">" .
$cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'},
- file_name=>"$basedir$t->{'name'}", %base_key),
- -class => "list"}, esc_html($t->{'name'})) . "</td>\n";
+ file_name=>"$basedir$t->{'name'}", %base_key),
+ -class => "list"}, esc_html($t->{'name'})) . "</td>\n";
print "<td class=\"link\">";
if ($have_blame) {
print $cgi->a({-href => href(action=>"blame", hash=>$t->{'hash'},
- file_name=>"$basedir$t->{'name'}", %base_key)},
- "blame");
+ file_name=>"$basedir$t->{'name'}", %base_key)},
+ "blame");
}
if (defined $hash_base) {
if ($have_blame) {
}
print " | " .
$cgi->a({-href => href(action=>"blob_plain", hash_base=>$hash_base,
- file_name=>"$basedir$t->{'name'}")},
- "raw");
+ file_name=>"$basedir$t->{'name'}")},
+ "raw");
print "</td>\n";
} elsif ($t->{'type'} eq "tree") {
print "<td>";
print $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'},
hash_base=>$hash, file_name=>$diff{'file'}),
- -class => "list"}, esc_html($diff{'file'}));
+ -class => "list"}, esc_html($diff{'file'}));
print "</td>\n";
print "<td>$mode_chng</td>\n";
print "<td class=\"link\">";
print " | ";
}
print $cgi->a({-href => href(action=>"blame", hash_base=>$parent,
- file_name=>$diff{'file'})},
- "blame") . " | ";
+ file_name=>$diff{'file'})},
+ "blame") . " | ";
print $cgi->a({-href => href(action=>"history", hash_base=>$parent,
- file_name=>$diff{'file'})},
- "history");
+ file_name=>$diff{'file'})},
+ "history");
print "</td>\n";
} elsif ($diff{'status'} eq "M" || $diff{'status'} eq "T") { # modified, or type changed
}
print "<td>";
print $cgi->a({-href => href(action=>"blob", hash=>$diff{'to_id'},
- hash_base=>$hash, file_name=>$diff{'file'}),
- -class => "list"}, esc_html($diff{'file'}));
+ hash_base=>$hash, file_name=>$diff{'file'}),
+ -class => "list"}, esc_html($diff{'file'}));
print "</td>\n";
print "<td>$mode_chnge</td>\n";
print "<td class=\"link\">";
print $cgi->a({-href => "#patch$patchno"}, "patch");
} else {
print $cgi->a({-href => href(action=>"blobdiff",
- hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'},
- hash_base=>$hash, hash_parent_base=>$parent,
- file_name=>$diff{'file'})},
- "diff");
+ hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'},
+ hash_base=>$hash, hash_parent_base=>$parent,
+ file_name=>$diff{'file'})},
+ "diff");
}
print " | ";
}
print $cgi->a({-href => href(action=>"blame", hash_base=>$hash,
- file_name=>$diff{'file'})},
- "blame") . " | ";
+ file_name=>$diff{'file'})},
+ "blame") . " | ";
print $cgi->a({-href => href(action=>"history", hash_base=>$hash,
- file_name=>$diff{'file'})},
- "history");
+ file_name=>$diff{'file'})},
+ "history");
print "</td>\n";
} elsif ($diff{'status'} eq "R" || $diff{'status'} eq "C") { # renamed or copied
print $cgi->a({-href => "#patch$patchno"}, "patch");
} else {
print $cgi->a({-href => href(action=>"blobdiff",
- hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'},
- hash_base=>$hash, hash_parent_base=>$parent,
- file_name=>$diff{'to_file'}, file_parent=>$diff{'from_file'})},
- "diff");
+ hash=>$diff{'to_id'}, hash_parent=>$diff{'from_id'},
+ hash_base=>$hash, hash_parent_base=>$parent,
+ file_name=>$diff{'to_file'}, file_parent=>$diff{'from_file'})},
+ "diff");
}
print " | ";
}
print $cgi->a({-href => href(action=>"blame", hash_base=>$parent,
- file_name=>$diff{'from_file'})},
- "blame") . " | ";
+ file_name=>$diff{'from_file'})},
+ "blame") . " | ";
print $cgi->a({-href => href(action=>"history", hash_base=>$parent,
- file_name=>$diff{'from_file'})},
- "history");
+ file_name=>$diff{'from_file'})},
+ "history");
print "</td>\n";
} # we should not encounter Unmerged (U) or Unknown (X) status
my $refs = git_get_references();
my $ref = format_ref_marker($refs, $hash_base);
git_header_html();
- my $base = "";
+ my $basedir = '';
my ($have_blame) = gitweb_check_feature('blame');
if (defined $hash_base && (my %co = parse_commit($hash_base))) {
my @views_nav = ();
# FIXME: Should be available when we have no hash base as well.
push @views_nav,
$cgi->a({-href => href(action=>"snapshot", hash=>$hash)},
- "snapshot");
+ "snapshot");
}
git_print_page_nav('tree','', $hash_base, undef, undef, join(' | ', @views_nav));
git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash_base);
print "<div class=\"title\">$hash</div>\n";
}
if (defined $file_name) {
- $base = esc_html("$file_name/");
+ $basedir = $file_name;
+ if ($basedir ne '' && substr($basedir, -1) ne '/') {
+ $basedir .= '/';
+ }
}
git_print_page_path($file_name, 'tree', $hash_base);
print "<div class=\"page_body\">\n";
print "<table cellspacing=\"0\">\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;
+
+ 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="list">';
+ print $cgi->a({-href => href(action=>"tree", hash_base=>$hash_base,
+ file_name=>$up)},
+ "..");
+ print "</td>\n";
+ print "<td class=\"link\"></td>\n";
+
+ print "</tr>\n";
+ }
foreach my $line (@entries) {
my %t = parse_ls_tree_line($line, -z => 1);
}
$alternate ^= 1;
- git_print_tree_entry(\%t, $base, $hash_base, $have_blame);
+ git_print_tree_entry(\%t, $basedir, $hash_base, $have_blame);
print "</tr>\n";
}