gitweb: parse project/action/hash_base:filename PATH_INFO
authorGiuseppe Bilotta <giuseppe.bilotta@gmail.com>
Tue, 21 Oct 2008 19:34:50 +0000 (21:34 +0200)
committerJunio C Hamano <gitster@pobox.com>
Sat, 25 Oct 2008 19:25:14 +0000 (12:25 -0700)
This patch enables gitweb to parse URLs with more information embedded
in PATH_INFO, reducing the need for CGI parameters. The typical gitweb
path is now $project/$action/$hash_base:$file_name or
$project/$action/$hash

This is mostly backwards compatible with the old-style gitweb paths,
$project/$branch[:$filename], except when it was used to access a branch
whose name matches a gitweb action.

Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
Acked-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
gitweb/gitweb.perl
index c5254afa7fabbc38c2abf188570cd5ab463b4c37..d09cf0a5202043663b0a45cf89c90b0a0c2edaf4 100755 (executable)
@@ -534,23 +534,55 @@ sub evaluate_path_info {
        return if $input_params{'action'};
        $path_info =~ s,^\Q$project\E/*,,;
 
+       # next, check if we have an action
+       my $action = $path_info;
+       $action =~ s,/.*$,,;
+       if (exists $actions{$action}) {
+               $path_info =~ s,^$action/*,,;
+               $input_params{'action'} = $action;
+       }
+
+       # list of actions that want hash_base instead of hash, but can have no
+       # pathname (f) parameter
+       my @wants_base = (
+               'tree',
+               'history',
+       );
+
        my ($refname, $pathname) = split(/:/, $path_info, 2);
        if (defined $pathname) {
-               # we got "project.git/branch:filename" or "project.git/branch:dir/"
-               # we could use git_get_type(branch:pathname), but it needs $git_dir
+               # we got "branch:filename" or "branch:dir/"
+               # we could use git_get_type(branch:pathname), but:
+               # - it needs $git_dir
+               # - it does a git() call
+               # - the convention of terminating directories with a slash
+               #   makes it superfluous
+               # - embedding the action in the PATH_INFO would make it even
+               #   more superfluous
                $pathname =~ s,^/+,,;
                if (!$pathname || substr($pathname, -1) eq "/") {
-                       $input_params{'action'} = "tree";
+                       $input_params{'action'} ||= "tree";
                        $pathname =~ s,/$,,;
                } else {
-                       $input_params{'action'} = "blob_plain";
+                       $input_params{'action'} ||= "blob_plain";
                }
                $input_params{'hash_base'} ||= $refname;
                $input_params{'file_name'} ||= $pathname;
        } elsif (defined $refname) {
-               # we got "project.git/branch"
-               $input_params{'action'} = "shortlog";
-               $input_params{'hash'} ||= $refname;
+               # we got "branch". In this case we have to choose if we have to
+               # set hash or hash_base.
+               #
+               # Most of the actions without a pathname only want hash to be
+               # set, except for the ones specified in @wants_base that want
+               # hash_base instead. It should also be noted that hand-crafted
+               # links having 'history' as an action and no pathname or hash
+               # set will fail, but that happens regardless of PATH_INFO.
+               $input_params{'action'} ||= "shortlog";
+               if (grep { $_ eq $input_params{'action'} } @wants_base) {
+                       $input_params{'hash_base'} ||= $refname;
+               } else {
+                       $input_params{'hash'} ||= $refname;
+               }
        }
 }
 evaluate_path_info();