Re: [PATCH] gitweb: Support for snapshot

Subsystems: the rest

8 messages, 3 authors, 2016-06-15 · open the first message on its own page

Re: [PATCH] gitweb: Support for snapshot

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:37

What I had in mind is more like this.

 * The global hash %feature defines optional features that site
   administrator can enable (or allow repo-owners to enable).
   The hash is keyed with feature name.

 * The value of the hash is an array whose first two elements
   are a sub and a bool, and the rest of the elements are the
   default values of feature specific parameters.

 * The bool tells gitweb_check_feature if the feature is
   overridable per repository, and the sub is called with the
   rest of elements in the array only when it is overridable.
   The sub should read from the repository config and if the
   values are satisfactory return them; otherwise it should
   throw back the default parameters.

 * When you want to know if a feature with enabled (and with
   what option), you call gitweb_check_feature with the feature
   name.  It will return either the default parameters for the
   feature, or the parameters overridden by the repository.

In the example, I do not allow overriding the setting of
'blame', so calling gitweb_check_feature('blame') would always
return 0 (because the third element of the feature array is that
value).

If you want to allow repositories to override, you put true
value as the second member; then repositories that define their
own gitweb.blame can override the default.

The patch demonstrates the use of overridable configuration;
gitweb.snapshot can be left undefined (to get site-wide
default), or defined to be 'none' (to disable it for the
repository even when site-wide default allows it), or 'gzip', or
'bzip2'.

While I was at it, I got rid of git_get_project_config_bool()
which was poorly designed.  It did not understand various ways
you can spell true and false, and did not distinguish between
defining a variable to false and not having any definition for
the variable.

I did this patch as a demonstration of the overall framework, so
minor details of feature_xxx implementation might be wrong.
Obviously patch is not tested.

But personally, this patch makes things a bit easier to read
(but I am biased -- I wrote it).

---
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index f8d1036..af8867e 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -67,6 +67,51 @@ # file to use for guessing MIME types be
 # (relative to the current git repository)
 our $mimetypes_file = undef;
 
+################################################################
+# Feature configuration.
+# These subs are only called when per repository
+# overrides are allowed.  They take the default options,
+# inspect the repository and return the values from there if
+# the repository wants to override the system default.
+
+sub feature_blame {
+	my ($val) = git_get_project_config('blame', '--bool');
+	if ($val eq 'true') { return 1; }
+	elsif ($val eq 'false') { return 0; }
+
+	return $_[0];
+}
+
+sub feature_snapshot {
+	my ($ctype, $suffix, $command) = @_;
+	my ($val) = git_get_project_config('snapshot');
+	if ($val eq 'gzip') { return ('gzip', 'gz'); }
+	elsif ($val eq 'bzip2') { return ('bzip2', 'bz2'); }
+	elsif ($val eq 'none') { return (); }
+
+	return ($ctype, $suffix, $command);
+}
+
+# You define site-wide feature defaults here; override them with
+# $GITWEB_CONFIG as necessary.
+our %feature = 
+(
+	# feature	=> [feature-sub, allow-override, default options...]
+
+	'blame'		=> [\&feature_blame, 0, 0],
+ 	'snapshot'	=> [\&feature_snapshot, 0, 'x-gzip', 'gz', 'gzip'],
+);
+
+sub gitweb_check_feature {
+	my ($name) = @_;
+	return undef unless exists $feature{$name};
+	my ($sub, $override, @defaults) = @{$feature{$name}};
+	if (!$override) { return @defaults; }
+	return $sub->(@defaults);
+}
+
+################################################################
+
 our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++";
 require $GITWEB_CONFIG if -e $GITWEB_CONFIG;
 
@@ -485,24 +530,19 @@ sub git_get_type {
 }
 
 sub git_get_project_config {
-	my $key = shift;
+	my ($key, $type) = @_;
 
 	return unless ($key);
 	$key =~ s/^gitweb\.//;
 	return if ($key =~ m/\W/);
 
-	my $val = qx($GIT repo-config --get gitweb.$key);
+	my @x = ($GIT, 'repo-config', '--get');
+	if (defined $type) { push @x, $type; }
+	push @x, "gitweb.$key";
+	my $val = qx(@x);
 	return ($val);
 }
 
