412
'override' => 0,
413
'default' => []},
414
415
- # Allow gitweb scan project content tags described in ctags/
416
- # of project repository, and display the popular Web 2.0-ish
417
- # "tag cloud" near the project list. Note that this is something
418
- # COMPLETELY different from the normal Git tags.
415
+ # Allow gitweb scan project content tags of project repository,
416
+ # and display the popular Web 2.0-ish "tag cloud" near the projects
417
+ # list. Note that this is something COMPLETELY different from the
418
+ # normal Git tags.
419
420
# gitweb by itself can show existing tags, but it does not handle
421
- # tagging itself; you need an external application for that.
422
- # For an example script, check Girocco's cgi/tagproj.cgi.
421
+ # tagging itself; you need to do it externally, outside gitweb.
422
+ # The format is described in git_get_project_ctags() subroutine.
423
# You may want to install the HTML::TagCloud Perl module to get
424
# a pretty tag cloud instead of just a list of tags.
425
426
# To enable system wide have in $GITWEB_CONFIG
427
- # $feature{'ctags'}{'default'} = ['path_to_tag_script'];
427
+ # $feature{'ctags'}{'default'} = [1];
428
# Project specific override is not supported.
429
+
430
+ # In the future whether ctags editing is enabled might depend
431
+ # on the value, but using 1 should always mean no editing of ctags.
432
'ctags' => {
433
'override' => 0,
434
'default' => [0]},
706
snapshot_format => "sf",
707
extra_options => "opt",
708
search_use_regexp => "sr",
709
+ ctag => "by_tag",
710
# this must be last entry (for manipulation from JavaScript)
711
javascript => "js"
712
);
2576
return $descr;
2577
}
2578
2579
+# supported formats:
2580
+# * $GIT_DIR/ctags/<tagname> file (in 'ctags' subdirectory)
2581
+# - if its contents is a number, use it as tag weight,
2582
+# - otherwise add a tag with weight 1
2583
+# * $GIT_DIR/ctags file, each line is a tag (with weight 1)
2584
+# the same value multiple times increases tag weight
2585
+# * `gitweb.ctag' multi-valued repo config variable
2586
sub git_get_project_ctags {
2576
- my $path = shift;
2587
+ my $project = shift;
2588
my $ctags = {};
2589
2579
- $git_dir = "$projectroot/$path";
2580
- opendir my $dh, "$git_dir/ctags"
2581
- or return $ctags;
2582
- foreach (grep { -f $_ } map { "$git_dir/ctags/$_" } readdir($dh)) {
2583
- open my $ct, '<', $_ or next;
2584
- my $val = <$ct>;
2585
- chomp $val;
2586
- close $ct;
2587
- my $ctag = $_; $ctag =~ s#.*/##;
2588
- $ctags->{$ctag} = $val;
2590
+ $git_dir = "$projectroot/$project";
2591
+ if (opendir my $dh, "$git_dir/ctags") {
2592
+ my @files = grep { -f $_ } map { "$git_dir/ctags/$_" } readdir($dh);
2593
+ foreach my $tagfile (@files) {
2594
+ open my $ct, '<', $tagfile
2595
+ or next;
2596
+ my $val = <$ct>;
2597
+ chomp $val if $val;
2598
+ close $ct;
2599
+
2600
+ (my $ctag = $tagfile) =~ s#.*/##;
2601
+ if ($val =~ /\d+/) {
2602
+ $ctags->{$ctag} = $val;
2603
+ } else {
2604
+ $ctags->{$ctag} = 1;
2605
+ }
2606
+ }
2607
+ closedir $dh;
2608
+
2609
+ } elsif (open my $fh, '<', "$git_dir/ctags") {
2610
+ while (my $line = <$fh>) {
2611
+ chomp $line;
2612
+ $ctags->{$line}++ if $line;
2613
+ }
2614
+ close $fh;
2615
+
2616
+ } else {
2617
+ my $taglist = config_to_multi(git_get_project_config('ctag'));
2618
+ foreach my $tag (@$taglist) {
2619
+ $ctags->{$tag}++;
2620
+ }
2621
}
2590
- closedir $dh;
2591
- $ctags;
2622
+
2623
+ return $ctags;
2624
+}
2625
+
2626
+# return hash, where keys are content tags ('ctags'),
2627
+# and values are sum of weights of given tag in every project
2628
+sub git_gather_all_ctags {
2629
+ my $projects = shift;
2630
+ my $ctags = {};
2631
+
2632
+ foreach my $p (@$projects) {
2633
+ foreach my $ct (keys %{$p->{'ctags'}}) {
2634
+ $ctags->{$ct} += $p->{'ctags'}->{$ct};
2635
+ }
2636
+ }
2637
+
2638
+ return $ctags;
2639
}
2640
2641
sub git_populate_project_tagcloud {
2655
my $cloud;
2656
if (eval { require HTML::TagCloud; 1; }) {
2657
$cloud = HTML::TagCloud->new;
2611
- foreach (sort keys %ctags_lc) {
2658
+ foreach my $ctag (sort keys %ctags_lc) {
2659
# Pad the title with spaces so that the cloud looks
2660
# less crammed.
2614
- my $title = $ctags_lc{$_}->{topname};
2661
+ my $title = esc_html($ctags_lc{$ctag}->{topname});
2662
$title =~ s/ / /g;
2663
$title =~ s/^/ /g;
2664
$title =~ s/$/ /g;
2618
- $cloud->add($title, $home_link."?by_tag=".$_, $ctags_lc{$_}->{count});
2665
+ $cloud->add($title, href(project=>undef, ctag=>$ctag),
2666
+ $ctags_lc{$ctag}->{count});
2667
}
2668
} else {
2621
- $cloud = \%ctags_lc;
2669
+ $cloud = {};
2670
+ foreach my $ctag (keys %ctags_lc) {
2671
+ my $title = $ctags_lc{$ctag}->{topname};
2672
+ $cloud->{$ctag}{count} = $ctags_lc{$ctag}->{count};
2673
+ $cloud->{$ctag}{ctag} =
2674
+ $cgi->a({-href=>href(project=>undef, ctag=>$ctag)},
2675
+ esc_html($title, -nbsp=>1));
2676
+ }
2677
}
2623
- $cloud;
2678
+ return $cloud;
2679
}
2680
2681
sub git_show_project_tagcloud {
2682
my ($cloud, $count) = @_;
2628
- print STDERR ref($cloud)."..\n";
2683
if (ref $cloud eq 'HTML::TagCloud') {
2684
return $cloud->html_and_css($count);
2685
} else {
2632
- my @tags = sort { $cloud->{$a}->{count} <=> $cloud->{$b}->{count} } keys %$cloud;
2633
- return '<p align="center">' . join (', ', map {
2634
- $cgi->a({-href=>"$home_link?by_tag=$_"}, $cloud->{$_}->{topname})
2635
- } splice(@tags, 0, $count)) . '</p>';
2686
+ my @tags = sort { $cloud->{$a}->{'count'} <=> $cloud->{$b}->{'count'} } keys %$cloud;
2687
+ return
2688
+ '<div id="htmltagcloud"'.($project ? '' : ' align="center"').'>' .
2689
+ join (', ', map {
2690
+ $cloud->{$_}->{'ctag'}
2691
+ } splice(@tags, 0, $count)) .
2692
+ '</div>';
2693
}
2694
}
2695
4977
@projects = sort_projects_list(\@projects, $order);
4978
4979
if ($show_ctags) {
4923
- my %ctags;
4924
- foreach my $p (@projects) {
4925
- foreach my $ct (keys %{$p->{'ctags'}}) {
4926
- $ctags{$ct} += $p->{'ctags'}->{$ct};
4927
- }
4928
- }
4929
- my $cloud = git_populate_project_tagcloud(\%ctags);
4980
+ my $ctags = git_gather_all_ctags(\@projects);
4981
+ my $cloud = git_populate_project_tagcloud($ctags);
4982
print git_show_project_tagcloud($cloud, 64);
4983
}
4984
5573
my $show_ctags = gitweb_check_feature('ctags');
5574
if ($show_ctags) {
5575
my $ctags = git_get_project_ctags($project);
5524
- my $cloud = git_populate_project_tagcloud($ctags);
5525
- print "<tr id=\"metadata_ctags\"><td>Content tags:<br />";
5526
- print "</td>\n<td>" unless %$ctags;
5527
- print "<form action=\"$show_ctags\" method=\"post\"><input type=\"hidden\" name=\"p\" value=\"$project\" />Add: <input type=\"text\" name=\"t\" size=\"8\" /></form>";
5528
- print "</td>\n<td>" if %$ctags;
5529
- print git_show_project_tagcloud($cloud, 48);
5530
- print "</td></tr>";
5576
+ if (%$ctags) {
5577
+ # without ability to add tags, don't show if there are none
5578
+ my $cloud = git_populate_project_tagcloud($ctags);
5579
+ print "<tr id=\"metadata_ctags\">" .
5580
+ "<td>content tags</td>" .
5581
+ "<td>".git_show_project_tagcloud($cloud, 48)."</td>" .
5582
+ "</tr>\n";
5583
+ }
5584
}
5585
5586
print "</table>\n";