summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/VREF/MAX_NEWBIN_SIZE2
-rw-r--r--src/VREF/MERGE-CHECK4
-rwxr-xr-xsrc/commands/1plus12
-rwxr-xr-xsrc/commands/access10
-rwxr-xr-xsrc/commands/compile-template-data101
-rwxr-xr-xsrc/commands/config19
-rwxr-xr-xsrc/commands/info16
-rwxr-xr-xsrc/commands/mirror63
-rwxr-xr-xsrc/commands/newbranch41
-rwxr-xr-x[-rw-r--r--]src/commands/option0
-rwxr-xr-xsrc/commands/rsync18
-rwxr-xr-xsrc/gitolite5
-rwxr-xr-xsrc/gitolite-shell16
-rw-r--r--src/lib/Gitolite/Common.pm20
-rw-r--r--src/lib/Gitolite/Conf.pm10
-rw-r--r--src/lib/Gitolite/Conf/Load.pm19
-rw-r--r--src/lib/Gitolite/Conf/Store.pm18
-rw-r--r--src/lib/Gitolite/Conf/Sugar.pm2
-rw-r--r--src/lib/Gitolite/Hooks/Update.pm2
-rw-r--r--src/lib/Gitolite/Triggers/Alias.pm4
-rw-r--r--src/lib/Gitolite/Triggers/Mirroring.pm85
-rw-r--r--src/lib/Gitolite/Triggers/RepoUmask.pm4
-rw-r--r--src/lib/Gitolite/Triggers/TProxy.pm3
-rwxr-xr-xsrc/triggers/expand-deny-messages14
-rwxr-xr-xsrc/triggers/post-compile/ssh-authkeys-split43
-rwxr-xr-xsrc/triggers/post-compile/update-git-configs12
-rwxr-xr-xsrc/triggers/post-compile/update-git-daemon-access-list17
-rwxr-xr-xsrc/triggers/post-compile/update-gitweb-access-list29
-rwxr-xr-xsrc/triggers/post-compile/update-gitweb-daemon-from-options11
-rwxr-xr-xsrc/triggers/repo-specific-hooks18
-rwxr-xr-xsrc/triggers/upstream8
31 files changed, 426 insertions, 190 deletions
diff --git a/src/VREF/MAX_NEWBIN_SIZE b/src/VREF/MAX_NEWBIN_SIZE
index 84a9efa..99d51d3 100755
--- a/src/VREF/MAX_NEWBIN_SIZE
+++ b/src/VREF/MAX_NEWBIN_SIZE
@@ -21,6 +21,8 @@ die "not meant to be run manually" unless $ARGV[7];
my ( $newsha, $oldtree, $newtree, $refex, $max ) = @ARGV[ 2, 3, 4, 6, 7 ];
+exit 0 if $newsha eq '0000000000000000000000000000000000000000';
+
# / (.*) +\| Bin 0 -> (\d+) bytes/
chomp( my $author_email = `git log --format=%ae -1 $newsha` );
diff --git a/src/VREF/MERGE-CHECK b/src/VREF/MERGE-CHECK
index 07f0351..a70fe23 100644
--- a/src/VREF/MERGE-CHECK
+++ b/src/VREF/MERGE-CHECK
@@ -9,9 +9,9 @@ use warnings;
# usage in conf/gitolite.conf goes like this:
-# - VREF/MERGE_CHECK/master = @all
+# - VREF/MERGE-CHECK/master = @all
# # reject only if the merge commit is being pushed to the master branch
-# - VREF/MERGE_CHECK = @all
+# - VREF/MERGE-CHECK = @all
# # reject merge commits to any branch
my $ref = $ARGV[0];
diff --git a/src/commands/1plus1 b/src/commands/1plus1
index 897d235..1d94006 100755
--- a/src/commands/1plus1
+++ b/src/commands/1plus1
@@ -5,7 +5,7 @@ use warnings;
# import LOCK_*
use Fcntl qw(:flock);
-my $lockbase = shift; # suggested: $GL_REPO_BASE/$GL_REPO.git/.gl-mirror-push-lock.$SLAVE_NAME
+my $lockbase = shift; # suggested: $GL_REPO_BASE/$GL_REPO.git/.gl-mirror-push-lock.$COPY_NAME
my @cmd_plus_args = @ARGV; # the actual 'gitolite mirror ...' command
@ARGV = ();
diff --git a/src/commands/access b/src/commands/access
index f02e533..7d4a5b9 100755
--- a/src/commands/access
+++ b/src/commands/access
@@ -51,7 +51,7 @@ $ref ||= 'any';
# fq the ref if needed
$ref =~ s(^)(refs/heads/) if $ref and $ref ne 'any' and $ref !~ m(^(refs|VREF)/);
_die "invalid perm" if not( $aa and $aa =~ /^(R|W|\+|C|D|M|\^C)$/ );
-_die "invalid ref name" if not( $ref and $ref =~ $REPONAME_PATT );
+_die "invalid ref name" if not( $ref and $ref =~ $REF_OR_FILENAME_PATT );
my $ret = '';
@@ -61,6 +61,9 @@ if ( $repo ne '%' and $user ne '%' ) {
show($ret) if $s;
+ # adjust for fallthru in VREFs
+ $ret =~ s/DENIED by fallthru/allowed by fallthru/ if $ref =~ m(^VREF/);
+
if ( $ret =~ /DENIED/ ) {
print "$ret\n" unless $q;
exit 1;
@@ -85,8 +88,9 @@ while (<>) {
sub adjust_aa {
my ($repo, $aa) = @_;
- $aa = '+' if $aa eq 'C' and not option($repo, 'CREATE_IS_C');
+ $aa = 'W' if $aa eq 'C' and not option($repo, 'CREATE_IS_C');
$aa = '+' if $aa eq 'D' and not option($repo, 'DELETE_IS_D');
+ $aa = 'W' if $aa eq 'M' and not option($repo, 'MERGE_CHECK');
return $aa;
}
@@ -103,7 +107,7 @@ sub show {
p => skipped due to perm (W, +, etc) not matching,
D => explicitly denied,
A => explicitly allowed,
- F => denied due to fallthru (no rules matched)
+ F => fallthru; access denied for normal refs, allowed for VREFs
";
diff --git a/src/commands/compile-template-data b/src/commands/compile-template-data
new file mode 100755
index 0000000..e4ef86e
--- /dev/null
+++ b/src/commands/compile-template-data
@@ -0,0 +1,101 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+# read template data to produce gl-perms and gl-repo-groups files in each
+# $repo dir. Create the repo if needed, using the wild repos create logic
+# (with a "creator" of "gitolite-admin"!), though they're not really wild
+# repos.
+
+# see rule-templates.html in the gitolite documentation site.
+
+# pure text manipulation (and very little of that!), no git or gitolite
+# functions, no access checks, no possibility of a performance drama (or at
+# least not a *complex* performance drama)
+
+use lib $ENV{GL_LIBDIR};
+use Gitolite::Rc;
+use Gitolite::Common;
+use Gitolite::Conf::Load;
+use Gitolite::Conf::Store;
+
+my $rb = $rc{GL_REPO_BASE};
+
+@ARGV = `find $rc{GL_ADMIN_BASE}/conf -type f -name "*.conf" | sort`; chomp(@ARGV);
+# we don't see the files in the exact same order that gitolite compile sees
+# them, but we don't need to, for the data we are interested in (as long as
+# you don't break up one repo's data across multiple files!)
+
+# XXX We also potentially see more; a conf file may be in the directory, but
+# not pulled in via an 'include' or 'subconf', so it doesn't exist as far as
+# 'gitolite compile' is concerned, but here we *do* pull it in.
+
+my $repos = '';
+my $perms = '';
+my $list = ''; # list of templates to apply
+my $lip = ''; # line in progress
+while (<>) {
+ chomp;
+ next unless /^=begin template-data$/ .. /^=end$/ and not /^=(begin|end)/;
+
+ next unless /\S/;
+ next if /^\s*#/;
+
+ s/\t/ /g; # all the same to us
+
+ # handle continuation lines (backslash as last character)
+ if (/\\$/) {
+ s/\\$//;
+ $lip .= $_;
+ next;
+ }
+ $_ = $lip . $_;
+ $lip = '';
+
+ _warn("bad line: $_"), next if m([^ \w.\@/=-]); # silently ignore lines that have characters we don't need
+ if (/^\s*repo\s+(\S.*)=\s*(\S.*)$/) {
+ flush($repos, $list, $perms);
+ $repos = $1;
+ $perms = '';
+ $list = $2;
+
+ } elsif (/^\s*(\S+)\s*=\s*(\S.*)$/) {
+ $perms .= "$1 = $2\n";
+ } else {
+ # probably a blank line or a comment line. If not, well *shrug*
+ }
+}
+flush($repos, $list, $perms);
+
+sub flush {
+ my ($r, $l, $p) = @_;
+ return unless $r and $l and $p;
+ $l =~ s/\s+/ /g;
+
+ my @r = split ' ', $r;
+ while (@r) {
+ my $r1 = shift @r;
+ if ($r1 =~ m(^@)) {
+ my @g = @{ Gitolite::Conf::Load::list_members($r1) };
+ _warn "undefined group '$r1'" unless @g;
+ unshift @r, @g;
+ next;
+ }
+
+ flush_1($r1, $l, $p);
+ }
+}
+sub flush_1 {
+ my ($repo, $list, $perms) = @_;
+
+ # beware of wild characters!
+ return unless $repo =~ $REPONAME_PATT;
+
+ if (not -d "$rb/$repo.git") {
+ new_wild_repo( $repo, 'gitolite-admin', 'template-data' );
+ }
+
+ _print("$rb/$repo.git/gl-repo-groups", $list);
+
+ _print("$rb/$repo.git/gl-perms", $perms);
+}
diff --git a/src/commands/config b/src/commands/config
index 7851c11..214158b 100755
--- a/src/commands/config
+++ b/src/commands/config
@@ -63,8 +63,8 @@ usage() if not @ARGV or $ARGV[0] eq '-h';
my $repo = shift;
-my ($op, $key, $val) = @ARGV;
-usage() unless $op and exists $nargs{$op} and @ARGV == $nargs{$op};
+my $op = shift;
+usage() unless $op and exists $nargs{$op};
# ----------------------------------------------------------------------
# authorisation checks
@@ -81,15 +81,30 @@ die "sorry, you are not authorised\n" unless
# key validity checks
unless ($op eq '--list') {
+ my $key = shift;
+
+ my $val = '';
+ $val = join(" ", @ARGV) if @ARGV;
+ # values with spaces embedded get flattened by sshd when it passes
+ # SSH_ORIGINAL_COMMAND to gitolite. In this specific instance, we will
+ # pretend we know what the user meant, and join up the last 1+ args into
+ # one space-separated arg.
+
my $user_configs = option( $repo, 'user-configs' );
# this is a space separated list of allowed config keys
my @validkeys = split( ' ', ( $user_configs || '' ) );
my @matched = grep { $key =~ /^$_$/i } @validkeys;
_die "config '$key' not allowed\n" if ( @matched < 1 );
+
+ @ARGV = ($key);
+ push @ARGV, $val if $val;
}
# ----------------------------------------------------------------------
# go!
+unshift @ARGV, $op;
+usage() unless @ARGV == $nargs{$op};
+
_chdir("$rc{GL_REPO_BASE}/$repo.git");
_system( "git", "config", @ARGV );
diff --git a/src/commands/info b/src/commands/info
index 5079cfa..b88e288 100755
--- a/src/commands/info
+++ b/src/commands/info
@@ -12,12 +12,13 @@ use Gitolite::Conf::Load;
=for args
Usage: gitolite info [-lc] [-ld] [-json] [<repo name pattern>]
-List all existing repos you can access, as well as repo name patterns you can
-create repos from (if any).
+List all existing repos you can access, as well as repo name patterns (see
+"wild repos") you have any kind of access to.
'-lc' lists creators as an additional field at the end.
'-ld' lists description as an additional field at the end.
'-json' produce JSON output instead of normal output
+ '-p' limits output to physical repos only (no wild repo regexes!)
The optional pattern is an unanchored regex that will limit the repos
searched, in both cases. It might speed up things a little if you have more
@@ -25,7 +26,7 @@ than a few thousand repos.
=cut
# these are globals
-my ( $lc, $ld, $json, $patt ) = args();
+my ( $lc, $ld, $json, $p, $patt ) = args();
my %out; # holds info to be json'd
$ENV{GL_USER} or _die "GL_USER not set";
@@ -35,8 +36,8 @@ if ($json) {
print greeting();
}
-print_patterns(); # repos he can create for himself
-print_phy_repos(); # repos already created
+print_patterns() unless $p; # repos he can create for himself
+print_phy_repos(); # repos already created
if ( $rc{SITE_INFO} ) {
$json
@@ -49,13 +50,14 @@ print JSON::to_json( \%out, { utf8 => 1, pretty => 1 } ) if $json;
# ----------------------------------------------------------------------
sub args {
- my ( $lc, $ld, $json, $patt ) = ( '', '', '', '' );
+ my ( $lc, $ld, $json, $p, $patt ) = ( '', '', '', '' );
my $help = '';
GetOptions(
'lc' => \$lc,
'ld' => \$ld,
'json' => \$json,
+ 'p' => \$p,
'h' => \$help,
) or usage();
@@ -64,7 +66,7 @@ sub args {
require JSON if $json;
- return ( $lc, $ld, $json, $patt );
+ return ( $lc, $ld, $json, $p, $patt );
}
sub print_patterns {
diff --git a/src/commands/mirror b/src/commands/mirror
index 3a74a42..b22ec2a 100755
--- a/src/commands/mirror
+++ b/src/commands/mirror
@@ -15,32 +15,32 @@ use Gitolite::Common;
use Gitolite::Conf::Load;
=for usage
-Usage 1: gitolite mirror push <slave> <repo>
- gitolite mirror status <slave> <repo>
+Usage 1: gitolite mirror push <copy> <repo>
+ gitolite mirror status <copy> <repo>
gitolite mirror status all <repo>
gitolite mirror status all all
-Usage 2: ssh git@master-server mirror push <slave> <repo>
- ssh git@master-server mirror status <slave> <repo>
+Usage 2: ssh git@master-server mirror push <copy> <repo>
+ ssh git@master-server mirror status <copy> <repo>
-Forces a push of one repo to one slave.
+Forces a push of one repo to one copy.
-Usage 1 is directly on the master server. Nothing is checked; if the slave
-accepts it, the push happens, even if the slave is not in any slaves
+Usage 1 is directly on the master server. Nothing is checked; if the copy
+accepts it, the push happens, even if the copy is not in any copies
option. This is how you do delayed or lagged pushes to servers that do not
need real-time updates or have bandwidth/connectivity issues.
Usage 2 can be initiated by *any* user who has *any* gitolite access to the
-master server, but it checks that the slave is in one of the slaves options
+master server, but it checks that the copy is in one of the copies options
before doing the push.
MIRROR STATUS: The usage examples above show what can be done. The 'status
-all <repo>' usage checks the status of all the slaves defined for the given
+all <repo>' usage checks the status of all the copies defined for the given
repo. The 'status all all' usage is special, in that it only prints a list of
repos that have *some* error, instead of dumping all the error info itself.
SERVER LIST: 'gitolite mirror list master <reponame>' and 'gitolite mirror
-list slaves <reponame>' will show you the name of the master server, and list
-the slave servers, for the repo. They only work on the server command line
+list copies <reponame>' will show you the name of the master server, and list
+the copy servers, for the repo. They only work on the server command line
(any server), but not remotely (from a normal user).
=cut
@@ -49,12 +49,13 @@ usage() if not @ARGV or $ARGV[0] eq '-h';
_die "HOSTNAME not set" if not $rc{HOSTNAME};
my ( $cmd, $host, $repo ) = @ARGV;
+$host = 'copies' if $host eq 'slaves';
$repo =~ s/\.git$//;
usage() if not $repo;
if ( $cmd eq 'push' ) {
- valid_slave( $host, $repo ) if exists $ENV{GL_USER};
- # will die if host not in slaves for repo
+ valid_copy( $host, $repo ) if exists $ENV{GL_USER};
+ # will die if host not in copies for repo
trace( 1, "TID=$tid host=$host repo=$repo", "gitolite mirror push started" );
_chdir( $rc{GL_REPO_BASE} );
@@ -80,15 +81,15 @@ if ( $cmd eq 'push' ) {
trace( 1, "mirror: $_" );
}
}
- # save the mirror push status for this slave if the word 'fatal' is found,
+ # save the mirror push status for this copy if the word 'fatal' is found,
# else remove the status file. We don't store "success" output messages;
# you can always get those from the log files if you really need them.
if ( $glss =~ /fatal/i ) {
my $glss_prefix = Gitolite::Common::gen_ts() . "\t$ENV{GL_TID}\t";
$glss =~ s/^/$glss_prefix/gm;
- _print("gl-slave-$host.status", $glss);
+ _print("gl-copy-$host.status", $glss);
} else {
- unlink "gl-slave-$host.status";
+ unlink "gl-copy-$host.status";
}
exit $errors;
@@ -101,20 +102,20 @@ if ( $cmd eq 'push' ) {
_chdir( $rc{GL_REPO_BASE} );
my $phy_repos = list_phy_repos(1);
for my $repo ( @{$phy_repos} ) {
- my @x = glob("$rc{GL_REPO_BASE}/$repo.git/gl-slave-*.status");
+ my @x = glob("$rc{GL_REPO_BASE}/$repo.git/gl-copy-*.status");
print "$repo\n" if @x;
}
exit 0;
}
- valid_slave( $host, $repo ) if exists $ENV{GL_USER};
- # will die if host not in slaves for repo
+ valid_copy( $host, $repo ) if exists $ENV{GL_USER};
+ # will die if host not in copies for repo
_chdir( $rc{GL_REPO_BASE} );
_chdir("$repo.git");
$host = '*' if $host eq 'all';
- map { print_status($repo, $_) } sort glob("gl-slave-$host.status");
+ map { print_status($repo, $_) } sort glob("gl-copy-$host.status");
} else {
# strictly speaking, we could allow some of the possible commands remotely
# also, at least for admins. However, these commands are mainly intended
@@ -126,18 +127,18 @@ if ( $cmd eq 'push' ) {
# ----------------------------------------------------------------------
-sub valid_slave {
+sub valid_copy {
my ( $host, $repo ) = @_;
_die "invalid repo '$repo'" unless $repo =~ $REPONAME_PATT;
- my %list = repo_slaves($repo);
- _die "'$host' not a valid slave for '$repo'" unless $list{$host};
+ my %list = repo_copies($repo);
+ _die "'$host' not a valid copy for '$repo'" unless $list{$host};
}
-sub repo_slaves {
+sub repo_copies {
my $repo = shift;
- my $ref = git_config( $repo, "^gitolite-options\\.mirror\\.slaves.*" );
+ my $ref = git_config( $repo, "^gitolite-options\\.mirror\\.copies.*" );
my %list = map { $_ => 1 } map { split } values %$ref;
return %list;
@@ -157,9 +158,9 @@ sub print_status {
my $repo = shift;
my $file = shift;
return unless -f $file;
- my $slave = $1 if $file =~ /^gl-slave-(.+)\.status$/;
+ my $copy = $1 if $file =~ /^gl-copy-(.+)\.status$/;
print "----------\n";
- print "WARNING: previous mirror push of repo '$repo' to host '$slave' failed, status is:\n";
+ print "WARNING: previous mirror push of repo '$repo' to host '$copy' failed, status is:\n";
print slurp($file);
print "----------\n";
}
@@ -167,17 +168,17 @@ sub print_status {
# ----------------------------------------------------------------------
# server side commands. Very little error checking.
# gitolite mirror list master <repo>
-# gitolite mirror list slaves <repo>
+# gitolite mirror list copies <repo>
sub server_side_commands {
if ( $cmd eq 'list' ) {
if ( $host eq 'master' ) {
say repo_master($repo);
- } elsif ( $host eq 'slaves' ) {
- my %list = repo_slaves($repo);
+ } elsif ( $host eq 'copies' ) {
+ my %list = repo_copies($repo);
say join( " ", sort keys %list );
} else {
- _die "gitolite mirror list master|slaves <reponame>";
+ _die "gitolite mirror list master|copies <reponame>";
}
} else {
_die "invalid command";
diff --git a/src/commands/newbranch b/src/commands/newbranch
new file mode 100755
index 0000000..6dff545
--- /dev/null
+++ b/src/commands/newbranch
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use lib $ENV{GL_LIBDIR};
+use Gitolite::Easy;
+
+=for usage
+Usage: ssh git@host newbranch <repo name> <new branch name> <based-on ref name>
+
+Create a new branch and set it to existing branch or tag. You should have
+write access to that branch.
+
+NOTE: runs "git branch arg-2 arg-3" in repo given by arg-1, which means you
+should NOT prefix arguments with "refs/heads/" or "refs/tags/".
+
+----
+
+This is for people who have restrictions on what files they can "touch". When
+you fork a branch and change a file, even if you changed only the files you're
+allowed to, gitolite thinks you changed *all* the files in the repo because
+the "old SHA" is basically empty.
+
+This helps get around that by first creating the new branch, so that you can
+then push to it.
+
+To enable this command, add it to the rc file as a 'command'.
+
+TODO: handle deletes also (less commonly encountered and left as an "exercise
+for the reader" for now!)
+=cut
+
+usage() if not @ARGV or @ARGV < 3 or $ARGV[0] eq '-h';
+
+my $repo = shift;
+my $newbr = shift;
+my $oldref = shift;
+
+_die "you are not authorized" unless can_write($repo, "W", "refs/heads/$newbr");
+
+Gitolite::Common::_system("git", "branch", $newbr, $oldref);
diff --git a/src/commands/option b/src/commands/option
index de49aab..de49aab 100644..100755
--- a/src/commands/option
+++ b/src/commands/option
diff --git a/src/commands/rsync b/src/commands/rsync
index 1109ac4..c7b25d1 100755
--- a/src/commands/rsync
+++ b/src/commands/rsync
@@ -28,11 +28,6 @@ BUNDLE SUPPORT
(2) Add 'rsync' to the ENABLE list in the rc file
-
-GENERIC RSYNC SUPPORT
-
- TBD
-
=cut
=for usage
@@ -43,7 +38,7 @@ BUNDLE SUPPORT
Admins: see src/commands/rsync for setup instructions
Users:
- rsync -P git@host:repo.bundle .
+ rsync git@host:repo.bundle .
# downloads a file called "<basename of repo>.bundle"; repeat as
# needed till the whole thing is downloaded
git clone repo.bundle repo
@@ -51,9 +46,8 @@ BUNDLE SUPPORT
git remote set-url origin git@host:repo
git fetch origin # and maybe git pull, etc. to freshen the clone
-GENERIC RSYNC SUPPORT
-
- TBD
+ NOTE on options to the rsync command: you are only allowed to use the
+ "-v", "-n", "-q", and "-P" options.
=cut
@@ -62,9 +56,9 @@ usage() if not @ARGV or $ARGV[0] eq '-h';
# rsync driver program. Several things can be done later, but for now it
# drives just the 'bundle' transfer.
-if ( $ENV{SSH_ORIGINAL_COMMAND} =~ /^rsync --server --sender (-[-\w=.]+ )+\. (\S+)\.bundle$/ ) {
+if ( $ENV{SSH_ORIGINAL_COMMAND} =~ /^rsync --server --sender (?:-[vn]*(?:e\d*\.\w*)? )?\. (\S+)\.bundle$/ ) {
- my $repo = $2;
+ my $repo = $1;
$repo =~ s/\.git$//;
# all errors have the same message to avoid leaking info
@@ -81,7 +75,7 @@ if ( $ENV{SSH_ORIGINAL_COMMAND} =~ /^rsync --server --sender (-[-\w=.]+ )+\. (\S
exit 0;
}
-_warn "invalid rsync command '$ENV{SSH_ORIGINAL_COMMAND}'";
+_warn "Sorry, you are only allowed to use the '-v', '-n', '-q', and '-P' options.";
usage();
# ----------------------------------------------------------------------
diff --git a/src/gitolite b/src/gitolite
index 4a4cbf5..c11e047 100755
--- a/src/gitolite
+++ b/src/gitolite
@@ -71,6 +71,11 @@ if ( $command eq 'setup' ) {
compile(@args);
} elsif ( $command eq 'trigger' ) {
+ my $s = $args[0];
+ _die "trigger section '$s' not found in rc"
+ unless $s eq 'POST_COMPILE'
+ or $s eq 'POST_CREATE'
+ or ( exists $rc{$s} and ref( $rc{$s} ) eq 'ARRAY' );
trigger(@args);
} elsif ( my $c = _which( "commands/$command", 'x' ) ) {
diff --git a/src/gitolite-shell b/src/gitolite-shell
index d9ec01f..072e0ff 100755
--- a/src/gitolite-shell
+++ b/src/gitolite-shell
@@ -153,11 +153,19 @@ sub parse_soc {
$soc ||= 'info';
my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
- if ( $soc =~ m(^($git_commands) '?/?(.*?)(?:\.git(\d)?)?'?$) ) {
- my ( $verb, $repo, $trace_level ) = ( $1, $2, $3 );
- $ENV{D} = $trace_level if $trace_level;
- _die "invalid repo name: '$repo'" if $repo !~ $REPONAME_PATT;
+ # simplify the regex; we'll handle all the reponame nuances later
+ if ( $soc =~ m(^($git_commands) '?/?(.*?)'?$) ) {
+ my ( $verb, $repo ) = ( $1, $2 );
trace( 2, "git command", $soc );
+
+ # clean up the repo name; first extract the trace level if supplied
+ # (and no, you can't have a trace level *and* a trailing slash).
+ $ENV{D} = $1 if $repo =~ s/\.git(\d)$//;
+ # and then the git-daemon-compatibility trailers
+ $repo =~ s(/$)();
+ $repo =~ s(\.git$)();
+
+ _die "invalid repo name: '$repo'" if $repo !~ $REPONAME_PATT;
return ( $verb, $repo );
}
diff --git a/src/lib/Gitolite/Common.pm b/src/lib/Gitolite/Common.pm
index 7a52f4b..b06f967 100644
--- a/src/lib/Gitolite/Common.pm
+++ b/src/lib/Gitolite/Common.pm
@@ -19,6 +19,8 @@ package Gitolite::Common;
ssh_fingerprint_file
ssh_fingerprint_line
+
+ update_hook_present
);
#>>>
use Exporter 'import';
@@ -235,14 +237,26 @@ sub cleanup_conf_line {
chomp($repo);
$repo =~ s/\.git$//;
$repo =~ s(^\./)();
- push @phy_repos, $repo unless $repo =~ m(/$);
- # tolerate bare repos within ~/repositories but silently ignore them
+ next if $repo =~ m(/$);
+ # tolerate non-bare repos within ~/repositories but silently ignore them
+ push @phy_repos, $repo;
}
trace( 3, scalar(@phy_repos) . " physical repos found" );
return sort_u( \@phy_repos );
}
}
+sub update_hook_present {
+ my $repo = shift;
+
+ return 1 unless -d "$ENV{GL_REPO_BASE}/$repo.git"; # non-existent repo is fine
+
+ my $x = readlink("$ENV{GL_REPO_BASE}/$repo.git/hooks/update");
+ return 1 if $x and $x eq "$ENV{GL_ADMIN_BASE}/hooks/common/update";
+
+ return 0;
+}
+
# generate a timestamp
sub gen_ts {
my ( $s, $min, $h, $d, $m, $y ) = (localtime)[ 0 .. 5 ];
@@ -347,7 +361,7 @@ sub ssh_fingerprint_file {
my $in = shift;
-f $in or die "file not found: $in\n";
my $fh;
- open( $fh, "ssh-keygen -l -f $in |" ) or die "could not fork: $!\n";
+ open( $fh, "ssh-keygen -l -f $in 2>&1 |" ) or die "could not fork: $!\n";
my $output = <$fh>;
chomp $output;
# dbg("fp = $fp");
diff --git a/src/lib/Gitolite/Conf.pm b/src/lib/Gitolite/Conf.pm
index ce7adca..97b6c32 100644
--- a/src/lib/Gitolite/Conf.pm
+++ b/src/lib/Gitolite/Conf.pm
@@ -47,9 +47,19 @@ sub compile {
cache_control('start');
}
+ # remove entries from POST_CREATE which also exist in POST_COMPILE. This
+ # not only saves us having to implement an optimisation in *those*
+ # scripts, but more importantly, moves the optimisation one step up -- we
+ # don't even *call* those scripts now.
+ my %pco = map { $_ => 1 } @{ $rc{POST_COMPILE} };
+ @{ $rc{POST_CREATE} } = grep { ! exists $pco{$_} } @{ $rc{POST_CREATE} };
+
for my $repo ( @{ $rc{NEW_REPOS_CREATED} } ) {
trigger( 'POST_CREATE', $repo );
}
+
+ # process rule template data
+ _system("gitolite compile-template-data");
}
sub parse {
diff --git a/src/lib/Gitolite/Conf/Load.pm b/src/lib/Gitolite/Conf/Load.pm
index 4f42cdc..7dea259 100644
--- a/src/lib/Gitolite/Conf/Load.pm
+++ b/src/lib/Gitolite/Conf/Load.pm
@@ -73,6 +73,7 @@ sub access {
trace( 2, $repo, $user, $aa, $ref );
_die "invalid user '$user'" if not( $user and $user =~ $USERNAME_PATT );
sanity($repo);
+ return "$aa any $repo $user DENIED by fallthru" unless update_hook_present($repo);
my @rules;
my $deny_rules;
@@ -305,7 +306,7 @@ sub load_1 {
}
if ( -f "gl-conf" ) {
- return if not $split_conf{$repo};
+ return if not $split_conf{$repo} and not $rc{ALLOW_ORPHAN_GL_CONF};
my $cc = "./gl-conf";
_die "parse '$cc' failed: " . ( $@ or $! ) unless do $cc;
@@ -384,13 +385,23 @@ sub memberships {
push @ret, $i;
}
}
+
+ # add in any group names explicitly given in (GIT_DIR)/gl-repo-groups
+ push @ret,
+ map { s/^\@?/\@/; $_ }
+ grep { ! /[^\w@-]/ }
+ split (' ', slurp("$ENV{GL_REPO_BASE}/$base.git/gl-repo-groups"))
+ if -f "$ENV{GL_REPO_BASE}/$base.git/gl-repo-groups";
}
push @ret, @{ $groups{$base} } if exists $groups{$base};
push @ret, @{ $groups{$base2} } if $base2 and exists $groups{$base2};
- for my $i ( keys %{ $patterns{groups} } ) {
- if ( $base =~ /^$i$/ or $base2 and ( $base2 =~ /^$i$/ ) ) {
- push @ret, @{ $groups{$i} };
+ if ($type eq 'repo') {
+ # regexes can only be used for repos, not for users
+ for my $i ( keys %{ $patterns{groups} } ) {
+ if ( $base =~ /^$i$/ or $base2 and ( $base2 =~ /^$i$/ ) ) {
+ push @ret, @{ $groups{$i} };
+ }
}
}
diff --git a/src/lib/Gitolite/Conf/Store.pm b/src/lib/Gitolite/Conf/Store.pm
index c7f9ab5..8757c89 100644
--- a/src/lib/Gitolite/Conf/Store.pm
+++ b/src/lib/Gitolite/Conf/Store.pm
@@ -188,10 +188,13 @@ sub new_repos {
next unless $repo =~ $REPONAME_PATT; # skip repo patterns
next if $repo =~ m(^\@|EXTCMD/); # skip groups and fake repos
- # use gl-conf as a sentinel
- hook_1($repo) if -d "$repo.git" and not -f "$repo.git/gl-conf";
+ # use gl-conf as a sentinel; if it exists, all is well
+ next if -f "$repo.git/gl-conf";
- if ( not -d "$repo.git" ) {
+ if (-d "$repo.git") {
+ # directory exists but sentinel missing? Maybe a freshly imported repo?
+ hook_1($repo);
+ } else {
push @{ $rc{NEW_REPOS_CREATED} }, $repo;
trigger( 'PRE_CREATE', $repo );
new_repo($repo);
@@ -239,9 +242,12 @@ sub store {
# first write out the ones for the physical repos
_chdir( $rc{GL_REPO_BASE} );
- my $phy_repos = list_phy_repos(1);
- for my $repo ( @{$phy_repos} ) {
+ # list of repos (union of keys of %repos plus %configs)
+ my %kr_kc;
+ @kr_kc{ keys %repos } = ();
+ @kr_kc{ keys %configs } = ();
+ for my $repo ( keys %kr_kc ) {
store_1($repo);
}
@@ -284,7 +290,7 @@ sub store_1 {
# warning: writes and *deletes* it from %repos and %configs
my ($repo) = shift;
trace( 3, $repo );
- return unless ( $repos{$repo} or $configs{$repo} ) and -d "$repo.git";
+ return unless -d "$repo.git";
my ( %one_repo, %one_config );
diff --git a/src/lib/Gitolite/Conf/Sugar.pm b/src/lib/Gitolite/Conf/Sugar.pm
index 68ad728..5c743d3 100644
--- a/src/lib/Gitolite/Conf/Sugar.pm
+++ b/src/lib/Gitolite/Conf/Sugar.pm
@@ -105,6 +105,7 @@ sub option {
# -> config gitolite-options.foo = bar
for my $line (@$lines) {
+ $line =~ s/option mirror\.slaves/option mirror.copies/;
if ( $line =~ /^option (\S+) = (\S.*)/ ) {
push @ret, "config gitolite-options.$1 = $2";
} else {
@@ -187,6 +188,7 @@ sub skip_block {
for (@$lines) {
my $skip = 0;
$skip = 1 if /^= *begin testconf$/;
+ $skip = 1 if /^= *begin template-data$/;
# add code for other types of blocks here as needed
next if $skip .. /^= *end$/;
diff --git a/src/lib/Gitolite/Hooks/Update.pm b/src/lib/Gitolite/Hooks/Update.pm
index 32cd6e0..2bc43a8 100644
--- a/src/lib/Gitolite/Hooks/Update.pm
+++ b/src/lib/Gitolite/Hooks/Update.pm
@@ -17,6 +17,8 @@ use Gitolite::Conf::Load;
use strict;
use warnings;
+$|++;
+
# ----------------------------------------------------------------------
sub update {
diff --git a/src/lib/Gitolite/Triggers/Alias.pm b/src/lib/Gitolite/Triggers/Alias.pm
index 1fa24bb..adaceb5 100644
--- a/src/lib/Gitolite/Triggers/Alias.pm
+++ b/src/lib/Gitolite/Triggers/Alias.pm
@@ -73,11 +73,11 @@ Notes:
test it and make it work please let me know.
* funnily enough, this even works with mirroring! That is, a master can
- push a repo "foo" to a slave per its configuration, while the slave thinks
+ push a repo "foo" to a copy per its configuration, while the copy thinks
it is getting repo "bar" from the master per its configuration.
Just make sure to put the Alias::input line *before* the Mirroring::input
- line in the rc file on the slave.
+ line in the rc file on the copy.
However, it will probably not work with redirected pushes unless you setup
the opposite alias ("bar" -> "foo") on master.
diff --git a/src/lib/Gitolite/Triggers/Mirroring.pm b/src/lib/Gitolite/Triggers/Mirroring.pm
index 860e6d0..07b7f96 100644
--- a/src/lib/Gitolite/Triggers/Mirroring.pm
+++ b/src/lib/Gitolite/Triggers/Mirroring.pm
@@ -7,10 +7,9 @@ use Gitolite::Conf::Load;
use strict;
use warnings;
-my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
my $hn = $rc{HOSTNAME};
-my ( $mode, $master, %slaves, %trusted_slaves );
+my ( $mode, $master, %copies, %trusted_copies );
# ----------------------------------------------------------------------
@@ -52,7 +51,7 @@ sub input {
$rc{REDIRECTED_PUSH} = 1;
trace( 3, "redirected_push for user $1" );
} else {
- # master -> slave push, no access checks needed
+ # master -> copy push, no access checks needed
$ENV{GL_BYPASS_ACCESS_CHECKS} = 1;
}
}
@@ -73,32 +72,32 @@ sub pre_git {
# now you know the repo, get its mirroring details
details($repo);
- # print mirror status if at least one slave status file is present
- print_status( $repo ) if not $rc{HUSH_MIRROR_STATUS} and $mode ne 'local' and glob("$rc{GL_REPO_BASE}/$repo.git/gl-slave-*.status");
+ # print mirror status if at least one copy status file is present
+ print_status( $repo ) if not $rc{HUSH_MIRROR_STATUS} and $mode ne 'local' and glob("$rc{GL_REPO_BASE}/$repo.git/gl-copy-*.status");
# we don't deal with any reads. Note that for pre-git this check must
# happen *after* getting details, to give mode() a chance to die on "known
# unknown" repos (repos that are in the config, but mirror settings
- # exclude this host from both the master and slave lists)
+ # exclude this host from both the master and copy lists)
return if $aa eq 'R';
trace( 1, "mirror", "pre_git", $repo, "user=$user", "sender=$sender", "mode=$mode", ( $rc{REDIRECTED_PUSH} ? ("redirected") : () ) );
# ------------------------------------------------------------------
- # case 1: we're master or slave, normal user pushing to us
+ # case 1: we're master or copy, normal user pushing to us
if ( $user and not $rc{REDIRECTED_PUSH} ) {
trace( 3, "case 1, user push" );
return if $mode eq 'local' or $mode eq 'master';
- if ( $trusted_slaves{$hn} ) {
+ if ( $trusted_copies{$hn} ) {
trace( 1, "redirect to $master" );
exec( "ssh", $master, "USER=$user", "SOC=$ENV{SSH_ORIGINAL_COMMAND}" );
} else {
- _die "$hn: pushing '$repo' to slave '$hn' not allowed";
+ _die "$hn: pushing '$repo' to copy '$hn' not allowed";
}
}
# ------------------------------------------------------------------
- # case 2: we're slave, master pushing to us
+ # case 2: we're copy, master pushing to us
if ( $sender and not $rc{REDIRECTED_PUSH} ) {
trace( 3, "case 2, master push" );
_die "$hn: '$repo' is local" if $mode eq 'local';
@@ -108,13 +107,13 @@ sub pre_git {
}
# ------------------------------------------------------------------
- # case 3: we're master, slave sending a redirected push to us
+ # case 3: we're master, copy sending a redirected push to us
if ( $sender and $rc{REDIRECTED_PUSH} ) {
- trace( 3, "case 2, slave redirect" );
+ trace( 3, "case 2, copy redirect" );
_die "$hn: '$repo' is local" if $mode eq 'local';
- _die "$hn: '$repo' is not native" if $mode eq 'slave';
- _die "$hn: '$sender' is not a valid slave for '$repo'" if not $slaves{$sender};
- _die "$hn: redirection not allowed from '$sender'" if not $trusted_slaves{$sender};
+ _die "$hn: '$repo' is not native" if $mode eq 'copy';
+ _die "$hn: '$sender' is not a valid copy for '$repo'" if not $copies{$sender};
+ _die "$hn: redirection not allowed from '$sender'" if not $trusted_copies{$sender};
return;
}
@@ -143,20 +142,20 @@ sub post_git {
trace( 1, "mirror", "post_git", $repo, "user=$user", "sender=$sender", "mode=$mode", ( $rc{REDIRECTED_PUSH} ? ("redirected") : () ) );
# ------------------------------------------------------------------
- # case 1: we're master or slave, normal user pushing to us
+ # case 1: we're master or copy, normal user pushing to us
if ( $user and not $rc{REDIRECTED_PUSH} ) {
trace( 3, "case 1, user push" );
return if $mode eq 'local';
- # slave was eliminated earlier anyway, so that leaves 'master'
+ # copy was eliminated earlier anyway, so that leaves 'master'
- # find all slaves and push to each of them
- push_to_slaves($repo);
+ # find all copies and push to each of them
+ push_to_copies($repo);
return;
}
# ------------------------------------------------------------------
- # case 2: we're slave, master pushing to us
+ # case 2: we're copy, master pushing to us
if ( $sender and not $rc{REDIRECTED_PUSH} ) {
trace( 3, "case 2, master push" );
# nothing to do
@@ -164,12 +163,12 @@ sub post_git {
}
# ------------------------------------------------------------------
- # case 3: we're master, slave sending a redirected push to us
+ # case 3: we're master, copy sending a redirected push to us
if ( $sender and $rc{REDIRECTED_PUSH} ) {
- trace( 3, "case 2, slave redirect" );
+ trace( 3, "case 2, copy redirect" );
- # find all slaves and push to each of them
- push_to_slaves($repo);
+ # find all copies and push to each of them
+ push_to_copies($repo);
return;
}
@@ -183,39 +182,39 @@ sub post_git {
return if $lastrepo eq $repo;
$master = master($repo);
- %slaves = slaves($repo);
+ %copies = copies($repo);
$mode = mode($repo);
- %trusted_slaves = trusted_slaves($repo);
- trace( 3, $master, $mode, join( ",", sort keys %slaves ), join( ",", sort keys %trusted_slaves ) );
+ %trusted_copies = trusted_copies($repo);
+ trace( 3, $master, $mode, join( ",", sort keys %copies ), join( ",", sort keys %trusted_copies ) );
}
sub master {
return option( +shift, 'mirror.master' );
}
- sub slaves {
+ sub copies {
my $repo = shift;
- my $ref = git_config( $repo, "^gitolite-options\\.mirror\\.slaves.*" );
+ my $ref = git_config( $repo, "^gitolite-options\\.mirror\\.copies.*" );
my %out = map { $_ => 'async' } map { split } values %$ref;
- $ref = git_config( $repo, "^gitolite-options\\.mirror\\.slaves\\.sync.*" );
+ $ref = git_config( $repo, "^gitolite-options\\.mirror\\.copies\\.sync.*" );
map { $out{$_} = 'sync' } map { split } values %$ref;
- $ref = git_config( $repo, "^gitolite-options\\.mirror\\.slaves\\.nosync.*" );
+ $ref = git_config( $repo, "^gitolite-options\\.mirror\\.copies\\.nosync.*" );
map { $out{$_} = 'nosync' } map { split } values %$ref;
return %out;
}
- sub trusted_slaves {
+ sub trusted_copies {
my $ref = git_config( +shift, "^gitolite-options\\.mirror\\.redirectOK.*" );
- # the list of trusted slaves (where we accept redirected pushes from)
+ # the list of trusted copies (where we accept redirected pushes from)
# is either explicitly given...
my @out = map { split } values %$ref;
my %out = map { $_ => 1 } @out;
- # ...or it's all the slaves mentioned if the list is just a "all"
- %out = %slaves if ( @out == 1 and $out[0] eq 'all' );
+ # ...or it's all the copies mentioned if the list is just a "all"
+ %out = %copies if ( @out == 1 and $out[0] eq 'all' );
return %out;
}
@@ -223,24 +222,24 @@ sub post_git {
my $repo = shift;
return 'local' if not $hn;
return 'master' if $master eq $hn;
- return 'slave' if $slaves{$hn};
- return 'local' if not $master and not %slaves;
+ return 'copy' if $copies{$hn};
+ return 'local' if not $master and not %copies;
_die "$hn: '$repo' is mirrored but not here";
}
}
-sub push_to_slaves {
+sub push_to_copies {
my $repo = shift;
my $u = $ENV{GL_USER};
delete $ENV{GL_USER}; # why? see src/commands/mirror
my $lb = "$ENV{GL_REPO_BASE}/$repo.git/.gl-mirror-lock";
- for my $s ( sort keys %slaves ) {
- trace( 1, "push_to_slaves: skipping self" ), next if $s eq $hn;
- system("gitolite 1plus1 $lb.$s gitolite mirror push $s $repo </dev/null >/dev/null 2>&1 &") if $slaves{$s} eq 'async';
- system("gitolite 1plus1 $lb.$s gitolite mirror push $s $repo </dev/null >/dev/null 2>&1") if $slaves{$s} eq 'sync';
- _warn "manual mirror push pending for '$s'" if $slaves{$s} eq 'nosync';
+ for my $s ( sort keys %copies ) {
+ trace( 1, "push_to_copies skipping self" ), next if $s eq $hn;
+ system("gitolite 1plus1 $lb.$s gitolite mirror push $s $repo </dev/null >/dev/null 2>&1 &") if $copies{$s} eq 'async';
+ system("gitolite 1plus1 $lb.$s gitolite mirror push $s $repo </dev/null >/dev/null 2>&1") if $copies{$s} eq 'sync';
+ _warn "manual mirror push pending for '$s'" if $copies{$s} eq 'nosync';
}
$ENV{GL_USER} = $u;
diff --git a/src/lib/Gitolite/Triggers/RepoUmask.pm b/src/lib/Gitolite/Triggers/RepoUmask.pm
index 109cb31..276cd01 100644
--- a/src/lib/Gitolite/Triggers/RepoUmask.pm
+++ b/src/lib/Gitolite/Triggers/RepoUmask.pm
@@ -23,6 +23,10 @@ use warnings;
option umask = 0027
+ * Anytime you add or change the value, if there are existing repos that
+ would be affected, you will need to do a manual "chmod" adjustment,
+ because umask only affects newly created files.
+
=cut
# sadly option/config values are not available at pre_create time for normal
diff --git a/src/lib/Gitolite/Triggers/TProxy.pm b/src/lib/Gitolite/Triggers/TProxy.pm
index b2ab8df..9c42918 100644
--- a/src/lib/Gitolite/Triggers/TProxy.pm
+++ b/src/lib/Gitolite/Triggers/TProxy.pm
@@ -49,7 +49,7 @@ package Gitolite::Triggers::TProxy;
# corresponding pub keys would already be set ok so step 2 in the
# upstream server setup (above) will not be needed.
# 2. needless to say, **don't** declare the repos you want to be
-# transparently proxied in the gitolite.conf for the slave.
+# transparently proxied in the gitolite.conf for the copy.
use Gitolite::Rc;
use Gitolite::Common;
@@ -58,7 +58,6 @@ use Gitolite::Conf::Load;
use strict;
use warnings;
-my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
my $soc = $ENV{SSH_ORIGINAL_COMMAND};
# ----------------------------------------------------------------------
diff --git a/src/triggers/expand-deny-messages b/src/triggers/expand-deny-messages
index a8b2289..107202c 100755
--- a/src/triggers/expand-deny-messages
+++ b/src/triggers/expand-deny-messages
@@ -2,6 +2,8 @@
use strict;
use warnings;
+$|++;
+
# program name: expand-deny-messages
# DOCUMENTATION IS AT THE BOTTOM OF THIS FILE; PLEASE READ
@@ -47,10 +49,14 @@ _info( "Operation", _op( $a12, $aa, $oldsha, $newsha ) );
if ( $ref =~ m((^VREF/[^/]+)) ) {
my $vref = $1;
- my $vref_text = slurp( _which( $vref, 'x' ) );
- my $etag = '(?:help|explain|explanation)';
- $vref_text =~ m(^\s*# $etag.start\n(.*)^\s*# $etag.end\n)sm
- and print STDERR "Explanation for $vref:\n$1";
+ if ($ref =~ s(^VREF/NAME/)()) {
+ print STDERR "You're apparently not allowed to push '$ref'";
+ } else {
+ my $vref_text = slurp( _which( $vref, 'x' ) );
+ my $etag = '(?:help|explain|explanation)';
+ $vref_text =~ m(^\s*# $etag.start\n(.*)^\s*# $etag.end\n)sm
+ and print STDERR "Explanation for $vref:\n$1";
+ }
}
print STDERR "\n";
diff --git a/src/triggers/post-compile/ssh-authkeys-split b/src/triggers/post-compile/ssh-authkeys-split
index b71f9eb..031bd07 100755
--- a/src/triggers/post-compile/ssh-authkeys-split
+++ b/src/triggers/post-compile/ssh-authkeys-split
@@ -18,13 +18,6 @@
# - assumes you don't have a subdir in keydir called "__split_keys__"
-# - RUNNING "GITOLITE SETUP" WILL LOSE ALL THESE KEYS. So if you ever do
-# that, you will then need to make a dummy push to the admin repo to add
-# them back. If all your **admin** keys were in split keys, then you lost
-# remote access. If that happens, log on to the server using "su - git" or
-# such, then use the methods described in the "bypassing gitolite" section
-# in "emergencies.html" instead of a remote push.
-
# SUPPORT
# -------
#
@@ -42,7 +35,29 @@ rm -rf __split_keys__
mkdir __split_keys__
export SKD=$PWD/__split_keys__
-find . -type f -name "*.pub" | while read k
+# if we're coming from a gitolite-admin push, delete all *.multi, and rename
+# all multi-line *.pub to *.multi
+if [ "$GL_REPO" = "gitolite-admin" ] || [ "$GL_BYPASS_ACCESS_CHECKS" = "1" ]
+then
+ find . -type f -name "*.multi" | while read k
+ do
+ rm -f "$k"
+ done
+ find . -type f -name "*.pub" | while read k
+ do
+ # is this a multi-key?
+ lines=`wc -l < $k`
+ case $lines in
+ (0|1) continue
+ esac
+
+ base=`basename $k .pub`
+ mv $k $base.multi
+ done
+fi
+
+# now process *.multi
+find . -type f -name "*.multi" | while read k
do
# do we need to split?
lines=`wc -l < $k`
@@ -50,14 +65,16 @@ do
(0|1) continue
esac
- # is it sane to split?
- base=`basename $k .pub`
+ base=`basename $k .multi`
+ # sanity check
echo $base | grep '@' >/dev/null && continue
# ok do it
- seq=1
+ seq=0
while read line
do
+ (( seq++ ))
+ [ -z "$line" ] && continue
f=$SKD/$base@$seq.pub
echo "$line" > $f
# similar sanity check as main ssh-authkeys script
@@ -66,9 +83,5 @@ do
echo 1>&2 "ssh-authkeys-split: bad line $seq in keydir/$k"
rm -f $f
fi
- (( seq++ ))
done < $k
-
- # now delete the original file
- rm $k
done
diff --git a/src/triggers/post-compile/update-git-configs b/src/triggers/post-compile/update-git-configs
index bdb83ac..6eb2f46 100755
--- a/src/triggers/post-compile/update-git-configs
+++ b/src/triggers/post-compile/update-git-configs
@@ -17,13 +17,6 @@ my $RB = $rc{GL_REPO_BASE};
_chdir($RB);
# ----------------------------------------------------------------------
-# skip if arg-0 is POST_CREATE and no arg-2 (user name) exists; this means
-# it's been triggered by a *normal* (not "wild") repo creation, which in turn
-# means a POST_COMPILE should be following so there's no need to waste time
-# running this once for each new repo
-exit 0 if @ARGV and $ARGV[0] eq 'POST_CREATE' and not $ARGV[2];
-
-# ----------------------------------------------------------------------
# if called from POST_CREATE, we have only a single repo to worry about
if ( @ARGV and $ARGV[0] eq 'POST_CREATE' ) {
my $repo = $ARGV[1];
@@ -46,12 +39,15 @@ sub fixup_config {
my $creator = creator($pr);
my $gc = git_config( $pr, '.', 1 );
+ my $ac = `git config --file $RB/$pr.git/config -l`;
while ( my ( $key, $value ) = each( %{$gc} ) ) {
next if $key =~ /^gitolite-options\./;
$value =~ s/(@\w+)/expand_group($1)/ge if $rc{EXPAND_GROUPS_IN_CONFIG};
+ my $lkey = lc $key;
+ next if $ac =~ /^\Q$lkey\E=\Q$value\E$/m;
if ( $value ne "" ) {
system( "git", "config", "--file", "$RB/$pr.git/config", $key, $value );
- } else {
+ } elsif ( $ac =~ /^\Q$lkey\E=/m ) {
system( "git", "config", "--file", "$RB/$pr.git/config", "--unset-all", $key );
}
}
diff --git a/src/triggers/post-compile/update-git-daemon-access-list b/src/triggers/post-compile/update-git-daemon-access-list
index 446b0da..ade97a8 100755
--- a/src/triggers/post-compile/update-git-daemon-access-list
+++ b/src/triggers/post-compile/update-git-daemon-access-list
@@ -11,21 +11,20 @@ use Gitolite::Common;
use strict;
use warnings;
-# ----------------------------------------------------------------------
-# skip if arg-0 is POST_CREATE and no arg-2 (user name) exists; this means
-# it's been triggered by a *normal* (not "wild") repo creation, which in turn
-# means a POST_COMPILE should be following so there's no need to waste time
-# running this once for each new repo
-exit 0 if @ARGV and $ARGV[0] eq 'POST_CREATE' and not $ARGV[2];
-
my $EO = "git-daemon-export-ok";
my $RB = $rc{GL_REPO_BASE};
-for my $d (`gitolite list-phy-repos | gitolite access % daemon R any`) {
+my $cmd = "gitolite list-phy-repos";
+if ( @ARGV and $ARGV[0] eq 'POST_CREATE' ) {
+ # only one repo to do
+ $cmd = "echo $ARGV[1]";
+}
+
+for my $d (`$cmd | gitolite access % daemon R any`) {
my @F = split "\t", $d;
if ($F[2] =~ /DENIED/) {
unlink "$RB/$F[0].git/$EO";
- } else {
+ } elsif (! -f "$RB/$F[0].git/$EO") {
textfile( file => $EO, repo => $F[0], text => "" );
}
}
diff --git a/src/triggers/post-compile/update-gitweb-access-list b/src/triggers/post-compile/update-gitweb-access-list
index 937226b..4085d59 100755
--- a/src/triggers/post-compile/update-gitweb-access-list
+++ b/src/triggers/post-compile/update-gitweb-access-list
@@ -11,13 +11,6 @@
# permissions changes for wild repos) and then you should not delete it.
[ "$1" = "POST_CREATE" ] && [ "$4" != "perms" ] && rm -f $GL_REPO_BASE/$2.git/description 2>/dev/null
-# ----------------------------------------------------------------------
-# skip if arg-1 is POST_CREATE and no arg-3 (user name) exists; this means
-# it's been triggered by a *normal* (not "wild") repo creation, which in turn
-# means a POST_COMPILE should be following so there's no need to waste time
-# running this once for each new repo
-[ "$1" = "POST_CREATE" ] && [ -z "$3" ] && exit 0;
-
plf=`gitolite query-rc GITWEB_PROJECTS_LIST`
[ -z "$plf" ] && plf=$HOME/projects.list
# since mktemp does not honor umask, we just use it to generate a temp
@@ -25,11 +18,23 @@ plf=`gitolite query-rc GITWEB_PROJECTS_LIST`
tmpfile=`mktemp $plf.tmp_XXXXXXXX`
rm -f $tmpfile;
-(
- gitolite list-phy-repos | gitolite access % gitweb R any | grep -v DENIED
- gitolite list-phy-repos | gitolite git-config -r % gitweb\\.
-) |
- cut -f1 | sort -u | sed -e 's/$/.git/' > $tmpfile
+if [ "$1" = "POST_CREATE" ] && [ -n "$2" ]
+then
+ # just one to be done
+ repo="$2"
+ grep -v "^$repo.git$" $plf > $tmpfile
+ if gitolite access -q $repo gitweb R any || gitolite git-config -q -r $repo gitweb\\.
+ then
+ echo "$repo.git" >> $tmpfile
+ fi
+else
+ # all of them
+ (
+ gitolite list-phy-repos | gitolite access % gitweb R any | grep -v DENIED
+ gitolite list-phy-repos | gitolite git-config -r % gitweb\\.
+ ) |
+ cut -f1 | sort -u | sed -e 's/$/.git/' > $tmpfile
+fi
[ -f $plf ] && perl -e "chmod ( ( (stat('$plf'))[2] & 07777 ), '$tmpfile')"
mv $tmpfile $plf
diff --git a/src/triggers/post-compile/update-gitweb-daemon-from-options b/src/triggers/post-compile/update-gitweb-daemon-from-options
index 9b499b2..1f5fd26 100755
--- a/src/triggers/post-compile/update-gitweb-daemon-from-options
+++ b/src/triggers/post-compile/update-gitweb-daemon-from-options
@@ -1,5 +1,9 @@
#!/bin/sh
+# TODO: look at the commit in which *this* line was added, and see the changes
+# to the other scripts. We need to make those changes here also, but I'm too
+# lazy right now. Plus I'm not even sure if anyone is using this!
+
# Update git-daemon and gitweb access using 'option' lines instead of special
# usernames.
@@ -21,13 +25,6 @@
# This is useful for people who don't like '@all' to be literally *all* users,
# including gitweb and daemon, and can't/won't use deny-rules properly.
-# ----------------------------------------------------------------------
-# skip if arg-1 is POST_CREATE and no arg-3 (user name) exists; this means
-# it's been triggered by a *normal* (not "wild") repo creation, which in turn
-# means a POST_COMPILE should be following so there's no need to waste time
-# running this once for each new repo
-[ "$1" = "POST_CREATE" ] && [ -z "$3" ] && exit 0;
-
# first do the gitweb stuff
plf=`gitolite query-rc GITWEB_PROJECTS_LIST`
diff --git a/src/triggers/repo-specific-hooks b/src/triggers/repo-specific-hooks
index bba7a58..4044cc9 100755
--- a/src/triggers/repo-specific-hooks
+++ b/src/triggers/repo-specific-hooks
@@ -41,21 +41,21 @@ while (<>) {
$hook =~ s/\..*//;
my @codes = split /\s+/, $codes;
- next unless @codes;
- # this is a special case
+ # bail on disallowed hook types (but warn only if @codes is non-empty)
if ( $repo eq 'gitolite-admin' and $hook eq 'post-update' ) {
- _warn "repo-specific-hooks: ignoring attempts to set post-update hook for the admin repo";
+ _warn "repo-specific-hooks: ignoring attempts to set post-update hook for the admin repo" if @codes;
next;
}
-
unless ( $hook =~ /^(pre-receive|post-receive|post-update|pre-auto-gc)$/ ) {
- _warn "repo-specific-hooks: '$hook' is not allowed, ignoring";
- _warn " (only pre-receive, post-receive, post-update, and pre-auto-gc are allowed)";
+ if (@codes) {
+ _warn "repo-specific-hooks: '$hook' is not allowed, ignoring";
+ _warn " (only pre-receive, post-receive, post-update, and pre-auto-gc are allowed)";
+ }
next;
}
- push @{ $repo_hooks{$repo}{$hook} }, @codes if @codes;
+ push @{ $repo_hooks{$repo}{$hook} }, @codes;
}
for my $repo (keys %repo_hooks) {
@@ -111,8 +111,8 @@ for h in $0.*; do
[ -x $h ] || continue
if [ $type = args ]
then
- $h $@
+ $h $@ || { [ $0 = hooks/pre-receive ] && exit 1; }
else
- echo "$stdin" | $h
+ echo "$stdin" | $h || { [ $0 = hooks/pre-receive ] && exit 1; }
fi
done
diff --git a/src/triggers/upstream b/src/triggers/upstream
index c64e2f2..611e11e 100755
--- a/src/triggers/upstream
+++ b/src/triggers/upstream
@@ -32,7 +32,7 @@ git fetch -q "$url" '+refs/*:refs/*'
# R = @all
# RW+ my-company/ = @developers
#
-# option upstream.url = git://git.kernel.org/pub/scm/git/git.git
+# option upstream.url = https://git.kernel.org/pub/scm/git/git.git
# option upstream.nice = 120
#
# * to force a fetch on the server shell (or via cron), run this command:
@@ -55,9 +55,9 @@ git fetch -q "$url" '+refs/*:refs/*'
# repo github/CREATOR/..*
# C = @all
# R = @all
-# option upstream.url = git://github.com/%GL_REPO.git
-# option upstream.nice = 120
-# config url.git://github.com/.insteadOf = git://github.com/github/
+# option upstream.url = https://github.com/%GL_REPO.git
+# option upstream.nice = 120
+# config url.https://github.com/.insteadOf = https://github.com/github/
#
# Now you can make local, read-only, clones of all your github repos with
#