-sub git_get_project_config_bool {
-	my $val = git_get_project_config (@_);
-	if ($val and $val =~ m/true|yes|on/) {
-		return (1);
-	}
-	return; # implicit false
-}
-
 # get hash of given path at given ref
 sub git_get_hash_by_path {
 	my $base = shift;
@@ -1397,7 +1437,10 @@ sub git_difftree_body {
 sub git_shortlog_body {
 	# uses global variable $project
 	my ($revlist, $from, $to, $refs, $extra) = @_;
-	my $have_snapshot = git_get_project_config_bool('snapshot');
+
+	my ($ctype, $suffix, $command) = gitweb_check_feature('snapshot');
+	my $have_snapshot = (defined $ctype && defined $suffix);
+
 	$from = 0 unless defined $from;
 	$to = $#{$revlist} if (!defined $to || $#{$revlist} < $to);
 
@@ -1858,7 +1901,10 @@ sub git_tag {
 sub git_blame2 {
 	my $fd;
 	my $ftype;
-	die_error(undef, "Permission denied") if (!git_get_project_config_bool ('blame'));
+
+	if (!gitweb_check_feature('blame')) {
+		die_error(undef, "Permission denied");
+	}
 	die_error('404 Not Found', "File name not defined") if (!$file_name);
 	$hash_base ||= git_get_head_hash($project);
 	die_error(undef, "Couldn't find base commit") unless ($hash_base);
@@ -1916,7 +1962,10 @@ sub git_blame2 {
 
 sub git_blame {
 	my $fd;
-	die_error('403 Permission denied', "Permission denied") if (!git_get_project_config_bool ('blame'));
+
+	if (!gitweb_check_feature('blame')) {
+		die_error(undef, "Permission denied");
+	}
 	die_error('404 Not Found', "File name not defined") if (!$file_name);
 	$hash_base ||= git_get_head_hash($project);
 	die_error(undef, "Couldn't find base commit") unless ($hash_base);
@@ -2195,25 +2244,31 @@ sub git_tree {
 
 sub git_snapshot {
 
+	my ($ctype, $suffix, $command) = gitweb_check_feature('snapshot');
+	my $have_snapshot = (defined $ctype && defined $suffix);
+	if (!$have_snapshot) {
+		die_error(undef, "Permission denied");
+	}
+
 	if (!defined $hash) {
 		$hash = git_get_head_hash($project);
 	}
 
-	my $filename = basename($project) . "-$hash.tar.gz";
+	my $filename = basename($project) . "-$hash.tar.$suffix";
 
 	print $cgi->header(-type => 'application/x-tar',
-			-content-encoding => 'x-gzip',
-			'-content-disposition' => "inline; filename=\"$filename\"",
-			-status => '200 OK');
+			   -content-encoding => $ctype,
+			   '-content-disposition' =>
+			   "inline; filename=\"$filename\"",
+			   -status => '200 OK');
 
-	open my $fd, "-|", "$GIT tar-tree $hash \'$project\' | gzip" or
-				die_error(undef, "Execute git-tar-tree failed.");
+	open my $fd, "-|", "$GIT tar-tree $hash \'$project\' | $command" or
+		die_error(undef, "Execute git-tar-tree failed.");
 	binmode STDOUT, ':raw';
 	print <$fd>;
 	binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi
 	close $fd;
 
-
 }
 
 sub git_log {

Re: [PATCH] gitweb: Support for snapshot

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:42:37

Junio C Hamano wrote:
+sub feature_snapshot {
+       my ($ctype, $suffix, $command) = @_;
+       my ($val) = git_get_project_config('snapshot');
+       if ($val eq 'gzip') { return ('gzip', 'gz'); }
+       elsif ($val eq 'bzip2') { return ('bzip2', 'bz2'); }
+       elsif ($val eq 'none') { return (); }
+
+       return ($ctype, $suffix, $command);
+}
Should it be ('x-gzip', 'gzip', 'gz') and ('x-bzip2', 'bzip2', 'bz2'),
i.e. with $ctype first?

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

Re: [PATCH] gitweb: Support for snapshot

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:42:37

Junio C Hamano wrote:
 * The value of the hash is an array whose first two elements
   are a sub and a bool, and the rest of the elements are the
   default values of feature specific parameters.
Which means that it is not that easy to change defaults from 
$GITWEB_CONFIG ($feature{'blame'}->[1] = 1; ?).

And there is no way to enable for example 'blame' support for all
repositories...
-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

Re: [PATCH] gitweb: Support for snapshot

From: Aneesh Kumar K.V <hidden>
Date: 2016-06-15 22:42:37

Jakub Narebski wrote:
Junio C Hamano wrote:
quoted
 * The value of the hash is an array whose first two elements
   are a sub and a bool, and the rest of the elements are the
   default values of feature specific parameters.
Which means that it is not that easy to change defaults from 
$GITWEB_CONFIG ($feature{'blame'}->[1] = 1; ?).
how about 

   'blame'         => [\&feature_blame, $feature_blame_override, 0],

and picking only $feature_blame_override from $GITWEB_CONFIG

-aneesh 

Re: [PATCH] gitweb: Support for snapshot

From: Aneesh Kumar K.V <hidden>
Date: 2016-06-15 22:42:37

Junio C Hamano wrote:
I did this patch as a demonstration of the overall framework, so
minor details of feature_xxx implementation might be wrong.
Obviously patch is not tested.

But personally, this patch makes things a bit easier to read
(but I am biased -- I wrote it).
I tested this and added some comments. I also fixed some code. I am attaching the full diff.
BTW git-repo-config have the below bug. 

$ git repo-config --bool --get gitweb.blame
true
$ git repo-config --get --bool gitweb.blame
$

So i dropped --get from the git_get_project_config

-aneesh

Re: [PATCH] gitweb: Support for snapshot

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:42:37

Aneesh Kumar K.V wrote:
I tested this and added some comments. I also fixed some code. 
I am attaching the full diff. 
Below comments to the patch.
BTW git-repo-config have the below bug. 

$ git repo-config --bool --get gitweb.blame
true
$ git repo-config --get --bool gitweb.blame
$

So i dropped --get from the git_get_project_config
Wouldn't it be better to correct the error in git-repo-config? 
Or (easier) add '--get' last (see comments)?
+# Feature configuration.
Wouldn't it make it easier to understand code to put %feature hash 
and gitweb_check_feature subroutine _before_ subroutines for specific
features?
+# These subs are only called when per repository
+# overrides are allowed.  They take the default options,
+# inspect the repository and return the values from there if
+# the repository wants to override the system default.
+
+# To enable system wide have in $GITWEB_CONFIG
+# $feature{'blame'} =  [\&feature_blame, 0, 1];
This enables system wide, but also disables per-project override.
To enable system wide, while allowing for per project disabling
it should read
# $feature{'blame'} = [\&feature_blame, 1, 1]; # overridable, enabled by default
+# To disbale project wide 
Typo. disbale -> disable.
+# you should have allow-override enabled in  $GITWEB_CONFIG
Example:
# $feature{'blame'} = [\&feature_blame, 1, 1]; # overridable, enabled by default
or just

$feature{'blame'}->[1] = 1;

(See below for comments on that form)
+# and in project config   gitweb.blame = 0;
Example:
# $ git repo-config --bool gitweb.blame false
+# To disable system wide have in $GITWEB_CONFIG
+# $feature{'snapshot'} =  [\&feature_snapshot, 0, undef, undef, undef];
It would be enough to put:
$feature{'snapshot'} =  [\&feature_snapshot, 0, undef];
+# You define site-wide feature defaults here; override them with
+# $GITWEB_CONFIG as necessary.
+our %feature =
+(
+       # feature       => [feature-sub, allow-override, default options...]
+
+       'blame'         => [\&feature_blame, 0, 0],
+       'snapshot'      => [\&feature_snapshot, 0, 'x-gzip', 'gz', 'gzip'],
+);
By the way, wouldn't it be better to use _hash_ for mixed meaning
than _array_? I.e.

our %feature =
(
       # feature       => {'sub' => feature-sub, 'override' => allow-override, 'default' => default options...]

       'blame'         => {'sub' => \&feature_blame, 'override' => 0, 'default' => 0},
   #or 'blame'         => {'sub' => \&feature_blame, 'override' => 0, 'default' => [ 0 ]},
       'snapshot'      => {'sub' => \&feature_snapshot, 'override' => 0, 'default => [ 'x-gzip', 'gz', 'gzip' ]},
);

Then you could enable override, or change default simplier in
$GITWEB_CONFIG, e.g. $feature{'blame'}{'override'} = 1; instead
of $feature{'blame'}[1] = 1;

By the way, it has more sense to have feature by default 
(i.e. in gitweb.perl) with override enabled if it is set to on.
 sub git_get_project_config {
[...]
-       my $val = qx($GIT repo-config --get gitweb.$key);
+       my @x = ($GIT, 'repo-config');
+       if (defined $type) { push @x, $type; }
Just add '--get' as the last argument, _after_ type:
  +       push @x, '--get';
+       push @x, "gitweb.$key";
+       my $val = qx(@x);
+       chomp $val;
        return ($val);
 }
-       die_error('403 Permission denied', "Permission denied") if (!git_get_project_config_bool ('blame'));
+
+       if (!gitweb_check_feature('blame')) {
+               die_error(undef, "Permission denied");
+       }
Why did you drop '403 Permission denied' HTTP return code from call
to die_error? (And not set in other similar cases)?

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

Re: [PATCH] gitweb: Support for snapshot

From: Aneesh Kumar K.V <hidden>
Date: 2016-06-15 22:42:37

Jakub Narebski wrote:
Aneesh Kumar K.V wrote:
quoted
I tested this and added some comments. I also fixed some code. 
I am attaching the full diff. 
Below comments to the patch.
updated patch attached. I guess i have taken care of all your comments. 


-aneesh 

Re: [PATCH] gitweb: Support for snapshot

From: Aneesh Kumar K.V <hidden>
Date: 2016-06-15 22:42:37

Aneesh Kumar K.V wrote:
Jakub Narebski wrote:
quoted
Aneesh Kumar K.V wrote:
quoted
I tested this and added some comments. I also fixed some code. I am 
attaching the full diff. 
Below comments to the patch.
updated patch attached. I guess i have taken care of all your comments.
After fixing some comments and adding signed-off

Signed-off-by: Aneesh Kumar K.V <redacted>

-aneesh
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help