From: Krzesimir Nowak <krzesimir@endocode.com>
To: Junio C Hamano <gitster@pobox.com>
Cc: git@vger.kernel.org
Subject: Re: [PATCH] gitweb: Add an option for adding more branch refs
Date: Wed, 27 Nov 2013 16:34:42 +0100 [thread overview]
Message-ID: <1385566482.2131.22.camel@localhost.localdomain> (raw)
In-Reply-To: <xmqqr4a2vnqd.fsf@gitster.dls.corp.google.com>
On Tue, 2013-11-26 at 13:48 -0800, Junio C Hamano wrote:
> Krzesimir Nowak <krzesimir@endocode.com> writes:
>
> > Overriding an @additional_branch_refs configuration variable with
> > value ('wip') will make gitweb to show branches that appear in
> > refs/heads and refs/wip (refs/heads is hardcoded). Might be useful for
> > gerrit setups where user branches are not stored under refs/heads/.
> >
> > Signed-off-by: Krzesimir Nowak <krzesimir@endocode.com>
> > ---
> > gitweb/gitweb.perl | 99 ++++++++++++++++++++++++++++++++++++++++--------------
> > 1 file changed, 74 insertions(+), 25 deletions(-)
> >
> > diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
> > index 68c77f6..9bfd38b 100755
> > --- a/gitweb/gitweb.perl
> > +++ b/gitweb/gitweb.perl
> > @@ -17,6 +17,7 @@ use Encode;
> > use Fcntl ':mode';
> > use File::Find qw();
> > use File::Basename qw(basename);
> > +use List::Util qw(min);
> > use Time::HiRes qw(gettimeofday tv_interval);
> > binmode STDOUT, ':utf8';
> >
> > @@ -122,6 +123,10 @@ our $logo_label = "git homepage";
> > # source of projects list
> > our $projects_list = "++GITWEB_LIST++";
> >
> > +# list of additional "directories" under "refs/" we want to display as
> > +# branches
> > +our @additional_branch_refs = ();
> > +
> > # the width (in characters) of the projects list "Description" column
> > our $projects_list_description_width = 25;
> >
> > @@ -626,14 +631,29 @@ sub feature_avatar {
> > return @val ? @val : @_;
> > }
> >
> > +sub get_branch_refs {
> > + return ('heads', @additional_branch_refs);
> > +}
> > +
> > # checking HEAD file with -e is fragile if the repository was
> > # initialized long time ago (i.e. symlink HEAD) and was pack-ref'ed
> > # and then pruned.
> > sub check_head_link {
> > my ($dir) = @_;
> > my $headfile = "$dir/HEAD";
> > - return ((-e $headfile) ||
> > - (-l $headfile && readlink($headfile) =~ /^refs\/heads\//));
> > +
> > + if (-e $headfile) {
> > + return 1;
> > + }
> > + if (-l $headfile) {
> > + my $rl = readlink($headfile);
> > +
> > + for my $ref (get_branch_refs()) {
> > + return 1 if $rl =~ /^refs\/$ref\//;
> > + }
> > + }
> > + return 0;
>
> The change to this function is wrong. A non-detached HEAD that
> points at anything other than refs/heads/ should be considered a
> repository corruption and should not be encouraged.
Ok, I'll get rid of it.
>
> > @@ -2515,6 +2535,7 @@ sub format_snapshot_links {
> > sub get_feed_info {
> > my $format = shift || 'Atom';
> > my %res = (action => lc($format));
> > + my $matched_ref = 0;
> >
> > # feed links are possible only for project views
> > return unless (defined $project);
> > @@ -2522,12 +2543,17 @@ sub get_feed_info {
> > # or don't have specific feed yet (so they should use generic)
> > return if (!$action || $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;
> > + my $branch = undef;
> > + # branches refs uses 'refs/' + $get_branch_refs()[x] + '/' prefix
> > + # (fullname) to differentiate from tag links; this also makes
> > + # possible to detect branch links
> > + for my $ref (get_branch_refs()) {
> > + if ((defined $hash_base && $hash_base =~ m!^refs/$ref/(.*)$!) ||
> > + (defined $hash && $hash =~ m!^refs/$ref/(.*)$!)) {
> > + $branch = $1;
> > + $matched_ref = $ref;
> > + last;
> > + }
> > }
> > # find log type for feed description (title)
> > my $type = 'log';
> > @@ -2540,7 +2566,7 @@ sub get_feed_info {
> > }
> >
> > $res{-title} = $type;
> > - $res{'hash'} = (defined $branch ? "refs/heads/$branch" : undef);
> > + $res{'hash'} = (defined $branch ? "refs/$matched_ref/$branch" : undef);
> > $res{'file_name'} = $file_name;
>
> OK.
>
> > @@ -3184,24 +3210,43 @@ sub git_get_project_owner {
> > return $owner;
> > }
> >
> > -sub git_get_last_activity {
> > - my ($path) = @_;
> > - my $fd;
> > +sub git_get_last_activity_age {
> > + my ($refs) = @_;
> > + my $fd = -1;
> >
> > - $git_dir = "$projectroot/$path";
> > open($fd, "-|", git_cmd(), 'for-each-ref',
> > '--format=%(committer)',
> > '--sort=-committerdate',
> > '--count=1',
> > - 'refs/heads') or return;
> > + $refs) or return undef;
> > +
> > my $most_recent = <$fd>;
> > - close $fd or return;
> > + close $fd or return undef;
> > if (defined $most_recent &&
> > $most_recent =~ / (\d+) [-+][01]\d\d\d$/) {
> > my $timestamp = $1;
> > - my $age = time - $timestamp;
> > - return ($age, age_string($age));
> > + return time - $timestamp;
> > }
> > +
> > + return undef;
> > +}
> > +
> > +sub git_get_last_activity {
> > + my ($path) = @_;
> > + my @ages = ();
> > +
> > + $git_dir = "$projectroot/$path";
> > + for my $ref (get_branch_refs()) {
> > + my $age = git_get_last_activity_age('refs/' . $_);
> > +
> > + push @ages, $age if defined $age;
> > + }
> > + if (@ages) {
> > + my $min_age = min(@ages);
> > +
> > + return ($min_age, age_string($min_age));
> > + }
> > +
> > return (undef, undef);
> > }
>
> The original runs
>
> for-each-ref --count=1 refs/heads
>
> and picks the latest one, so shouldn't it be the matter of running
>
> for-each-ref --count=1 refs/heads refs/extra
>
> i.e. something like
>
> @@ -3193,7 +3193,7 @@ sub git_get_last_activity {
> '--format=%(committer)',
> '--sort=-committerdate',
> '--count=1',
> - 'refs/heads') or return;
> + map { "refs/$_" } get_branch_refs()) or return;
> my $most_recent = <$fd>;
> close $fd or return;
> if (defined $most_recent &&
>
> to grab the latest among the refs you care about?
That's simpler, yes.
>
> > @@ -3223,7 +3268,7 @@ sub git_get_remotes_list {
> > next if $wanted and not $remote eq $wanted;
> > my ($url, $key) = ($1, $2);
> >
> > - $remotes{$remote} ||= { 'heads' => () };
> > + $remotes{$remote} ||= { map { $_ => () } get_branch_refs() };
> > $remotes{$remote}{$key} = $url;
> > }
> > close $fd or return;
> > @@ -3237,9 +3282,11 @@ sub fill_remote_heads {
> > my @heads = map { "remotes/$_" } keys %$remotes;
> > my @remoteheads = git_get_heads_list(undef, @heads);
> > foreach my $remote (keys %$remotes) {
> > - $remotes->{$remote}{'heads'} = [ grep {
> > - $_->{'name'} =~ s!^$remote/!!
> > - } @remoteheads ];
> > + foreach my $ref (get_branch_refs()) {
> > + $remotes->{$remote}{$ref} = [ grep {
> > + $_->{'name'} =~ s!^$remote/!!
> > + } @remoteheads ];
> > + }
> > }
> > }
>
> Hmmm, why? Aren't these additional ones about the local
> "branch-like" refs? What makes us think that these names are also
> shared with the names from remote hierarchies?
Might be another place where I had no clue if the change is right.
Sorry.
>
> > @@ -3644,7 +3691,7 @@ sub parse_from_to_diffinfo {
> >
> > sub git_get_heads_list {
> > my ($limit, @classes) = @_;
> > - @classes = ('heads') unless @classes;
> > + @classes = get_branch_refs() unless @classes;
> > my @patterns = map { "refs/$_" } @classes;
> > my @headslist;
> >
> > @@ -3662,7 +3709,8 @@ sub git_get_heads_list {
> > my ($committer, $epoch, $tz) =
> > ($committerinfo =~ /^(.*) ([0-9]+) (.*)$/);
> > $ref_item{'fullname'} = $name;
> > - $name =~ s!^refs/(?:head|remote)s/!!;
> > + my $strip_refs = join '|', get_branch_refs();
> > + $name =~ s!^refs/(?:$strip_refs|remotes)/!!;
> >
> > $ref_item{'name'} = $name;
> > $ref_item{'id'} = $hash;
> > @@ -4286,7 +4334,7 @@ sub git_print_page_nav {
> > # available if the feature is enabled
> > sub format_ref_views {
> > my ($current) = @_;
> > - my @ref_views = qw{tags heads};
> > + my @ref_views = ('tags', get_branch_refs());
I'll get rid of that change, too. I just verified that it is wrong too.
> > push @ref_views, 'remotes' if gitweb_check_feature('remote_heads');
> > return join " | ", map {
> > $_ eq $current ? $_ :
> > @@ -7179,7 +7227,8 @@ sub snapshot_name {
> > $ver = $1;
> > } else {
> > # branches and other need shortened SHA-1 hash
> > - if ($hash =~ m!^refs/(?:heads|remotes)/(.*)$!) {
> > + my $strip_refs = join '|', get_branch_refs();
> > + if ($hash =~ m!^refs/(?:$strip_refs|remotes)/(.*)$!) {
> > $ver = $1;
> > }
> > $ver .= '-' . git_get_short_hash($project, $hash);
>
> As the elements of @additional_branch_refs are expected by code
> added by this patch to never have any special metacharacters in
> them, it probably is a good idea to sanity check it to catch
> misconfigurations and typos before doing anything else.
>
I assume that in case of misconfiguration we are returning 500.
I added a sanity checking for duplicate refs, for explicitly specified
'heads' and refs that fail to pass the validate_ref (which I splitted
from validate_refname).
As for metacharacters - valid ref can contain a '|' which is a
metacharacter in regex, so I wrapped some uses of
@additional_branch_refs members in regexes into \Q and \E or used a
quotemeta on them. That escapes metacharacters.
Also, I added some docs to gitweb.conf.txt.
Patch in "[PATCH v2] gitweb: Add an option for adding more branch refs"
> Other than that, looks good to me.
>
> Thanks.
--
Krzesimir Nowak
Software Developer
Endocode AG
krzesimir@endocode.com
------
Endocode AG, Johannisstraße 20, 10117 Berlin
info@endocode.com | www.endocode.com
Vorstandsvorsitzender: Mirko Boehm
Vorstände: Dr. Karl Beecher, Chris Kühl, Sebastian Sucker
Aufsichtsratsvorsitzende: Jennifer Beecher
Registergericht: Amtsgericht Charlottenburg - HRB 150748 B
next prev parent reply other threads:[~2013-11-27 15:34 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-11-26 10:37 [PATCH] gitweb: Add an option for adding more branch refs Krzesimir Nowak
2013-11-26 21:48 ` Junio C Hamano
2013-11-27 15:34 ` Krzesimir Nowak [this message]
2013-11-27 15:56 ` Jakub Narębski
2013-11-27 16:15 ` Krzesimir Nowak
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1385566482.2131.22.camel@localhost.localdomain \
--to=krzesimir@endocode.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.