From: Jakub Narebski <jnareb@gmail.com>
To: git@vger.kernel.org
Subject: Re: [RFD] gitweb: href() function to generate URLs for CGI
Date: Mon, 21 Aug 2006 20:38:45 +0200 [thread overview]
Message-ID: <eccujr$90h$1@sea.gmane.org> (raw)
In-Reply-To: 7v1wrauex2.fsf@assigned-by-dhcp.cox.net
Junio C Hamano wrote:
> Jakub Narebski <jnareb@gmail.com> writes:
>
>> In first version of href() function we had
>> (commit 06a9d86b49b826562e2b12b5c7e831e20b8f7dce)
>>
>> my $href = "$my_uri?";
>> $href .= esc_param( join(";",
>> map {
>> "$mapping{$_}=$params{$_}"
>> } keys %params
>> ) );
>>
>> First, there was a question what happend if someone would enter
>> parameter name incorrectly, and some key of %params is not found in
>> %mapping hash. The above code would generate warnings (which web admins
>> frown upon), and empty (because undef) parameters corresponding to e.g.
>> mistyped parameter name.
>
> The one in "next" seems to do this (the diff is between "master"
> and "next"):
>
> @@ -204,7 +277,9 @@ sub href(%) {
>
> my $href = "$my_uri?";
> $href .= esc_param( join(";",
> - map { "$mapping{$_}=$params{$_}" } keys %params
> + map {
> + "$mapping{$_}=$params{$_}" if defined $params{$_}
> + } keys %params
> ) );
>
> return $href;
>
This doesn't work as expected. Map works on _every_ element of list; if
expression doesn't return anything it just puts undef I think. For example
while
print join(";",
map {
"a/$_" if ($_ eq lc($_))
} ("a", "b", "C", "d")),
"\n";'
returns "a/a;a/b;;a/d" (notice the doubled ';'), the correct way would be to
use grep instead:
print join(";",
map {
"a/$_"
} grep {
($_ eq lc($_))
} ("a", "b", "C", "d")),
"\n";
returns correct "a/a;a/b;a/d". So the fragment should read what I wrote:
my $href = "$my_uri?";
$href .= esc_param( join(";",
map {
"$mapping{$_}=$params{$_}"
} grep { exists $mapping{$_} } keys %params
) );
>> Second problem is that using href() function, although it consolidates
>> to generate URL for CGI, it changes the order of CGI parameters. It
>> used to be that 'p' (project) parameter was first, then 'a' (action)
>> parameter, then hashes ('h', 'hp', 'hb'), last 'f' (filename) or
>> 'p' (page) or 's' (searchtext). The simplest and fastest solution would
>> be to create array with all keys of %mapping in appropriate order and
>> do something like this:
>>
>> my @mapping_sorted = ('project', 'action', 'hash',
>> 'hash_parent', 'hash_base', 'file_name', 'searchtext');
>>
>> my $href = "$my_uri?";
>> $href .= esc_param( join(";",
>> map {
>> "$mapping{$_}=$params{$_}"
>> } grep { exists $params{$_}} @mapping_sorted;
>> ) );
>>
>> The problem is of course updating both %mappings and @mapping_sorted.
>>
>> Is this really a problem, should this (ordering of CGI parameters)
>> addressed?
>
> Keeping the generated URL stable would be a very desirable
> feature. Perhaps something like this?
>
> sub href(%) {
> my @mapping = ( project => "p",
> action => "a",
> hash => "h",
> hash_parent => "hp",
> hash_base => "hb",
> file_name => "f",
> file_parent => "fp",
> page => "pg",
> searchtext => "s",
> );
> my %mapping;
> for (my $i = 0; $i < @mapping; $i += 2) {
> my ($k, $v) = ($mapping[$i], $mapping[$i+1]);
> $mapping{$k} = [$i, $v];
> }
> my %params = @_;
> $params{"project"} ||= $project;
>
> my $href = "$my_uri?";
> $href .= esc_param( join(";",
> map { $_->[1] }
> sort { $a->[0] <=> $b->[0] }
> map {
> (defined $params{$_} && exists $mapping{$_})
> ? [ $mapping{$_}[0], "$mapping{$_}[1]=$params{$_}" ]
> : ();
> } keys %params
> ) );
>
> return $href;
> }
What about my proposed solution? Don't sort, use sorted keys instead, i.e.
something like (after unmangling whitespace)
sub href(%) {
my @mapping = ( project => "p",
action => "a",
hash => "h",
hash_parent => "hp",
hash_base => "hb",
file_name => "f",
file_parent => "fp",
page => "pg",
searchtext => "s",
);
my %mapping;
my @mapping_keys;
for (my $i = 0; $i < @mapping; $i += 2) {
my ($k, $v) = ($mapping[$i], $mapping[$i+1]);
$mapping{$k} = $v;
push @mapping_keys, $k;
}
my %params = @_;
$params{"project"} ||= $project;
my $href = "$my_uri?";
$href .= esc_param( join(";",
map { "$mapping{$_}=$params{$_}" }
grep { exists $params{$_} }
@mapping_keys
) );
return $href;
}
This has the advantage and disadvantage of constant cost, linear with number
of %mapping keys, instead of N log N cost where N is number of parameters.
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
next prev parent reply other threads:[~2006-08-21 18:39 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-08-21 15:39 [RFD] gitweb: href() function to generate URLs for CGI Jakub Narebski
2006-08-21 15:52 ` Jakub Narebski
2006-08-21 18:22 ` Junio C Hamano
2006-08-21 18:38 ` Jakub Narebski [this message]
2006-08-22 7:09 ` Junio C Hamano
2006-08-22 8:18 ` Jakub Narebski
2006-08-22 8:55 ` Junio C Hamano
2006-08-22 9:34 ` Jakub Narebski
2006-08-22 10:47 ` Jakub Narebski
2006-08-22 22:26 ` Junio C Hamano
2006-08-22 22:39 ` Jakub Narebski
2006-08-22 18:35 ` Randal L. Schwartz
2006-08-22 19:55 ` Jakub Narebski
2006-08-22 20:01 ` Jakub Narebski
2006-08-22 22:21 ` Junio C Hamano
2006-08-22 17:05 ` [PATCH 1/2] gitweb: Drop the href() params which keys are not in %mapping Jakub Narebski
2006-08-22 17:05 ` [PATCH 2/2] gitweb: Sort CGI parameters returned by href() Jakub Narebski
-- strict thread matches above, loose matches on Subject: below --
2006-08-21 15:21 [RFD] gitweb: href() function to generate URLs for CGI Jakub Narebski
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='eccujr$90h$1@sea.gmane.org' \
--to=jnareb@gmail.com \
--cc=git@vger.kernel.org \
/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.