#!/usr/bin/perl use strict; use warnings; my $tid; BEGIN { $tid = $ENV{GL_TID} || 0; delete $ENV{GL_TID}; } use lib $ENV{GL_LIBDIR}; use Gitolite::Rc; use Gitolite::Common; use Gitolite::Conf::Load; =for usage Usage 1: gitolite mirror push Usage 2: ssh git@master-server mirror push Forces a push of one repo to one slave. 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 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 before doing the push. =cut usage() if not @ARGV or $ARGV[0] eq '-h'; _die "HOSTNAME not set" if not $rc{HOSTNAME}; my ( $cmd, $host, $repo ) = @ARGV; 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 trace( 1, "TID=$tid host=$host repo=$repo", "gitolite mirror push started" ); _chdir( $rc{GL_REPO_BASE} ); _chdir("$repo.git"); if (-f "gl-creator") { # try to propagate the wild repo, including creator name and gl-perms my $creator = `cat gl-creator`; chomp($creator); trace(1, `cat gl-perms 2>/dev/null | ssh $host CREATOR=$creator perms -c \\'$repo\\' 2>/dev/null`); } my $errors = 0; for (`git push --mirror $host:$repo 2>&1`) { $errors = 1 if $?; print STDERR "$_" if -t STDERR or exists $ENV{GL_USER}; chomp; if (/FATAL/) { $errors = 1; gl_log( 'mirror', $_ ); } else { trace( 1, "mirror: $_" ); } } exit $errors; } sub valid_slave { my ( $host, $repo ) = @_; _die "invalid repo '$repo'" unless $repo =~ $REPONAME_PATT; my $ref = git_config( $repo, "^gitolite-options\\.mirror\\.slaves.*" ); my %list = map { $_ => 1 } map { split } values %$ref; _die "'$host' not a valid slave for '$repo'" unless $list{$host}; }