diff options
Diffstat (limited to 'gitweb/gitweb.perl')
| -rwxr-xr-x | gitweb/gitweb.perl | 159 | 
1 files changed, 115 insertions, 44 deletions
| diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 2cb832753a..d6eb7291d6 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -160,7 +160,8 @@ our %known_snapshot_formats = (  	# 	'suffix' => filename suffix,  	# 	'format' => --format for git-archive,  	# 	'compressor' => [compressor command and arguments] -	# 	                (array reference, optional)} +	# 	                (array reference, optional) +	# 	'disabled' => boolean (optional)}  	#  	'tgz' => {  		'display' => 'tar.gz', @@ -176,6 +177,14 @@ our %known_snapshot_formats = (  		'format' => 'tar',  		'compressor' => ['bzip2']}, +	'txz' => { +		'display' => 'tar.xz', +		'type' => 'application/x-xz', +		'suffix' => '.tar.xz', +		'format' => 'tar', +		'compressor' => ['xz'], +		'disabled' => 1}, +  	'zip' => {  		'display' => 'zip',  		'type' => 'application/x-zip', @@ -188,6 +197,7 @@ our %known_snapshot_formats = (  our %known_snapshot_format_aliases = (  	'gzip'  => 'tgz',  	'bzip2' => 'tbz2', +	'xz'    => 'txz',  	# backward compatibility: legacy gitweb config support  	'x-gzip' => undef, 'gz' => undef, @@ -287,6 +297,19 @@ our %feature = (  		'override' => 0,  		'default' => [1]}, +	# Enable showing size of blobs in a 'tree' view, in a separate +	# column, similar to what 'ls -l' does.  This cost a bit of IO. + +	# To disable system wide have in $GITWEB_CONFIG +	# $feature{'show-sizes'}{'default'} = [0]; +	# To have project specific config enable override in $GITWEB_CONFIG +	# $feature{'show-sizes'}{'override'} = 1; +	# and in project config gitweb.showsizes = 0|1; +	'show-sizes' => { +		'sub' => sub { feature_bool('showsizes', @_) }, +		'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 @@ -494,7 +517,8 @@ sub filter_snapshot_fmts {  		exists $known_snapshot_format_aliases{$_} ?  		       $known_snapshot_format_aliases{$_} : $_} @fmts;  	@fmts = grep { -		exists $known_snapshot_formats{$_} } @fmts; +		exists $known_snapshot_formats{$_} && +		!$known_snapshot_formats{$_}{'disabled'}} @fmts;  }  our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++"; @@ -940,10 +964,13 @@ sub href {  			if (defined $params{'hash_parent_base'}) {  				$href .= esc_url($params{'hash_parent_base'});  				# skip the file_parent if it's the same as the file_name -				delete $params{'file_parent'} if $params{'file_parent'} eq $params{'file_name'}; -				if (defined $params{'file_parent'} && $params{'file_parent'} !~ /\.\./) { -					$href .= ":/".esc_url($params{'file_parent'}); -					delete $params{'file_parent'}; +				if (defined $params{'file_parent'}) { +					if (defined $params{'file_name'} && $params{'file_parent'} eq $params{'file_name'}) { +						delete $params{'file_parent'}; +					} elsif ($params{'file_parent'} !~ /\.\./) { +						$href .= ":/".esc_url($params{'file_parent'}); +						delete $params{'file_parent'}; +					}  				}  				$href .= "..";  				delete $params{'hash_parent'}; @@ -1510,10 +1537,10 @@ sub format_subject_html {  		$long =~ s/[[:cntrl:]]/?/g;  		return $cgi->a({-href => $href, -class => "list subject",  		                -title => to_utf8($long)}, -		       esc_html($short) . $extra); +		       esc_html($short)) . $extra;  	} else {  		return $cgi->a({-href => $href, -class => "list subject"}, -		       esc_html($long)  . $extra); +		       esc_html($long)) . $extra;  	}  } @@ -2750,16 +2777,31 @@ sub parse_ls_tree_line {  	my %opts = @_;  	my %res; -	#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa	panic.c' -	$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/s; +	if ($opts{'-l'}) { +		#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa   16717	panic.c' +		$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40}) +(-|[0-9]+)\t(.+)$/s; -	$res{'mode'} = $1; -	$res{'type'} = $2; -	$res{'hash'} = $3; -	if ($opts{'-z'}) { -		$res{'name'} = $4; +		$res{'mode'} = $1; +		$res{'type'} = $2; +		$res{'hash'} = $3; +		$res{'size'} = $4; +		if ($opts{'-z'}) { +			$res{'name'} = $5; +		} else { +			$res{'name'} = unquote($5); +		}  	} else { -		$res{'name'} = unquote($4); +		#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa	panic.c' +		$line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/s; + +		$res{'mode'} = $1; +		$res{'type'} = $2; +		$res{'hash'} = $3; +		if ($opts{'-z'}) { +			$res{'name'} = $4; +		} else { +			$res{'name'} = unquote($4); +		}  	}  	return wantarray ? %res : \%res; @@ -3550,6 +3592,9 @@ sub git_print_tree_entry {  	# and link is the action links of the entry.  	print "<td class=\"mode\">" . mode_str($t->{'mode'}) . "</td>\n"; +	if (exists $t->{'size'}) { +		print "<td class=\"size\">$t->{'size'}</td>\n"; +	}  	if ($t->{'type'} eq "blob") {  		print "<td class=\"list\">" .  			$cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'}, @@ -3595,12 +3640,14 @@ sub git_print_tree_entry {  	} elsif ($t->{'type'} eq "tree") {  		print "<td class=\"list\">";  		print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'}, -		                             file_name=>"$basedir$t->{'name'}", %base_key)}, +		                             file_name=>"$basedir$t->{'name'}", +		                             %base_key)},  		              esc_path($t->{'name'}));  		print "</td>\n";  		print "<td class=\"link\">";  		print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'}, -		                             file_name=>"$basedir$t->{'name'}", %base_key)}, +		                             file_name=>"$basedir$t->{'name'}", +		                             %base_key)},  		              "tree");  		if (defined $hash_base) {  			print " | " . @@ -4800,7 +4847,7 @@ sub git_blame {  	git_print_page_path($file_name, $ftype, $hash_base);  	# page body -	my @rev_color = qw(light2 dark2); +	my @rev_color = qw(light dark);  	my $num_colors = scalar(@rev_color);  	my $current_color = 0;  	my %metainfo = (); @@ -4818,15 +4865,18 @@ HTML  		my ($full_rev, $orig_lineno, $lineno, $group_size) =  		   ($line =~ /^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/);  		if (!exists $metainfo{$full_rev}) { -			$metainfo{$full_rev} = {}; +			$metainfo{$full_rev} = { 'nprevious' => 0 };  		}  		my $meta = $metainfo{$full_rev};  		my $data;  		while ($data = <$fd>) {  			chomp $data;  			last if ($data =~ s/^\t//); # contents of line -			if ($data =~ /^(\S+) (.*)$/) { -				$meta->{$1} = $2; +			if ($data =~ /^(\S+)(?: (.*))?$/) { +				$meta->{$1} = $2 unless exists $meta->{$1}; +			} +			if ($data =~ /^previous /) { +				$meta->{'nprevious'}++;  			}  		}  		my $short_rev = substr($full_rev, 0, 8); @@ -4837,7 +4887,11 @@ HTML  		if ($group_size) {  			$current_color = ($current_color + 1) % $num_colors;  		} -		print "<tr id=\"l$lineno\" class=\"$rev_color[$current_color]\">\n"; +		my $tr_class = $rev_color[$current_color]; +		$tr_class .= ' boundary' if (exists $meta->{'boundary'}); +		$tr_class .= ' no-previous' if ($meta->{'nprevious'} == 0); +		$tr_class .= ' multiple-previous' if ($meta->{'nprevious'} > 1); +		print "<tr id=\"l$lineno\" class=\"$tr_class\">\n";  		if ($group_size) {  			print "<td class=\"sha1\"";  			print " title=\"". esc_html($author) . ", $date\""; @@ -4847,22 +4901,31 @@ HTML  			                             hash=>$full_rev,  			                             file_name=>$file_name)},  			              esc_html($short_rev)); +			if ($group_size >= 2) { +				my @author_initials = ($author =~ /\b([[:upper:]])\B/g); +				if (@author_initials) { +					print "<br />" . +					      esc_html(join('', @author_initials)); +					#           or join('.', ...) +				} +			}  			print "</td>\n";  		} -		my $parent_commit; -		if (!exists $meta->{'parent'}) { -			open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^") -				or die_error(500, "Open git-rev-parse failed"); -			$parent_commit = <$dd>; -			close $dd; -			chomp($parent_commit); -			$meta->{'parent'} = $parent_commit; -		} else { -			$parent_commit = $meta->{'parent'}; -		} +		# 'previous' <sha1 of parent commit> <filename at commit> +		if (exists $meta->{'previous'} && +		    $meta->{'previous'} =~ /^([a-fA-F0-9]{40}) (.*)$/) { +			$meta->{'parent'} = $1; +			$meta->{'file_parent'} = unquote($2); +		} +		my $linenr_commit = +			exists($meta->{'parent'}) ? +			$meta->{'parent'} : $full_rev; +		my $linenr_filename = +			exists($meta->{'file_parent'}) ? +			$meta->{'file_parent'} : unquote($meta->{'filename'});  		my $blamed = href(action => 'blame', -		                  file_name => $meta->{'filename'}, -		                  hash_base => $parent_commit); +		                  file_name => $linenr_filename, +		                  hash_base => $linenr_commit);  		print "<td class=\"linenr\">";  		print $cgi->a({ -href => "$blamed#l$orig_lineno",  		                -class => "linenr" }, @@ -5058,10 +5121,14 @@ sub git_tree {  	}  	die_error(404, "No such tree") unless defined($hash); +	my $show_sizes = gitweb_check_feature('show-sizes'); +	my $have_blame = gitweb_check_feature('blame'); +  	my @entries = ();  	{  		local $/ = "\0"; -		open my $fd, "-|", git_cmd(), "ls-tree", '-z', $hash +		open my $fd, "-|", git_cmd(), "ls-tree", '-z', +			($show_sizes ? '-l' : ()), @extra_options, $hash  			or die_error(500, "Open git-ls-tree failed");  		@entries = map { chomp; $_ } <$fd>;  		close $fd @@ -5072,7 +5139,6 @@ sub git_tree {  	my $ref = format_ref_marker($refs, $hash_base);  	git_header_html();  	my $basedir = ''; -	my $have_blame = gitweb_check_feature('blame');  	if (defined $hash_base && (my %co = parse_commit($hash_base))) {  		my @views_nav = ();  		if (defined $file_name) { @@ -5088,7 +5154,8 @@ sub git_tree {  			# FIXME: Should be available when we have no hash base as well.  			push @views_nav, $snapshot_links;  		} -		git_print_page_nav('tree','', $hash_base, undef, undef, join(' | ', @views_nav)); +		git_print_page_nav('tree','', $hash_base, undef, undef, +		                   join(' | ', @views_nav));  		git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash_base);  	} else {  		undef $hash_base; @@ -5121,8 +5188,10 @@ sub git_tree {  		undef $up unless $up;  		# based on git_print_tree_entry  		print '<td class="mode">' . mode_str('040000') . "</td>\n"; +		print '<td class="size"> </td>'."\n" if $show_sizes;  		print '<td class="list">'; -		print $cgi->a({-href => href(action=>"tree", hash_base=>$hash_base, +		print $cgi->a({-href => href(action=>"tree", +		                             hash_base=>$hash_base,  		                             file_name=>$up)},  		              "..");  		print "</td>\n"; @@ -5131,7 +5200,7 @@ sub git_tree {  		print "</tr>\n";  	}  	foreach my $line (@entries) { -		my %t = parse_ls_tree_line($line, -z => 1); +		my %t = parse_ls_tree_line($line, -z => 1, -l => $show_sizes);  		if ($alternate) {  			print "<tr class=\"dark\">\n"; @@ -5160,6 +5229,8 @@ sub git_snapshot {  		die_error(400, "Invalid snapshot format parameter");  	} elsif (!exists($known_snapshot_formats{$format})) {  		die_error(400, "Unknown snapshot format"); +	} elsif ($known_snapshot_formats{$format}{'disabled'}) { +		die_error(403, "Snapshot format not allowed");  	} elsif (!grep($_ eq $format, @snapshot_fmts)) {  		die_error(403, "Unsupported snapshot format");  	} @@ -5296,7 +5367,7 @@ sub git_commit {  			} @$parents ) .  			')';  	} -	if (gitweb_check_feature('patches')) { +	if (gitweb_check_feature('patches') && @$parents <= 1) {  		$formats_nav .= " | " .  			$cgi->a({-href => href(action=>"patch", -replay=>1)},  				"patch"); @@ -5584,7 +5655,7 @@ sub git_commitdiff {  		$formats_nav =  			$cgi->a({-href => href(action=>"commitdiff_plain", -replay=>1)},  			        "raw"); -		if ($patch_max) { +		if ($patch_max && @{$co{'parents'}} <= 1) {  			$formats_nav .= " | " .  				$cgi->a({-href => href(action=>"patch", -replay=>1)},  					"patch"); @@ -5792,7 +5863,7 @@ sub git_commitdiff_plain {  # format-patch-style patches  sub git_patch { -	git_commitdiff(-format => 'patch', -single=> 1); +	git_commitdiff(-format => 'patch', -single => 1);  }  sub git_patches { | 
