@@ -67,40 +67,6 @@ $strict_export = "++GITWEB_STRICT_EXPORT++";$GITWEB_CONFIG=$ENV{'GITWEB_CONFIG'}||"++GITWEB_CONFIG++";$GITWEB_CONFIG_SYSTEM=$ENV{'GITWEB_CONFIG_SYSTEM'}||"++GITWEB_CONFIG_SYSTEM++";-subgitweb_get_feature{-my($name)=@_;-returnunlessexists$feature{$name};-my($sub,$override,@defaults)=(-$feature{$name}{'sub'},-$feature{$name}{'override'},-@{$feature{$name}{'default'}});-# project specific override is possible only if we have project-if(!$override||!defined$git_dir){-return@defaults;-}-if(!defined$sub){-warn"feature $name is not overridable";-return@defaults;-}-return$sub->(@defaults);-}--# A wrapper to check if a given feature is enabled.-# With this, you can say-#-# my $bool_feat = gitweb_check_feature('bool_feat');-# gitweb_check_feature('bool_feat') or somecode;-#-# instead of-#-# my ($bool_feat) = gitweb_get_feature('bool_feat');-# (gitweb_get_feature('bool_feat'))[0] or somecode;-#-subgitweb_check_feature{-return(gitweb_get_feature(@_))[0];-}--subfeature_bool{my$key=shift;my($val)=git_get_project_config($key,'--bool');
@@ -159,19 +125,6 @@ sub check_export_ok {(!$export_auth_hook||$export_auth_hook->($dir)));}-# process alternate names for backward compatibility-# filter out unsupported (unknown) snapshot formats-subfilter_snapshot_fmts{-my@fmts=@_;--@fmts=map{-exists$known_snapshot_format_aliases{$_}?-$known_snapshot_format_aliases{$_}:$_}@fmts;-@fmts=grep{-exists$known_snapshot_formats{$_}&&-!$known_snapshot_formats{$_}{'disabled'}}@fmts;-}-# Get loadavg of system, to compare against $maxload.# Currently it requires '/proc/loadavg' present to get loadavg;# if it is not present it returns 0, which means no load checking.
@@ -486,26 +439,6 @@ sub evaluate_git_dir {$git_dir="$projectroot/$project"if$project;}-our(@snapshot_fmts,$git_avatar);-subconfigure_gitweb_features{-# list of supported snapshot formats-our@snapshot_fmts=gitweb_get_feature('snapshot');-@snapshot_fmts=filter_snapshot_fmts(@snapshot_fmts);--# check that the avatar feature is set to a known provider name,-# and for each provider check if the dependencies are satisfied.-# if the provider name is invalid or the dependencies are not met,-# reset $git_avatar to the empty string.-our($git_avatar)=gitweb_get_feature('avatar');-if($git_avatareq'gravatar'){-$git_avatar=''unless(eval{requireDigest::MD5;1;});-}elsif($git_avatareq'picon'){-# no dependencies-}else{-$git_avatar='';-}-}-# custom error handler: 'die <message>' is Internal Server Errorsubhandle_errors_html{my$msg=shift;# it is already HTML escaped
@@ -10,13 +10,16 @@ use strict;usewarnings;useExporterqw(import);-our@EXPORT=qw(evaluate_gitweb_config$version$projectroot$project_maxdepth$mimetypes_file+our@EXPORT=qw(evaluate_gitweb_configgitweb_check_featuregitweb_get_featureconfigure_gitweb_features+filter_snapshot_fmts$version$projectroot$project_maxdepth$mimetypes_file$git_avatar$projects_list@git_base_url_list$export_ok$strict_export$home_link_str$site_name$site_header$site_footer$home_text@stylesheets$stylesheet$logo$favicon$javascript$GITWEB_CONFIG$GITWEB_CONFIG_SYSTEM$logo_url$logo_label$export_auth_hook$projects_list_description_width$default_projects_order$default_blob_plain_mimetype$default_text_plain_charset$fallback_encoding@diff_opts$prevent_xss$maxload-%avatar_size%known_snapshot_formats%known_snapshot_format_aliases%feature);+%avatar_size%known_snapshot_formats%feature@snapshot_fmts);++useGitweb::Gitqw($git_dir);# The following variables are affected by build-time configuration# and hence their initialisation is put in gitweb.perl script
@@ -425,4 +428,71 @@ sub evaluate_gitweb_config {}}++subgitweb_get_feature{+my($name)=@_;+returnunlessexists$feature{$name};+my($sub,$override,@defaults)=(+$feature{$name}{'sub'},+$feature{$name}{'override'},+@{$feature{$name}{'default'}});+# project specific override is possible only if we have project+if(!$override||!defined$git_dir){+return@defaults;+}+if(!defined$sub){+warn"feature $name is not overridable";+return@defaults;+}+return$sub->(@defaults);+}++# A wrapper to check if a given feature is enabled.+# With this, you can say+#+# my $bool_feat = gitweb_check_feature('bool_feat');+# gitweb_check_feature('bool_feat') or somecode;+#+# instead of+#+# my ($bool_feat) = gitweb_get_feature('bool_feat');+# (gitweb_get_feature('bool_feat'))[0] or somecode;+#+subgitweb_check_feature{+return(gitweb_get_feature(@_))[0];+}++# process alternate names for backward compatibility+# filter out unsupported (unknown) snapshot formats+subfilter_snapshot_fmts{+my@fmts=@_;++@fmts=map{+exists$known_snapshot_format_aliases{$_}?+$known_snapshot_format_aliases{$_}:$_}@fmts;+@fmts=grep{+exists$known_snapshot_formats{$_}&&+!$known_snapshot_formats{$_}{'disabled'}}@fmts;+}++our(@snapshot_fmts,$git_avatar);+subconfigure_gitweb_features{+# list of supported snapshot formats+our@snapshot_fmts=gitweb_get_feature('snapshot');+@snapshot_fmts=filter_snapshot_fmts(@snapshot_fmts);++# check that the avatar feature is set to a known provider name,+# and for each provider check if the dependencies are satisfied.+# if the provider name is invalid or the dependencies are not met,+# reset $git_avatar to the empty string.+our($git_avatar)=gitweb_get_feature('avatar');+if($git_avatareq'gravatar'){+$git_avatar=''unless(eval{requireDigest::MD5;1;});+}elsif($git_avatareq'picon'){+# no dependencies+}else{+$git_avatar='';+}+}+1;
@@ -28,6 +28,7 @@ use Gitweb::Git;useGitweb::Config;useGitweb::Request;useGitweb::Escape;+useGitweb::HTML::Link;BEGIN{CGI->compile()if$ENV{'MOD_PERL'};
@@ -554,128 +555,6 @@ sub run {run();## ======================================================================-## action links--# possible values of extra options-# -full => 0|1 - use absolute/full URL ($my_uri/$my_url as base)-# -replay => 1 - start from a current view (replay with modifications)-# -path_info => 0|1 - don't use/use path_info URL (if possible)-subhref{-my%params=@_;-# default is to use -absolute url() i.e. $my_uri-my$href=$params{-full}?$my_url:$my_uri;--$params{'project'}=$projectunlessexists$params{'project'};--if($params{-replay}){-while(my($name,$symbol)=each%cgi_param_mapping){-if(!exists$params{$name}){-$params{$name}=$input_params{$name};-}-}-}--my$use_pathinfo=gitweb_check_feature('pathinfo');-if(defined$params{'project'}&&-(exists$params{-path_info}?$params{-path_info}:$use_pathinfo)){-# try to put as many parameters as possible in PATH_INFO:-# - project name-# - action-# - hash_parent or hash_parent_base:/file_parent-# - hash or hash_base:/filename-# - the snapshot_format as an appropriate suffix--# When the script is the root DirectoryIndex for the domain,-# $href here would be something like http://gitweb.example.com/-# Thus, we strip any trailing / from $href, to spare us double-# slashes in the final URL-$href=~s,/$,,;--# Then add the project name, if present-$href.="/".esc_url($params{'project'});-delete$params{'project'};--# since we destructively absorb parameters, we keep this-# boolean that remembers if we're handling a snapshot-my$is_snapshot=$params{'action'}eq'snapshot';--# Summary just uses the project path URL, any other action is-# added to the URL-if(defined$params{'action'}){-$href.="/".esc_url($params{'action'})unless$params{'action'}eq'summary';-delete$params{'action'};-}--# Next, we put hash_parent_base:/file_parent..hash_base:/file_name,-# stripping nonexistent or useless pieces-$href.="/"if($params{'hash_base'}||$params{'hash_parent_base'}-||$params{'hash_parent'}||$params{'hash'});-if(defined$params{'hash_base'}){-if(defined$params{'hash_parent_base'}){-$href.=esc_url($params{'hash_parent_base'});-# skip the file_parent if it's the same as the file_name-if(defined$params{'file_parent'}){-if(defined$params{'file_name'}&&$params{'file_parent'}eq$params{'file_name'}){-delete$params{'file_parent'};-}elsif($params{'file_parent'}!~/\.\./){-$href.=":/".esc_url($params{'file_parent'});-delete$params{'file_parent'};-}-}-$href.="..";-delete$params{'hash_parent'};-delete$params{'hash_parent_base'};-}elsif(defined$params{'hash_parent'}){-$href.=esc_url($params{'hash_parent'})."..";-delete$params{'hash_parent'};-}--$href.=esc_url($params{'hash_base'});-if(defined$params{'file_name'}&&$params{'file_name'}!~/\.\./){-$href.=":/".esc_url($params{'file_name'});-delete$params{'file_name'};-}-delete$params{'hash'};-delete$params{'hash_base'};-}elsif(defined$params{'hash'}){-$href.=esc_url($params{'hash'});-delete$params{'hash'};-}--# If the action was a snapshot, we can absorb the-# snapshot_format parameter too-if($is_snapshot){-my$fmt=$params{'snapshot_format'};-# snapshot_format should always be defined when href()-# is called, but just in case some code forgets, we-# fall back to the default-$fmt||=$snapshot_fmts[0];-$href.=$known_snapshot_formats{$fmt}{'suffix'};-delete$params{'snapshot_format'};-}-}--# now encode the parameters explicitly-my@result=();-for(my$i=0;$i<@cgi_param_mapping;$i+=2){-my($name,$symbol)=($cgi_param_mapping[$i],$cgi_param_mapping[$i+1]);-if(defined$params{$name}){-if(ref($params{$name})eq"ARRAY"){-foreachmy$par(@{$params{$name}}){-push@result,$symbol."=".esc_param($par);-}-}else{-push@result,$symbol."=".esc_param($params{$name});-}-}-}-$href.="?".join(';',@result)ifscalar@result;--return$href;-}---## ======================================================================## validation, quoting/unquoting and escapingsubvalidate_action{
@@ -0,0 +1,137 @@+#!/usr/bin/perl+#+# Gitweb::HTML::Link -- gitweb's action links package+#+# This program is licensed under the GPLv2++packageGitweb::HTML::Link;++usestrict;+usewarnings;+useExporterqw(import);++our@EXPORT=qw(href);++useGitweb::Configqw(gitweb_check_feature%known_snapshot_formats@snapshot_fmts);+useGitweb::Requestqw($project%cgi_param_mapping@cgi_param_mapping$my_url$my_uri%input_params);+useGitweb::Escapeqw(esc_urlesc_param);++# possible values of extra options+# -full => 0|1 - use absolute/full URL ($my_uri/$my_url as base)+# -replay => 1 - start from a current view (replay with modifications)+# -path_info => 0|1 - don't use/use path_info URL (if possible)+subhref{+my%params=@_;+# default is to use -absolute url() i.e. $my_uri+my$href=$params{-full}?$my_url:$my_uri;++$params{'project'}=$projectunlessexists$params{'project'};++if($params{-replay}){+while(my($name,$symbol)=each%cgi_param_mapping){+if(!exists$params{$name}){+$params{$name}=$input_params{$name};+}+}+}++my$use_pathinfo=gitweb_check_feature('pathinfo');+if(defined$params{'project'}&&+(exists$params{-path_info}?$params{-path_info}:$use_pathinfo)){+# try to put as many parameters as possible in PATH_INFO:+# - project name+# - action+# - hash_parent or hash_parent_base:/file_parent+# - hash or hash_base:/filename+# - the snapshot_format as an appropriate suffix++# When the script is the root DirectoryIndex for the domain,+# $href here would be something like http://gitweb.example.com/+# Thus, we strip any trailing / from $href, to spare us double+# slashes in the final URL+$href=~s,/$,,;++# Then add the project name, if present+$href.="/".esc_url($params{'project'});+delete$params{'project'};++# since we destructively absorb parameters, we keep this+# boolean that remembers if we're handling a snapshot+my$is_snapshot=$params{'action'}eq'snapshot';++# Summary just uses the project path URL, any other action is+# added to the URL+if(defined$params{'action'}){+$href.="/".esc_url($params{'action'})unless$params{'action'}eq'summary';+delete$params{'action'};+}++# Next, we put hash_parent_base:/file_parent..hash_base:/file_name,+# stripping nonexistent or useless pieces+$href.="/"if($params{'hash_base'}||$params{'hash_parent_base'}+||$params{'hash_parent'}||$params{'hash'});+if(defined$params{'hash_base'}){+if(defined$params{'hash_parent_base'}){+$href.=esc_url($params{'hash_parent_base'});+# skip the file_parent if it's the same as the file_name+if(defined$params{'file_parent'}){+if(defined$params{'file_name'}&&$params{'file_parent'}eq$params{'file_name'}){+delete$params{'file_parent'};+}elsif($params{'file_parent'}!~/\.\./){+$href.=":/".esc_url($params{'file_parent'});+delete$params{'file_parent'};+}+}+$href.="..";+delete$params{'hash_parent'};+delete$params{'hash_parent_base'};+}elsif(defined$params{'hash_parent'}){+$href.=esc_url($params{'hash_parent'})."..";+delete$params{'hash_parent'};+}++$href.=esc_url($params{'hash_base'});+if(defined$params{'file_name'}&&$params{'file_name'}!~/\.\./){+$href.=":/".esc_url($params{'file_name'});+delete$params{'file_name'};+}+delete$params{'hash'};+delete$params{'hash_base'};+}elsif(defined$params{'hash'}){+$href.=esc_url($params{'hash'});+delete$params{'hash'};+}++# If the action was a snapshot, we can absorb the+# snapshot_format parameter too+if($is_snapshot){+my$fmt=$params{'snapshot_format'};+# snapshot_format should always be defined when href()+# is called, but just in case some code forgets, we+# fall back to the default+$fmt||=$snapshot_fmts[0];+$href.=$known_snapshot_formats{$fmt}{'suffix'};+delete$params{'snapshot_format'};+}+}++# now encode the parameters explicitly+my@result=();+for(my$i=0;$i<@cgi_param_mapping;$i+=2){+my($name,$symbol)=($cgi_param_mapping[$i],$cgi_param_mapping[$i+1]);+if(defined$params{$name}){+if(ref($params{$name})eq"ARRAY"){+foreachmy$par(@{$params{$name}}){+push@result,$symbol."=".esc_param($par);+}+}else{+push@result,$symbol."=".esc_param($params{$name});+}+}+}+$href.="?".join(';',@result)ifscalar@result;++return$href;+}++1;
@@ -0,0 +1,17 @@+#!/usr/bin/perl+#+# Gitweb::HTML -- gitweb's HTML subs package+#+# This program is licensed under the GPLv2++packageGitweb::HTML;++usestrict;+usewarnings;+useExporterqw(import);++our@EXPORT=qw(href);++useGitweb::HTML::Link;++1;
@@ -582,219 +582,6 @@ sub project_in_list {}## -----------------------------------------------------------------------## HTML aware string manipulation--# Try to chop given string on a word boundary between position-# $len and $len+$add_len. If there is no word boundary there,-# chop at $len+$add_len. Do not chop if chopped part plus ellipsis-# (marking chopped part) would be longer than given string.-subchop_str{-my$str=shift;-my$len=shift;-my$add_len=shift||10;-my$where=shift||'right';# 'left' | 'center' | 'right'--# Make sure perl knows it is utf8 encoded so we don't-# cut in the middle of a utf8 multibyte char.-$str=to_utf8($str);--# allow only $len chars, but don't cut a word if it would fit in $add_len-# if it doesn't fit, cut it if it's still longer than the dots we would add-# remove chopped character entities entirely--# when chopping in the middle, distribute $len into left and right part-# return early if chopping wouldn't make string shorter-if($whereeq'center'){-return$strif($len+5>=length($str));# filler is length 5-$len=int($len/2);-}else{-return$strif($len+4>=length($str));# filler is length 4-}--# regexps: ending and beginning with word part up to $add_len-my$endre=qr/.{$len}\w{0,$add_len}/;-my$begre=qr/\w{0,$add_len}.{$len}/;--if($whereeq'left'){-$str=~m/^(.*?)($begre)$/;-my($lead,$body)=($1,$2);-if(length($lead)>4){-$lead=" ...";-}-return"$lead$body";--}elsif($whereeq'center'){-$str=~m/^($endre)(.*)$/;-my($left,$str)=($1,$2);-$str=~m/^(.*?)($begre)$/;-my($mid,$right)=($1,$2);-if(length($mid)>5){-$mid=" ... ";-}-return"$left$mid$right";--}else{-$str=~m/^($endre)(.*)$/;-my$body=$1;-my$tail=$2;-if(length($tail)>4){-$tail="... ";-}-return"$body$tail";-}-}--# takes the same arguments as chop_str, but also wraps a <span> around the-# result with a title attribute if it does get chopped. Additionally, the-# string is HTML-escaped.-subchop_and_escape_str{-my($str)=@_;--my$chopped=chop_str(@_);-if($choppedeq$str){-returnesc_html($chopped);-}else{-$str=~s/[[:cntrl:]]/?/g;-return$cgi->span({-title=>$str},esc_html($chopped));-}-}--## -----------------------------------------------------------------------## functions returning short strings--# CSS class for given age value (in seconds)-subage_class{-my$age=shift;--if(!defined$age){-return"noage";-}elsif($age<60*60*2){-return"age0";-}elsif($age<60*60*24*2){-return"age1";-}else{-return"age2";-}-}--# convert age in seconds to "nn units ago" string-subage_string{-my$age=shift;-my$age_str;--if($age>60*60*24*365*2){-$age_str=(int$age/60/60/24/365);-$age_str.=" years ago";-}elsif($age>60*60*24*(365/12)*2){-$age_str=int$age/60/60/24/(365/12);-$age_str.=" months ago";-}elsif($age>60*60*24*7*2){-$age_str=int$age/60/60/24/7;-$age_str.=" weeks ago";-}elsif($age>60*60*24*2){-$age_str=int$age/60/60/24;-$age_str.=" days ago";-}elsif($age>60*60*2){-$age_str=int$age/60/60;-$age_str.=" hours ago";-}elsif($age>60*2){-$age_str=int$age/60;-$age_str.=" min ago";-}elsif($age>2){-$age_str=int$age;-$age_str.=" sec ago";-}else{-$age_str.=" right now";-}-return$age_str;-}--useconstant{-S_IFINVALID=>0030000,-S_IFGITLINK=>0160000,-};--# submodule/subproject, a commit object reference-subS_ISGITLINK{-my$mode=shift;--return(($mode&S_IFMT)==S_IFGITLINK)-}--# convert file mode in octal to symbolic file mode string-submode_str{-my$mode=octshift;--if(S_ISGITLINK($mode)){-return'm---------';-}elsif(S_ISDIR($mode&S_IFMT)){-return'drwxr-xr-x';-}elsif(S_ISLNK($mode)){-return'lrwxrwxrwx';-}elsif(S_ISREG($mode)){-# git cares only about the executable bit-if($mode&S_IXUSR){-return'-rwxr-xr-x';-}else{-return'-rw-r--r--';-};-}else{-return'----------';-}-}--# convert file mode in octal to file type string-subfile_type{-my$mode=shift;--if($mode!~m/^[0-7]+$/){-return$mode;-}else{-$mode=oct$mode;-}--if(S_ISGITLINK($mode)){-return"submodule";-}elsif(S_ISDIR($mode&S_IFMT)){-return"directory";-}elsif(S_ISLNK($mode)){-return"symlink";-}elsif(S_ISREG($mode)){-return"file";-}else{-return"unknown";-}-}--# convert file mode in octal to file type description string-subfile_type_long{-my$mode=shift;--if($mode!~m/^[0-7]+$/){-return$mode;-}else{-$mode=oct$mode;-}--if(S_ISGITLINK($mode)){-return"submodule";-}elsif(S_ISDIR($mode&S_IFMT)){-return"directory";-}elsif(S_ISLNK($mode)){-return"symlink";-}elsif(S_ISREG($mode)){-if($mode&S_IXUSR){-return"executable";-}else{-return"file";-};-}else{-return"unknown";-}-}---## ----------------------------------------------------------------------## functions returning short HTML fragments, or transforming HTML fragments## which don't belong to other sections
@@ -0,0 +1,232 @@+#!/usr/bin/perl+#+# Gitweb::HTML::String -- gitweb's string manipulation & short string package+#+# This program is licensed under the GPLv2++packageGitweb::HTML::String;++usestrict;+usewarnings;+useExporterqw(import);++our@EXPORT=qw(chop_strchop_and_escape_strage_classage_stringmode_str+file_typefile_type_long);++useFcntl':mode';+useGitweb::Requestqw($cgi);+useGitweb::Escapeqw(to_utf8esc_html);++## ----------------------------------------------------------------------+## HTML aware string manipulation++# Try to chop given string on a word boundary between position+# $len and $len+$add_len. If there is no word boundary there,+# chop at $len+$add_len. Do not chop if chopped part plus ellipsis+# (marking chopped part) would be longer than given string.+subchop_str{+my$str=shift;+my$len=shift;+my$add_len=shift||10;+my$where=shift||'right';#'left'|'center'|'right'++# Make sure perl knows it is utf8 encoded so we don't+# cut in the middle of a utf8 multibyte char.+$str=to_utf8($str);++# allow only $len chars, but don't cut a word if it would fit in $add_len+# if it doesn't fit, cut it if it's still longer than the dots we would add+# remove chopped character entities entirely++# when chopping in the middle, distribute $len into left and right part+# return early if chopping wouldn't make string shorter+if($whereeq'center'){+return$strif($len+5>=length($str));#fillerislength5+$len=int($len/2);+}else{+return$strif($len+4>=length($str));#fillerislength4+}++# regexps: ending and beginning with word part up to $add_len+my$endre=qr/.{$len}\w{0,$add_len}/;+my$begre=qr/\w{0,$add_len}.{$len}/;++if($whereeq'left'){+$str=~m/^(.*?)($begre)$/;+my($lead,$body)=($1,$2);+if(length($lead)>4){+$lead=" ...";+}+return"$lead$body";++}elsif($whereeq'center'){+$str=~m/^($endre)(.*)$/;+my($left,$str)=($1,$2);+$str=~m/^(.*?)($begre)$/;+my($mid,$right)=($1,$2);+if(length($mid)>5){+$mid=" ... ";+}+return"$left$mid$right";++}else{+$str=~m/^($endre)(.*)$/;+my$body=$1;+my$tail=$2;+if(length($tail)>4){+$tail="... ";+}+return"$body$tail";+}+}++# takes the same arguments as chop_str, but also wraps a <span> around the+# result with a title attribute if it does get chopped. Additionally, the+# string is HTML-escaped.+subchop_and_escape_str{+my($str)=@_;++my$chopped=chop_str(@_);+if($choppedeq$str){+returnesc_html($chopped);+}else{+$str=~s/[[:cntrl:]]/?/g;+return$cgi->span({-title=>$str},esc_html($chopped));+}+}++## ----------------------------------------------------------------------+## functions returning short strings++# CSS class for given age value (in seconds)+subage_class{+my$age=shift;++if(!defined$age){+return"noage";+}elsif($age<60*60*2){+return"age0";+}elsif($age<60*60*24*2){+return"age1";+}else{+return"age2";+}+}++# convert age in seconds to "nn units ago" string+subage_string{+my$age=shift;+my$age_str;++if($age>60*60*24*365*2){+$age_str=(int$age/60/60/24/365);+$age_str.=" years ago";+}elsif($age>60*60*24*(365/12)*2){+$age_str=int$age/60/60/24/(365/12);+$age_str.=" months ago";+}elsif($age>60*60*24*7*2){+$age_str=int$age/60/60/24/7;+$age_str.=" weeks ago";+}elsif($age>60*60*24*2){+$age_str=int$age/60/60/24;+$age_str.=" days ago";+}elsif($age>60*60*2){+$age_str=int$age/60/60;+$age_str.=" hours ago";+}elsif($age>60*2){+$age_str=int$age/60;+$age_str.=" min ago";+}elsif($age>2){+$age_str=int$age;+$age_str.=" sec ago";+}else{+$age_str.=" right now";+}+return$age_str;+}++useconstant{+S_IFINVALID=>0030000,+S_IFGITLINK=>0160000,+};++# submodule/subproject, a commit object reference+subS_ISGITLINK{+my$mode=shift;++return(($mode&S_IFMT)==S_IFGITLINK)+}++# convert file mode in octal to symbolic file mode string+submode_str{+my$mode=octshift;++if(S_ISGITLINK($mode)){+return'm---------';+}elsif(S_ISDIR($mode&S_IFMT)){+return'drwxr-xr-x';+}elsif(S_ISLNK($mode)){+return'lrwxrwxrwx';+}elsif(S_ISREG($mode)){+# git cares only about the executable bit+if($mode&S_IXUSR){+return'-rwxr-xr-x';+}else{+return'-rw-r--r--';+};+}else{+return'----------';+}+}++# convert file mode in octal to file type string+subfile_type{+my$mode=shift;++if($mode!~m/^[0-7]+$/){+return$mode;+}else{+$mode=oct$mode;+}++if(S_ISGITLINK($mode)){+return"submodule";+}elsif(S_ISDIR($mode&S_IFMT)){+return"directory";+}elsif(S_ISLNK($mode)){+return"symlink";+}elsif(S_ISREG($mode)){+return"file";+}else{+return"unknown";+}+}++# convert file mode in octal to file type description string+subfile_type_long{+my$mode=shift;++if($mode!~m/^[0-7]+$/){+return$mode;+}else{+$mode=oct$mode;+}++if(S_ISGITLINK($mode)){+return"submodule";+}elsif(S_ISDIR($mode&S_IFMT)){+return"directory";+}elsif(S_ISLNK($mode)){+return"symlink";+}elsif(S_ISREG($mode)){+if($mode&S_IXUSR){+return"executable";+}else{+return"file";+};+}else{+return"unknown";+}+}++1;
From: Jakub Narebski <hidden> Date: 2016-06-15 22:48:56
A few generic comments about this whole series.
First, when you are sending larger patch series (and I think this series
of 4 patches qualify), you should provide cover letter, [RFC/PATCH 0/4]
in this case, describing the series. git-format-patch has --cover-letter
option to make it easier to write such cover letters. I could then write
generic comments about whole series as comments to cover letter...
Second, all those commits about splitting gitweb should perhaps be
reorganized (rebased). Currently you have 'create Gitweb::Config',
'create Gitweb::Git', 'move subs to Gitweb::Config'; if Gitweb::Git
was created before Gitweb::Config, you would not need two commits
to create Gitweb::Config (to be exact even more than two, as not all
subroutines are moved, as you write yourself).
Third, and I think most important, is that the whole splitting gitweb into
modules series seems to alck direction, some underlying architecture
design. For example Gitweb::HTML, Gitweb::HTML::Link, Gitweb::HTML::String
seems to me too detailed, too fine-grained modules.
It was not visible at first, because Gitweb::Config, Gitweb::Request and to
a bit lesser extent Gitweb::Git fell out naturally. But should there be
for example Gitweb::Escape module, or should its functionality be a part of
Gitweb::Util? Those issues needs to be addressed. Perhaps they were
discussed with this GSoC project mentors (via IRC, private email, IM), but
we don't know what is the intended architecture design of gitweb.
Should we try for Model-Viewer-Controller pattern without backing MVC
(micro)framework? (One of design decisions for gitweb was have it working
out of the box if Perl and git are installed, without requiring to install
extra modules; but now we can install extra Perl modules e.g. from CPAN
under lib/...). How should we organize gitweb code into packages
(modules)?
Perhaps having gitweb.perl, Gitweb::Git, Gitweb::Config, Gitweb::Request,
Gitweb::Util and Gitweb would be enough? Should it be Gitweb::HTML or
Gitweb::View? Etc., etc.,...
That is a very important question.
On Mon, 7 June 2010, Pavan Kumar Sunkara wrote:
Subject: [RFC/PATCH 1/4] gitweb: Move subroutines to Gitweb::Config module
This summary doesn't tell us much. What subroutines, or what kind of
subroutines were moved to Gitweb::Config? Why they were moved, and why
they weren't there from beginning (perhaps it would be better to simply
reorder patches, to have creation of Gitweb::Git before creation of
Gitweb::Config)? Why can they be moved now?
Not all of those questions can be answered in summary (subject line for
email), but it should tell us what this commit is about.
I can find which subroutines were moved from the patch itself. What
I cannot find without good commit message is _why_ do you feel they
belong in Gitweb::Config (unless it is obvious), and why they can be
moved now and why they could not be moved earlier.
Subroutines yet to move: (Contains not yet packaged subs & vars)
feature_bool
feature_avatar
feature_snapshot
feature_patches
Why they can't be moved; what is missing? That is the question that commit
message should answer, or at least hint about / point the direction.
@@ -10,13 +10,16 @@ use strict;usewarnings;useExporterqw(import);-our@EXPORT=qw(evaluate_gitweb_config$version$projectroot$project_maxdepth$mimetypes_file+our@EXPORT=qw(evaluate_gitweb_configgitweb_check_featuregitweb_get_featureconfigure_gitweb_features+filter_snapshot_fmts$version$projectroot$project_maxdepth$mimetypes_file$git_avatar$projects_list@git_base_url_list$export_ok$strict_export$home_link_str$site_name$site_header$site_footer$home_text@stylesheets$stylesheet$logo$favicon$javascript$GITWEB_CONFIG$GITWEB_CONFIG_SYSTEM$logo_url$logo_label$export_auth_hook$projects_list_description_width$default_projects_order$default_blob_plain_mimetype$default_text_plain_charset$fallback_encoding@diff_opts$prevent_xss$maxload-%avatar_size%known_snapshot_formats%known_snapshot_format_aliases%feature);+%avatar_size%known_snapshot_formats%feature@snapshot_fmts);
I think it would be better to have exported subroutines separated from
exported variables at least in that exported variables should begin on new
line. This way it would be easier to see what was added, and (sometimes)
what was removed.
I had to look carefully to notice that you have removed the
%known_snapshot_format_aliases variable. This was not mentioned in the
commit message. There was no reason for removing it given in the commit
message (probably it was removed because it is internal to gitweb, and is
used only for backward compatibility with older configs... but it might be
not so internal, and might be useful and should be exported).
+
+use Gitweb::Git qw($git_dir);
O.K.
+sub gitweb_get_feature {
[...]
+ # project specific override is possible only if we have project
+ if (!$override || !defined $git_dir) {
+ return @defaults;
+ }
Note that '!defined $git_dir' is a bit of hack, to check whether we are in
git repository and if we can run per-repository config. This probably
could be solved better... but I don't mean that you would have to solve it.
It can be left for later.
--
Jakub Narebski
Poland
A few generic comments about this whole series.
[...]
Third, and I think most important, is that the whole splitting gitweb into
modules series seems to alck direction, some underlying architecture
design. For example Gitweb::HTML, Gitweb::HTML::Link, Gitweb::HTML::String
seems to me too detailed, too fine-grained modules.
It was not visible at first, because Gitweb::Config, Gitweb::Request and to
a bit lesser extent Gitweb::Git fell out naturally. But should there be
for example Gitweb::Escape module, or should its functionality be a part of
Gitweb::Util? Those issues needs to be addressed. Perhaps they were
discussed with this GSoC project mentors (via IRC, private email, IM), but
we don't know what is the intended architecture design of gitweb.
Should we try for Model-Viewer-Controller pattern without backing MVC
(micro)framework? (One of design decisions for gitweb was have it working
out of the box if Perl and git are installed, without requiring to install
extra modules; but now we can install extra Perl modules e.g. from CPAN
under lib/...). How should we organize gitweb code into packages
(modules)?
Perhaps having gitweb.perl, Gitweb::Git, Gitweb::Config, Gitweb::Request,
Gitweb::Util and Gitweb would be enough? Should it be Gitweb::HTML or
Gitweb::View? Etc., etc.,...
I haven't contributed to Gitweb, nor do I have to deal with it. But
I've followed this series and reviewed most of the Perl code in
Git. Take these with a grain of salt.
It would be very useful for the future of our Perl code if we had a
dual-life system in Git. I.e. a cpan/ directory where we could drop
CPAN modules that should be shipped with Git.
We already do this in a less sophisticated way for Error.pm, is there
any reason not to expand it to install more CPAN modules if they
aren't present on the system? That'd allow us to use them, but still
only depend on vanilla Perl.
Then we could just use e.g. Config::General (~3k lines of code)
instead of writing our own config system. There are probably lots of
wheels that we're inventing (and are going to invent) that have been
done better elsewhere, with more testing.
Unlike Python or Java, Perl's policy is for core modules is to only
include those required to better bootstrap the CPAN toolchain. So if
we continue sticking to core Perl our code is only going to drift
further away from Perl best practices.
From: Petr Baudis <hidden> Date: 2016-06-15 22:48:56
Hi!
On Tue, Jun 08, 2010 at 02:46:20PM +0200, Jakub Narebski wrote:
Third, and I think most important, is that the whole splitting gitweb into
modules series seems to alck direction, some underlying architecture
design. For example Gitweb::HTML, Gitweb::HTML::Link, Gitweb::HTML::String
seems to me too detailed, too fine-grained modules.
I agree!
It was not visible at first, because Gitweb::Config, Gitweb::Request and to
a bit lesser extent Gitweb::Git fell out naturally. But should there be
for example Gitweb::Escape module, or should its functionality be a part of
Gitweb::Util? Those issues needs to be addressed. Perhaps they were
discussed with this GSoC project mentors (via IRC, private email, IM), but
we don't know what is the intended architecture design of gitweb.
I would expect Gitweb::Escape functionality to live in Gitweb::HTML
(HTML escaping) and/or Gitweb::Request (URL escaping).
Should we try for Model-Viewer-Controller pattern without backing MVC
(micro)framework? (One of design decisions for gitweb was have it working
out of the box if Perl and git are installed, without requiring to install
extra modules; but now we can install extra Perl modules e.g. from CPAN
under lib/...). How should we organize gitweb code into packages
(modules)?
I thought we already discussed MVC and sort of agreed that it's an
overkill at this point. At least that is still my opinion on it; I'm not
opposed to MVC per se, but to me, this modularization is a good
intermediate step even if we go the MVC way later, and doing MVC properly
would mean much huger large-scale refactoring than just naming a module
Gitweb::View instead of Gitweb::HTML. Let's do it not at all, or
properly sometime later. I think it's well out-of-scope for GSoC.
Perhaps having gitweb.perl, Gitweb::Git, Gitweb::Config, Gitweb::Request,
Gitweb::Util and Gitweb would be enough?
I'm not sure what would fall into Gitweb::Util. I think Gitweb::HTML
makes a lot of sense to have, but I don't see the advantage of finer
graining than that - I dislike the Gitweb::HTML::* submodules as well.
Pavan, can you outline your next plan on the other modules you aim to
create, plus possibly a bit of rationale?
--
Petr "Pasky" Baudis
The true meaning of life is to plant a tree under whose shade
you will never sit.
On Tue, Jun 8, 2010 at 7:43 PM, Petr Baudis [off-list ref] wrote:
Hi!
On Tue, Jun 08, 2010 at 02:46:20PM +0200, Jakub Narebski wrote:
quoted
Third, and I think most important, is that the whole splitting gitweb into
modules series seems to alck direction, some underlying architecture
design. For example Gitweb::HTML, Gitweb::HTML::Link, Gitweb::HTML::String
seems to me too detailed, too fine-grained modules.
I agree!
quoted
It was not visible at first, because Gitweb::Config, Gitweb::Request and to
a bit lesser extent Gitweb::Git fell out naturally. But should there be
for example Gitweb::Escape module, or should its functionality be a part of
Gitweb::Util? Those issues needs to be addressed. Perhaps they were
discussed with this GSoC project mentors (via IRC, private email, IM), but
we don't know what is the intended architecture design of gitweb.
I would expect Gitweb::Escape functionality to live in Gitweb::HTML
(HTML escaping) and/or Gitweb::Request (URL escaping).
quoted
Should we try for Model-Viewer-Controller pattern without backing MVC
(micro)framework? (One of design decisions for gitweb was have it working
out of the box if Perl and git are installed, without requiring to install
extra modules; but now we can install extra Perl modules e.g. from CPAN
under lib/...). How should we organize gitweb code into packages
(modules)?
I thought we already discussed MVC and sort of agreed that it's an
overkill at this point. At least that is still my opinion on it; I'm not
opposed to MVC per se, but to me, this modularization is a good
intermediate step even if we go the MVC way later, and doing MVC properly
would mean much huger large-scale refactoring than just naming a module
Gitweb::View instead of Gitweb::HTML. Let's do it not at all, or
properly sometime later. I think it's well out-of-scope for GSoC.
quoted
Perhaps having gitweb.perl, Gitweb::Git, Gitweb::Config, Gitweb::Request,
Gitweb::Util and Gitweb would be enough?
I'm not sure what would fall into Gitweb::Util. I think Gitweb::HTML
makes a lot of sense to have, but I don't see the advantage of finer
graining than that - I dislike the Gitweb::HTML::* submodules as well.
Pavan, can you outline your next plan on the other modules you aim to
create, plus possibly a bit of rationale?
I am graining Gitweb::HTML into Gitweb::HTML::* to reduce circular
dependancies of the modules.
In the following days, I will be creating more modules
Gitweb::HTML::Navigation
Gitweb::HTML::Error
Gitweb::HTML::Page (Containing header and footer subs)
Gitweb::HTML::Format (format_* subs)
Gitweb::Parse
Gitweb::RepoConfig
Gitweb::Util
Gitweb::Action::* (All action subs like git_blame, git_log)
This is my architectural design for now. But It may change due to
later circular dependancies.
I will be rebasing the whole series, edit them and send them once
every module has undergone as RFC in the mailing list.
I have been stuck many times trying to workaround the circular module
dependancies and believe me, the patches I am sending and the modules
I am creating involves a lot of effort from my side and as long as you
think there's nothing wrong with the grouping of subroutines in my
modules and their names, you need not worry about the module
structure.
Thanks,
Pavan.
From: Petr Baudis <hidden> Date: 2016-06-15 22:48:56
On Wed, Jun 09, 2010 at 12:52:11AM +0530, Pavan Kumar Sunkara wrote:
I am graining Gitweb::HTML into Gitweb::HTML::* to reduce circular
dependancies of the modules.
I'm sorry, I don't understand. How is splitting up Gitweb::HTML to
submodules helping to reduce circular dependencies? I don't quite see
that right now. :-( Can you give a concrete example? Perhaps it would be
better to refactor the few problematic users instead of convoluting the
whole module structure because of the offenders.
Gitweb::Parse
What will this module do?
Gitweb::Util
What will this module do?
Gitweb::Action::* (All action subs like git_blame, git_log)
Do we need to do this right now? I think moving huge chunks of the code
around like this right now is unneccessary and it might just enlarge the
patch queue and delay you in your main GSoC efforts; perhaps we could do
this later when the dust settles a bit and we are sure that the rest of
the modular structure we have introduced fits well?
I will be rebasing the whole series, edit them and send them once
every module has undergone as RFC in the mailing list.
Ok! I have meant to ask about that.
I have been stuck many times trying to workaround the circular module
dependancies and believe me, the patches I am sending and the modules
I am creating involves a lot of effort from my side and as long as you
think there's nothing wrong with the grouping of subroutines in my
modules and their names, you need not worry about the module
structure.
I'm sorry but it doesn't work like that - if you have put a lot of
effort behind it, you need to present us with the rationale you have
reached and convince us that this is the right way to take.
--
Petr "Pasky" Baudis
The true meaning of life is to plant a tree under whose shade
you will never sit.
On Wed, Jun 9, 2010 at 1:25 AM, Petr Baudis [off-list ref] wrote:
On Wed, Jun 09, 2010 at 12:52:11AM +0530, Pavan Kumar Sunkara wrote:
quoted
I am graining Gitweb::HTML into Gitweb::HTML::* to reduce circular
dependancies of the modules.
I'm sorry, I don't understand. How is splitting up Gitweb::HTML to
submodules helping to reduce circular dependencies? I don't quite see
that right now. :-( Can you give a concrete example? Perhaps it would be
better to refactor the few problematic users instead of convoluting the
whole module structure because of the offenders.
Ok. I will be combining them into a single module.
quoted
Gitweb::Parse
What will this module do?
This module contains all the parse_* subroutines
Gitweb::Format contains all the format_* subroutines
quoted
Gitweb::Util
What will this module do?
This modules contains all the git utility functions.
quoted
Gitweb::Action::* (All action subs like git_blame, git_log)
Do we need to do this right now? I think moving huge chunks of the code
around like this right now is unneccessary and it might just enlarge the
patch queue and delay you in your main GSoC efforts; perhaps we could do
this later when the dust settles a bit and we are sure that the rest of
the modular structure we have introduced fits well?
I still have until this week in the timeline. Don't I ?
I strongly hope that I will be able to finalise the patch queue by
this week and will move on to develop write functionalities.
Thanks,
Pavan.
From: Petr Baudis <hidden> Date: 2016-06-15 22:48:56
On Wed, Jun 09, 2010 at 01:54:34AM +0530, Pavan Kumar Sunkara wrote:
On Wed, Jun 9, 2010 at 1:25 AM, Petr Baudis [off-list ref] wrote:
quoted
On Wed, Jun 09, 2010 at 12:52:11AM +0530, Pavan Kumar Sunkara wrote:
quoted
Gitweb::Parse
What will this module do?
This module contains all the parse_* subroutines
Ok, that makes sense. It might be also possible to have them in
Gitweb::Git, but I see href() invocations and such that would probably
create layering violations.
Gitweb::Format contains all the format_* subroutines
Here, I'm less decided. I would have put these in Gitweb::HTML, but I
have no hard opinion, maybe that's clumping things too much - so no nack
from me personally.
quoted
quoted
Gitweb::Util
What will this module do?
This modules contains all the git utility functions.
Can you give an example, please?
I still have until this week in the timeline. Don't I ?
I strongly hope that I will be able to finalise the patch queue by
this week and will move on to develop write functionalities.
Sure, my only concern is that if the queue of patches your future work
will depend on gets too long and gets delayed too much in merging in,
it will get much more difficult to produce further patches, get them
reviewed and get them on the merging track.
--
Petr "Pasky" Baudis
The true meaning of life is to plant a tree under whose shade
you will never sit.
From: Jakub Narebski <hidden> Date: 2016-06-15 22:48:56
On Tue, 8 Jun 2010, Petr Baudis wrote:
On Tue, Jun 08, 2010 at 02:46:20PM +0200, Jakub Narebski wrote:
quoted
Third, and I think most important, is that the whole splitting gitweb into
modules series seems to alck direction, some underlying architecture
design. For example Gitweb::HTML, Gitweb::HTML::Link, Gitweb::HTML::String
seems to me too detailed, too fine-grained modules.
I agree!
quoted
It was not visible at first, because Gitweb::Config, Gitweb::Request and to
a bit lesser extent Gitweb::Git fell out naturally. But should there be
for example Gitweb::Escape module, or should its functionality be a part of
Gitweb::Util? Those issues needs to be addressed. Perhaps they were
discussed with this GSoC project mentors (via IRC, private email, IM), but
we don't know what is the intended architecture design of gitweb.
I would expect Gitweb::Escape functionality to live in Gitweb::HTML
(HTML escaping) and/or Gitweb::Request (URL escaping).
I agree... well, partially, depending if we allow Gitweb::Request to be
only about request i.e. inbound links, or also with generating outbound
links. Thos two are tied together, e.g. with %cgi_param_mapping.
From what Pavan says, it seems that the problem with splitting gitweb is
interdependency of various commands, and overdepenency on global variables.
That was caused by the fact that gitweb was (well, is currently) big large
monolithic script, and there were no mechanism protecting against adding
(inter)dependencies.
Perhaps instead of fine-splitting gitweb into tiny modules to avoid
circular dependencies (module A needs module B because of variable a,
module B needs module A because of variable b) we should fix overdependence
on global variables by passing more as parameters - at least where it makes
sense.
quoted
Should we try for Model-Viewer-Controller pattern without backing MVC
(micro)framework? (One of design decisions for gitweb was have it working
out of the box if Perl and git are installed, without requiring to install
extra modules; but now we can install extra Perl modules e.g. from CPAN
under lib/...). How should we organize gitweb code into packages
(modules)?
I thought we already discussed MVC and sort of agreed that it's an
overkill at this point. At least that is still my opinion on it; I'm not
opposed to MVC per se, but to me, this modularization is a good
intermediate step even if we go the MVC way later, and doing MVC properly
would mean much huger large-scale refactoring than just naming a module
Gitweb::View instead of Gitweb::HTML. Let's do it not at all, or
properly sometime later. I think it's well out-of-scope for GSoC.
Well, let's not forget that the whole reason behind including splitting
gitweb into project that is about adding write capabilities to gitweb,
making a web interface equivalent to git-gui. Splitting gitweb was meant
to make it easier to add new functionality without having gitweb become too
large, and maintenance nightmare.
So it would be enough to have Gitweb with core of gitweb, gitweb.perl
top-level script, Gitweb::Write or something like that for new write
functionality and Gitweb::Util containing things that are needed by Gitweb
and by Gitweb::Write(r).
quoted
Perhaps having gitweb.perl, Gitweb::Git, Gitweb::Config, Gitweb::Request,
Gitweb::Util and Gitweb would be enough?
I'm not sure what would fall into Gitweb::Util. I think Gitweb::HTML
makes a lot of sense to have, but I don't see the advantage of finer
graining than that - I dislike the Gitweb::HTML::* submodules as well.
Gitweb does its work in the following way: first it parses path_info,
query parameters etc. and saves them in global variables. This is in
Gitweb::Request. But to parse-out project name from pathinfo it needs
$projectsroot from Gitweb::Config. Then it runs appropriate git commands
using subroutines from Gitweb::Cmd / Gitweb::Git, setting $git_dir first.
Then it parses output of git commands (probably Gitweb::Git too).
Finally it composes a response, usually HTML, but also feed (OPML, RSS,
Atom), plain text, and other output (blob_plain, snapshot); probably
Gitweb::Response, or Gitweb::Output, or Gitweb::View.
There are of course some problems.
To properly extract project from path_info in Gitweb::Request one needs
$projectroot from Gitweb::Config. Also generated gitweb links,
i.e. href() and esc_param() etc., are tied with parsing request URL, at
least via %cgi_param_mapping.
Gitweb::Config isn't that simple either. There is git configuration, e.g
$GIT, there is gitweb configuration, e.g. $projectroot, and there is
per-project configuration or configuration override.
Gitweb::Git / Gitweb::Cmd / Gitweb::Git::Cmd needs $GIT, but also
$git_dir, which is set using $projectroot and $project from
Gitweb::Request. Should it include parsing output of git commands, and
auxiliary commands dealing directly with files in git repository?
Then there is dispatch and generating response. It uses many utility
functions, like chop_str, or die_error. Then there aresubroutines
responsible for actions / views.
Fnally there is a question which parts of those the futture write support
would need...
--
Jakub Narebski
Poland
From: Jakub Narebski <hidden> Date: 2016-06-15 22:48:56
On Wed, Jun 9, 2010 at 1:38 AM, Jakub Narebski [off-list ref] wrote:
On Tue, 8 Jun 2010, Petr Baudis wrote:
quoted
I thought we already discussed MVC and sort of agreed that it's an
overkill at this point. At least that is still my opinion on it; I'm not
opposed to MVC per se, but to me, this modularization is a good
intermediate step even if we go the MVC way later, and doing MVC properly
would mean much huger large-scale refactoring than just naming a module
Gitweb::View instead of Gitweb::HTML. Let's do it not at all, or
properly sometime later. I think it's well out-of-scope for GSoC.
So it would be enough to have Gitweb with core of gitweb, gitweb.perl
top-level script, Gitweb::Write or something like that for new write
functionality and Gitweb::Util containing things that are needed by Gitweb
and by Gitweb::Write(r).
From: Jakub Narebski <hidden> Date: 2016-06-15 22:48:57
On Tue, 8 June 2010, Ævar Arnfjörð Bjarmason wrote:
I haven't contributed to Gitweb, nor do I have to deal with it. But
I've followed this series and reviewed most of the Perl code in
Git. Take these with a grain of salt.
It would be very useful for the future of our Perl code if we had a
dual-life system in Git. I.e. a cpan/ directory where we could drop
CPAN modules that should be shipped with Git.
The standard name for such directory is 'inc/', I think.
There is for example 'inc::latest' module (unfortunately in core only
since latest Perl, i.e. version 5.12), which uses modules bundled in
'inc/' if they are newer than installed ones. It is in Module-Build
distribution.
BTW. it's a pity that PAR (Perl Archiving Toolkit, par.perl.org)
is not in core...
We already do this in a less sophisticated way for Error.pm, is there
any reason not to expand it to install more CPAN modules if they
aren't present on the system? That'd allow us to use them, but still
only depend on vanilla Perl.
Sidenote about Error.pm: from what I understand modern consensus is
that Error.pm was a failed approach, and currently recommended way to
use exceptions in Perl is via block form of eval, e.g. Try::Tiny or
TryCatch (this requires Moose and PPI), and not Error.
The Error documentation nowadays includes the following instructions:
WARNING
Using the "Error" module is no longer recommended due to the
black-magical nature of its syntactic sugar, which often tends to
break. Its maintainers have stopped actively writing code that uses
it, and discourage people from doing so. See the "SEE ALSO" section
below for better recommendations.
[...]
SEE ALSO
See Exception::Class for a different module providing Object-Oriented
exception handling, along with a convenient syntax for declaring
hierarchies for them. It doesn't provide Error's syntactic sugar of
'try { ... }, catch { ... }', etc. which may be a good thing or a bad
thing based on what you want. (Because Error's syntactic sugar tends
to break.)
Error::Exception aims to combine Error and Exception::Class "with
correct stringification".
TryCatch and Try::Tiny are similar in concept to Error.pm only
providing a syntax that hopefully breaks less.
Then we could just use e.g. Config::General (~3k lines of code)
instead of writing our own config system. There are probably lots of
wheels that we're inventing (and are going to invent) that have been
done better elsewhere, with more testing.
The problem with _optional_ Config::General config is that people
would have incompatibile gitweb config files, some using Config::General
syntax, some current configuration in Perl.
Unlike Python or Java, Perl's policy is for core modules is to only
include those required to better bootstrap the CPAN toolchain. So if
we continue sticking to core Perl our code is only going to drift
further away from Perl best practices.
Right.
Still, we don't want to require having half of CPAN in 'inc/' to
install gitweb. Perhaps "no non-core dependencies" is too strict,
and should be replaced by "minimal non-core depencencies".
--
Jakub Narebski
Poland
On Sat, Jun 12, 2010 at 01:01, Jakub Narebski [off-list ref] wrote:
On Tue, 8 June 2010, Ævar Arnfjörð Bjarmason wrote:
quoted
I haven't contributed to Gitweb, nor do I have to deal with it. But
I've followed this series and reviewed most of the Perl code in
Git. Take these with a grain of salt.
It would be very useful for the future of our Perl code if we had a
dual-life system in Git. I.e. a cpan/ directory where we could drop
CPAN modules that should be shipped with Git.
The standard name for such directory is 'inc/', I think.
Perl itself uses cpan/, but Module::Install started the inc/. What we
call it really doesn't matter though.
There is for example 'inc::latest' module (unfortunately in core only
since latest Perl, i.e. version 5.12), which uses modules bundled in
'inc/' if they are newer than installed ones. It is in Module-Build
distribution.
Interesting. I hadn't looked at it.
BTW. it's a pity that PAR (Perl Archiving Toolkit, par.perl.org)
is not in core...
It has a bunch of off edge cases unlike its namesake .jar, but in any
case using it wouldn't help us.
quoted
We already do this in a less sophisticated way for Error.pm, is there
any reason not to expand it to install more CPAN modules if they
aren't present on the system? That'd allow us to use them, but still
only depend on vanilla Perl.
Sidenote about Error.pm: from what I understand modern consensus is
that Error.pm was a failed approach, and currently recommended way to
use exceptions in Perl is via block form of eval, e.g. Try::Tiny or
TryCatch (this requires Moose and PPI), and not Error.
Yeah, but it was just an example of how we can (and should) bundle
modules with Git.
quoted
Then we could just use e.g. Config::General (~3k lines of code)
instead of writing our own config system. There are probably lots of
wheels that we're inventing (and are going to invent) that have been
done better elsewhere, with more testing.
The problem with _optional_ Config::General config is that people
would have incompatibile gitweb config files, some using Config::General
syntax, some current configuration in Perl.
Isn't the current patch series the first attempt at config file
support? I.e. it's always been editing the source until now.
In any case, proper non-executable config file support could easily be
made optional, hopefully with a transition the non-executable one.
quoted
Unlike Python or Java, Perl's policy is for core modules is to only
include those required to better bootstrap the CPAN toolchain. So if
we continue sticking to core Perl our code is only going to drift
further away from Perl best practices.
Right.
Still, we don't want to require having half of CPAN in 'inc/' to
install gitweb. Perhaps "no non-core dependencies" is too strict,
and should be replaced by "minimal non-core depencencies".
From: Jakub Narebski <hidden> Date: 2016-06-15 22:48:57
On Sat, 12 Jun 2010, Ævar Arnfjörð Bjarmason wrote:
On Sat, Jun 12, 2010 at 01:01, Jakub Narebski [off-list ref] wrote:
quoted
On Tue, 8 June 2010, Ævar Arnfjörð Bjarmason wrote:
quoted
I haven't contributed to Gitweb, nor do I have to deal with it. But
I've followed this series and reviewed most of the Perl code in
Git. Take these with a grain of salt.
It would be very useful for the future of our Perl code if we had a
dual-life system in Git. I.e. a cpan/ directory where we could drop
CPAN modules that should be shipped with Git.
The standard name for such directory is 'inc/', I think.
Perl itself uses cpan/, but Module::Install started the inc/. What we
call it really doesn't matter though.
Right.
Although better example would be what modules on CPAN use, rather than
what Perl itself uses.
quoted
quoted
Then we could just use e.g. Config::General (~3k lines of code)
instead of writing our own config system. There are probably lots of
wheels that we're inventing (and are going to invent) that have been
done better elsewhere, with more testing.
The problem with _optional_ Config::General config is that people
would have incompatibile gitweb config files, some using Config::General
syntax, some current configuration in Perl.
Isn't the current patch series the first attempt at config file
support? I.e. it's always been editing the source until now.
Errr... no!
$ git blame -C -C -w -L/^our.*'GITWEB_CONFIG'/,+12 gitweb/gitweb.perl
shows that current config file in Perl (loaded using 'do $file') is
with gitweb since at least 2006-08-02.
In any case, proper non-executable config file support could easily be
made optional, hopefully with a transition the non-executable one.
I'm not sure if it would be easy to translate currently used gitweb
config files to non-executable file format. I think that %feature
hash make it so such config format would have to support nested
structures, which means e.g. JSON or YAML.
Besides how would you store / define $export_auth_hook in non-executable
file format?
# show repository only if this subroutine returns true
# when given the path to the project, for example:
# sub { return -e "$_[0]/git-daemon-export-ok"; }
our $export_auth_hook = undef;
--
Jakub Narebski
Poland