@@ -548,6 +548,20 @@ sub evaluate_uri {
548548 ' sub' => sub { feature_bool(' remote_heads' , @_ ) },
549549 ' override' => 0,
550550 ' default' => [0]},
551+
552+ # Enable showing branches under other refs in addition to heads
553+
554+ # To set system wide extra branch refs have in $GITWEB_CONFIG
555+ # $feature{'extra-branch-refs'}{'default'} = ['dirs', 'of', 'choice'];
556+ # To have project specific config enable override in $GITWEB_CONFIG
557+ # $feature{'extra-branch-refs'}{'override'} = 1;
558+ # and in project config gitweb.extrabranchrefs = dirs of choice
559+ # Every directory is separated with whitespace.
560+
561+ ' extra-branch-refs' => {
562+ ' sub' => \&feature_extra_branch_refs,
563+ ' override' => 0,
564+ ' default' => []},
551565);
552566
553567sub gitweb_get_feature {
@@ -626,6 +640,21 @@ sub feature_avatar {
626640 return @val ? @val : @_ ;
627641}
628642
643+ sub feature_extra_branch_refs {
644+ my (@branch_refs ) = @_ ;
645+ my $values = git_get_project_config(' extrabranchrefs' );
646+
647+ if ($values ) {
648+ $values = config_to_multi ($values );
649+ @branch_refs = ();
650+ foreach my $value (@{$values }) {
651+ push @branch_refs , split /\s +/, $value ;
652+ }
653+ }
654+
655+ return @branch_refs ;
656+ }
657+
629658# checking HEAD file with -e is fragile if the repository was
630659# initialized long time ago (i.e. symlink HEAD) and was pack-ref'ed
631660# and then pruned.
@@ -656,6 +685,18 @@ sub filter_snapshot_fmts {
656685 !$known_snapshot_formats {$_ }{' disabled' }} @fmts ;
657686}
658687
688+ sub filter_and_validate_refs {
689+ my @refs = @_ ;
690+ my %unique_refs = ();
691+
692+ foreach my $ref (@refs ) {
693+ die_error(500, " Invalid ref '$ref ' in 'extra-branch-refs' feature" ) unless (is_valid_ref_format($ref ));
694+ # 'heads' are added implicitly in get_branch_refs().
695+ $unique_refs {$ref } = 1 if ($ref ne ' heads' );
696+ }
697+ return sort keys %unique_refs ;
698+ }
699+
659700# If it is set to code reference, it is code that it is to be run once per
660701# request, allowing updating configurations that change with each request,
661702# while running other code in config file only once.
@@ -1113,7 +1154,7 @@ sub evaluate_git_dir {
11131154 our $git_dir = " $projectroot /$project " if $project ;
11141155}
11151156
1116- our (@snapshot_fmts , $git_avatar );
1157+ our (@snapshot_fmts , $git_avatar , @extra_branch_refs );
11171158sub configure_gitweb_features {
11181159 # list of supported snapshot formats
11191160 our @snapshot_fmts = gitweb_get_feature(' snapshot' );
@@ -1131,6 +1172,13 @@ sub configure_gitweb_features {
11311172 } else {
11321173 $git_avatar = ' ' ;
11331174 }
1175+
1176+ our @extra_branch_refs = gitweb_get_feature(' extra-branch-refs' );
1177+ @extra_branch_refs = filter_and_validate_refs (@extra_branch_refs );
1178+ }
1179+
1180+ sub get_branch_refs {
1181+ return (' heads' , @extra_branch_refs );
11341182}
11351183
11361184# custom error handler: 'die <message>' is Internal Server Error
@@ -2527,19 +2575,25 @@ sub format_snapshot_links {
25272575sub get_feed_info {
25282576 my $format = shift || ' Atom' ;
25292577 my %res = (action => lc ($format ));
2578+ my $matched_ref = 0;
25302579
25312580 # feed links are possible only for project views
25322581 return unless (defined $project );
25332582 # some views should link to OPML, or to generic project feed,
25342583 # or don't have specific feed yet (so they should use generic)
25352584 return if (!$action || $action =~ / ^(?:tags|heads|forks|tag|search)$ /x );
25362585
2537- my $branch ;
2538- # branches refs uses 'refs/heads/' prefix (fullname) to differentiate
2539- # from tag links; this also makes possible to detect branch links
2540- if ((defined $hash_base && $hash_base =~ m ! ^refs/heads/(.*)$ ! ) ||
2541- (defined $hash && $hash =~ m ! ^refs/heads/(.*)$ ! )) {
2542- $branch = $1 ;
2586+ my $branch = undef ;
2587+ # branches refs uses 'refs/' + $get_branch_refs()[x] + '/' prefix
2588+ # (fullname) to differentiate from tag links; this also makes
2589+ # possible to detect branch links
2590+ for my $ref (get_branch_refs()) {
2591+ if ((defined $hash_base && $hash_base =~ m ! ^refs/\Q $ref \E /(.*)$ ! ) ||
2592+ (defined $hash && $hash =~ m ! ^refs/\Q $ref \E /(.*)$ ! )) {
2593+ $branch = $1 ;
2594+ $matched_ref = $ref ;
2595+ last ;
2596+ }
25432597 }
25442598 # find log type for feed description (title)
25452599 my $type = ' log' ;
@@ -2552,7 +2606,7 @@ sub get_feed_info {
25522606 }
25532607
25542608 $res {-title} = $type ;
2555- $res {' hash' } = (defined $branch ? " refs/heads /$branch " : undef );
2609+ $res {' hash' } = (defined $branch ? " refs/$matched_ref /$branch " : undef );
25562610 $res {' file_name' } = $file_name ;
25572611
25582612 return %res ;
@@ -3205,7 +3259,7 @@ sub git_get_last_activity {
32053259 ' --format=%(committer)' ,
32063260 ' --sort=-committerdate' ,
32073261 ' --count=1' ,
3208- ' refs/heads ' ) or return ;
3262+ map { " refs/$_ " } get_branch_refs () ) or return ;
32093263 my $most_recent = <$fd >;
32103264 close $fd or return ;
32113265 if (defined $most_recent &&
@@ -3656,7 +3710,7 @@ sub parse_from_to_diffinfo {
36563710
36573711sub git_get_heads_list {
36583712 my ($limit , @classes ) = @_ ;
3659- @classes = ( ' heads ' ) unless @classes ;
3713+ @classes = get_branch_refs( ) unless @classes ;
36603714 my @patterns = map { " refs/$_ " } @classes ;
36613715 my @headslist ;
36623716
@@ -3674,7 +3728,8 @@ sub git_get_heads_list {
36743728 my ($committer , $epoch , $tz ) =
36753729 ($committerinfo =~ / ^(.*) ([0-9]+) (.*)$ / );
36763730 $ref_item {' fullname' } = $name ;
3677- $name =~ s ! ^refs/(?:head|remote)s/!! ;
3731+ my $strip_refs = join ' |' , map { quotemeta } get_branch_refs();
3732+ $name =~ s ! ^refs/($strip_refs|remotes)/!! ;
36783733
36793734 $ref_item {' name' } = $name ;
36803735 $ref_item {' id' } = $hash ;
@@ -7191,7 +7246,8 @@ sub snapshot_name {
71917246 $ver = $1 ;
71927247 } else {
71937248 # branches and other need shortened SHA-1 hash
7194- if ($hash =~ m ! ^refs/(?:heads|remotes)/(.*)$ ! ) {
7249+ my $strip_refs = join ' |' , map { quotemeta } get_branch_refs();
7250+ if ($hash =~ m ! ^refs/($strip_refs |remotes)/(.*)$ ! ) {
71957251 $ver = $1 ;
71967252 }
71977253 $ver .= ' -' . git_get_short_hash($project , $hash );
0 commit comments