{"thread":{"id":"15705","subject":"[PATCHv3] gitweb: parse parent..current syntax from pathinfo","startedAt":"2008-09-29T15:26:53Z","lastAt":"2008-09-29T15:26:57Z","messageCount":5,"participants":["Giuseppe Bilotta"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"91850","messageId":"1222702017-4496-1-git-send-email-giuseppe.bilotta@gmail.com","threadId":"15705","inReplyTo":null,"subject":"[PATCHv3] gitweb path info enhancements","fromName":"Giuseppe Bilotta","fromEmail":"giuseppe.bilotta@gmail.com","sentAt":"2008-09-29T15:26:53Z","receivedAt":"2008-09-29T15:26:53Z","isPatch":false,"sender":{"key":"giuseppe.bilotta@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1464?v=4"},"body":"Third run for the PATH_INFO handling enhancements in gitweb. A\ntrivial but important bugfix was sent as a separate patch, and the\nother patches were rearranged a little, reducing the total number of\npatches to four, paired in parsing and generation of the enhanced\nPATH_INFO URLs.\n\nThe first two patches deal with the inclusion of action and hash or\nthe hash_base:filename pair in the URL, while still keeping support\nfor old-style PATH_INFO URLs whenever possible.\n\nThe other two patches extend the URL format to also include parent\nhash/filename information when possible.\n\nGiuseppe Bilotta (4):\n  gitweb: parse project/action/hash_base:filename PATH_INFO\n  gitweb: generate project/action/hash URLs\n  gitweb: parse parent..current syntax from pathinfo\n  gitweb: generate parent..current URLs\n\n gitweb/gitweb.perl |  167 +++++++++++++++++++++++++++++++++++++++-------------\n 1 files changed, 126 insertions(+), 41 deletions(-)\n"},{"id":"91851","messageId":"1222702017-4496-2-git-send-email-giuseppe.bilotta@gmail.com","threadId":"15705","inReplyTo":"1222702017-4496-1-git-send-email-giuseppe.bilotta@gmail.com","subject":"[PATCHv3] gitweb: parse project/action/hash_base:filename PATH_INFO","fromName":"Giuseppe Bilotta","fromEmail":"giuseppe.bilotta@gmail.com","sentAt":"2008-09-29T15:26:54Z","receivedAt":"2008-09-29T15:26:54Z","isPatch":false,"sender":{"key":"giuseppe.bilotta@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1464?v=4"},"body":"This patch enables gitweb to parse URLs with more information embedded\nin PATH_INFO, reducing the need for CGI parameters. The typical gitweb\npath is now $project/$action/$hash_base:$file_name or\n$project/$action/$hash\n\nThis is mostly backwards compatible with the old-style gitweb paths,\nexcept when $project/$branch was used to access a branch whose name\nmatches a gitweb action.\n---\n gitweb/gitweb.perl |   90 +++++++++++++++++++++++++++++++---------------------\n 1 files changed, 54 insertions(+), 36 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex ffe3dbf..a3076bd 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -495,6 +495,37 @@ if (defined $searchtext) {\n \t$search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext;\n }\n \n+# dispatch\n+my %actions = (\n+\t\"blame\" => \\&git_blame,\n+\t\"blobdiff\" => \\&git_blobdiff,\n+\t\"blobdiff_plain\" => \\&git_blobdiff_plain,\n+\t\"blob\" => \\&git_blob,\n+\t\"blob_plain\" => \\&git_blob_plain,\n+\t\"commitdiff\" => \\&git_commitdiff,\n+\t\"commitdiff_plain\" => \\&git_commitdiff_plain,\n+\t\"commit\" => \\&git_commit,\n+\t\"forks\" => \\&git_forks,\n+\t\"heads\" => \\&git_heads,\n+\t\"history\" => \\&git_history,\n+\t\"log\" => \\&git_log,\n+\t\"rss\" => \\&git_rss,\n+\t\"atom\" => \\&git_atom,\n+\t\"search\" => \\&git_search,\n+\t\"search_help\" => \\&git_search_help,\n+\t\"shortlog\" => \\&git_shortlog,\n+\t\"summary\" => \\&git_summary,\n+\t\"tag\" => \\&git_tag,\n+\t\"tags\" => \\&git_tags,\n+\t\"tree\" => \\&git_tree,\n+\t\"snapshot\" => \\&git_snapshot,\n+\t\"object\" => \\&git_object,\n+\t# those below don't need $project\n+\t\"opml\" => \\&git_opml,\n+\t\"project_list\" => \\&git_project_list,\n+\t\"project_index\" => \\&git_project_index,\n+);\n+\n # now read PATH_INFO and use it as alternative to parameters\n sub evaluate_path_info {\n \treturn if defined $project;\n@@ -519,9 +550,19 @@ sub evaluate_path_info {\n \t# do not change any parameters if an action is given using the query string\n \treturn if $action;\n \t$path_info =~ s,^\\Q$project\\E/*,,;\n+\n+\t# next comes the action\n+\t$action = $path_info;\n+\t$action =~ s,/.*$,,;\n+\tif (exists $actions{$action}) {\n+\t\t$path_info =~ s,^$action/*,,;\n+\t} else {\n+\t\t$action  = undef;\n+\t}\n+\n \tmy ($refname, $pathname) = split(/:/, $path_info, 2);\n \tif (defined $pathname) {\n-\t\t# we got \"project.git/branch:filename\" or \"project.git/branch:dir/\"\n+\t\t# we got \"project.git/action/branch:filename\" or \"project.git/action/branch:dir/\"\n \t\t# we could use git_get_type(branch:pathname), but it needs $git_dir\n \t\t$pathname =~ s,^/+,,;\n \t\tif (!$pathname || substr($pathname, -1) eq \"/\") {\n@@ -534,8 +575,9 @@ sub evaluate_path_info {\n \t\t$file_name ||= validate_pathname($pathname);\n \t} elsif (defined $refname) {\n \t\t# we got \"project.git/branch\"\n-\t\t$action ||= \"shortlog\";\n-\t\t$hash   ||= validate_refname($refname);\n+\t\t$action    ||= \"shortlog\";\n+\t\t$hash      ||= validate_refname($refname);\n+\t\t$hash_base ||= validate_refname($refname);\n \t}\n }\n evaluate_path_info();\n@@ -544,37 +586,6 @@ evaluate_path_info();\n our $git_dir;\n $git_dir = \"$projectroot/$project\" if $project;\n \n-# dispatch\n-my %actions = (\n-\t\"blame\" => \\&git_blame,\n-\t\"blobdiff\" => \\&git_blobdiff,\n-\t\"blobdiff_plain\" => \\&git_blobdiff_plain,\n-\t\"blob\" => \\&git_blob,\n-\t\"blob_plain\" => \\&git_blob_plain,\n-\t\"commitdiff\" => \\&git_commitdiff,\n-\t\"commitdiff_plain\" => \\&git_commitdiff_plain,\n-\t\"commit\" => \\&git_commit,\n-\t\"forks\" => \\&git_forks,\n-\t\"heads\" => \\&git_heads,\n-\t\"history\" => \\&git_history,\n-\t\"log\" => \\&git_log,\n-\t\"rss\" => \\&git_rss,\n-\t\"atom\" => \\&git_atom,\n-\t\"search\" => \\&git_search,\n-\t\"search_help\" => \\&git_search_help,\n-\t\"shortlog\" => \\&git_shortlog,\n-\t\"summary\" => \\&git_summary,\n-\t\"tag\" => \\&git_tag,\n-\t\"tags\" => \\&git_tags,\n-\t\"tree\" => \\&git_tree,\n-\t\"snapshot\" => \\&git_snapshot,\n-\t\"object\" => \\&git_object,\n-\t# those below don't need $project\n-\t\"opml\" => \\&git_opml,\n-\t\"project_list\" => \\&git_project_list,\n-\t\"project_index\" => \\&git_project_index,\n-);\n-\n if (!defined $action) {\n \tif (defined $hash) {\n \t\t$action = git_get_type($hash);\n@@ -631,8 +642,15 @@ sub href (%) {\n \tif ($params{-replay}) {\n \t\twhile (my ($name, $symbol) = each %mapping) {\n \t\t\tif (!exists $params{$name}) {\n-\t\t\t\t# to allow for multivalued params we use arrayref form\n-\t\t\t\t$params{$name} = [ $cgi->param($symbol) ];\n+\t\t\t\t# the parameter we want to recycle may be either part of the\n+\t\t\t\t# list of CGI parameter, or recovered from PATH_INFO\n+\t\t\t\tif ($cgi->param($symbol)) {\n+\t\t\t\t\t# to allow for multivalued params we use arrayref form\n+\t\t\t\t\t$params{$name} = [ $cgi->param($symbol) ];\n+\t\t\t\t} else {\n+\t\t\t\t\tno strict 'refs';\n+\t\t\t\t\t$params{$name} = $$name if $$name;\n+\t\t\t\t}\n \t\t\t}\n \t\t}\n \t}\n-- \n1.5.6.5\n"},{"id":"91852","messageId":"1222702017-4496-3-git-send-email-giuseppe.bilotta@gmail.com","threadId":"15705","inReplyTo":"1222702017-4496-2-git-send-email-giuseppe.bilotta@gmail.com","subject":"[PATCHv3] gitweb: generate project/action/hash URLs","fromName":"Giuseppe Bilotta","fromEmail":"giuseppe.bilotta@gmail.com","sentAt":"2008-09-29T15:26:55Z","receivedAt":"2008-09-29T15:26:55Z","isPatch":false,"sender":{"key":"giuseppe.bilotta@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1464?v=4"},"body":"When generating path info URLs, reduce the number of CGI parameters by\nembedding action and hash_parent:filename or hash in the path.\n\nSigned-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>\n---\n gitweb/gitweb.perl |   32 +++++++++++++++++++++++++++++---\n 1 files changed, 29 insertions(+), 3 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex a3076bd..75d4178 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -657,14 +657,40 @@ sub href (%) {\n \n \tmy ($use_pathinfo) = gitweb_check_feature('pathinfo');\n \tif ($use_pathinfo) {\n-\t\t# use PATH_INFO for project name\n+\t\t# try to put as many parameters as possible in PATH_INFO:\n+\t\t#   - project name\n+\t\t#   - action\n+\t\t#   - hash or hash_base:filename\n+\n+\t\t# Strip any trailing / from $href, or we might get double\n+\t\t# slashes when the script is the DirectoryIndex\n+\t\t#\n+\t\t$href =~ s,/$,,;\n+\n+\t\t# Then add the project name, if present\n \t\t$href .= \"/\".esc_url($params{'project'}) if defined $params{'project'};\n \t\tdelete $params{'project'};\n \n-\t\t# Summary just uses the project path URL\n-\t\tif (defined $params{'action'} && $params{'action'} eq 'summary') {\n+\t\t# Summary just uses the project path URL, any other action is\n+\t\t# added to the URL\n+\t\tif (defined $params{'action'}) {\n+\t\t\t$href .= \"/\".esc_url($params{'action'}) unless $params{'action'} eq 'summary';\n \t\t\tdelete $params{'action'};\n \t\t}\n+\n+\t\t# Finally, we put either hash_base:/file_name or hash\n+\t\tif (defined $params{'hash_base'}) {\n+\t\t\t$href .= \"/\".esc_url($params{'hash_base'});\n+\t\t\tif (defined $params{'file_name'}) {\n+\t\t\t\t$href .= \":/\".esc_url($params{'file_name'});\n+\t\t\t\tdelete $params{'file_name'};\n+\t\t\t}\n+\t\t\tdelete $params{'hash'};\n+\t\t\tdelete $params{'hash_base'};\n+\t\t} elsif (defined $params{'hash'}) {\n+\t\t\t$href .= \"/\".esc_url($params{'hash'});\n+\t\t\tdelete $params{'hash'};\n+\t\t}\n \t}\n \n \t# now encode the parameters explicitly\n-- \n1.5.6.5\n"},{"id":"91849","messageId":"1222702017-4496-4-git-send-email-giuseppe.bilotta@gmail.com","threadId":"15705","inReplyTo":"1222702017-4496-3-git-send-email-giuseppe.bilotta@gmail.com","subject":"[PATCHv3] gitweb: parse parent..current syntax from pathinfo","fromName":"Giuseppe Bilotta","fromEmail":"giuseppe.bilotta@gmail.com","sentAt":"2008-09-29T15:26:56Z","receivedAt":"2008-09-29T15:26:56Z","isPatch":false,"sender":{"key":"giuseppe.bilotta@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1464?v=4"},"body":"This makes it possible to use an URL such as\n$project/somebranch..otherbranch:/filename to get a diff between\ndifferent version of a file. Paths like\n$project/$action/somebranch:/somefile..otherbranch:/otherfile are parsed\nas well.\n\nSigned-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>\n---\n gitweb/gitweb.perl |   26 ++++++++++++++++++++++++--\n 1 files changed, 24 insertions(+), 2 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 75d4178..7b4f2d3 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -560,7 +560,9 @@ sub evaluate_path_info {\n \t\t$action  = undef;\n \t}\n \n-\tmy ($refname, $pathname) = split(/:/, $path_info, 2);\n+\t$path_info =~ /^((.+?)(:(.+))?\\.\\.)?(.+?)(:(.+))?$/;\n+\tmy ($parentrefname, $parentpathname, $refname, $pathname) = (\n+\t\t$2, $4, $5, $7);\n \tif (defined $pathname) {\n \t\t# we got \"project.git/action/branch:filename\" or \"project.git/action/branch:dir/\"\n \t\t# we could use git_get_type(branch:pathname), but it needs $git_dir\n@@ -569,7 +571,11 @@ sub evaluate_path_info {\n \t\t\t$action  ||= \"tree\";\n \t\t\t$pathname =~ s,/$,,;\n \t\t} else {\n-\t\t\t$action  ||= \"blob_plain\";\n+\t\t\tif ($parentrefname) {\n+\t\t\t\t$action ||= \"blobdiff_plain\";\n+\t\t\t} else {\n+\t\t\t\t$action  ||= \"blob_plain\";\n+\t\t\t}\n \t\t}\n \t\t$hash_base ||= validate_refname($refname);\n \t\t$file_name ||= validate_pathname($pathname);\n@@ -579,6 +585,22 @@ sub evaluate_path_info {\n \t\t$hash      ||= validate_refname($refname);\n \t\t$hash_base ||= validate_refname($refname);\n \t}\n+\t# the parent part might be missing the pathname, in which case we use the $file_name, if present\n+\tif (defined $parentrefname) {\n+\t\t$hash_parent_base ||= validate_refname($parentrefname);\n+\t\tif ($parentpathname) {\n+\t\t\t$parentpathname =~ s,^/+,,;\n+\t\t\t$parentpathname =~ s,/$,,;\n+\t\t\t$file_parent ||= validate_pathname($parentpathname);\n+\t\t} else {\n+\t\t\t$file_parent ||= $file_name\n+\t\t}\n+\t\tif (defined $file_parent) {\n+\t\t\t$hash_parent ||= git_get_hash_by_path($hash_parent_base, $file_parent);\n+\t\t} else {\n+\t\t\t$hash_parent ||= validate_refname($parentrefname);\n+\t\t}\n+\t}\n }\n evaluate_path_info();\n \n-- \n1.5.6.5\n"},{"id":"91853","messageId":"1222702017-4496-5-git-send-email-giuseppe.bilotta@gmail.com","threadId":"15705","inReplyTo":"1222702017-4496-4-git-send-email-giuseppe.bilotta@gmail.com","subject":"[PATCHv3] gitweb: generate parent..current URLs","fromName":"Giuseppe Bilotta","fromEmail":"giuseppe.bilotta@gmail.com","sentAt":"2008-09-29T15:26:57Z","receivedAt":"2008-09-29T15:26:57Z","isPatch":false,"sender":{"key":"giuseppe.bilotta@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1464?v=4"},"body":"If use_pathinfo is enabled, href now creates links that contain paths in\nthe form $project/$action/oldhash:/oldname..newhash:/newname for actions\nthat use hash_parent etc.\n\nIf any of the filename contains two consecutive dots, it's kept as a CGI\nparameter since the resulting path would otherwise be ambiguous.\n\nSigned-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>\n---\n gitweb/gitweb.perl |   27 +++++++++++++++++++++++----\n 1 files changed, 23 insertions(+), 4 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 7b4f2d3..4fa4364 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -700,17 +700,36 @@ sub href (%) {\n \t\t\tdelete $params{'action'};\n \t\t}\n \n-\t\t# Finally, we put either hash_base:/file_name or hash\n+\t\t# Next, we put hash_parent_base:/file_parent..hash_base:/file_name,\n+\t\t# stripping nonexistent or useless pieces\n+\t\t$href .= \"/\" if ($params{'hash_base'} || $params{'hash_parent_base'}\n+\t\t\t|| $params{'hash_parent'} || $params{'hash'});\n \t\tif (defined $params{'hash_base'}) {\n-\t\t\t$href .= \"/\".esc_url($params{'hash_base'});\n-\t\t\tif (defined $params{'file_name'}) {\n+\t\t\tif (defined $params{'hash_parent_base'}) {\n+\t\t\t\t$href .= esc_url($params{'hash_parent_base'});\n+\t\t\t\t# skip the file_parent if it's the same as the file_name\n+\t\t\t\tdelete $params{'file_parent'} if $params{'file_parent'} eq $params{'file_name'};\n+\t\t\t\tif (defined $params{'file_parent'} && $params{'file_parent'} !~ /\\.\\./) {\n+\t\t\t\t\t$href .= \":/\".esc_url($params{'file_parent'});\n+\t\t\t\t\tdelete $params{'file_parent'};\n+\t\t\t\t}\n+\t\t\t\t$href .= \"..\";\n+\t\t\t\tdelete $params{'hash_parent'};\n+\t\t\t\tdelete $params{'hash_parent_base'};\n+\t\t\t} elsif (defined $params{'hash_parent'}) {\n+\t\t\t\t$href .= esc_url($params{'hash_parent'}). \"..\";\n+\t\t\t\tdelete $params{'hash_parent'};\n+\t\t\t}\n+\n+\t\t\t$href .= esc_url($params{'hash_base'});\n+\t\t\tif (defined $params{'file_name'} && $params{'file_name'} !~ /\\.\\./) {\n \t\t\t\t$href .= \":/\".esc_url($params{'file_name'});\n \t\t\t\tdelete $params{'file_name'};\n \t\t\t}\n \t\t\tdelete $params{'hash'};\n \t\t\tdelete $params{'hash_base'};\n \t\t} elsif (defined $params{'hash'}) {\n-\t\t\t$href .= \"/\".esc_url($params{'hash'});\n+\t\t\t$href .= esc_url($params{'hash'});\n \t\t\tdelete $params{'hash'};\n \t\t}\n \t}\n-- \n1.5.6.5\n"}]}