Pushmi::Command::Mirror - initialize pushmi mirrors
Index
Code Index:
NAME

Pushmi::Command::Mirror - initialize pushmi mirrors
SYNOPSIS

package Pushmi::Command::Mirror;
use strict;
use warnings;
use base 'Pushmi::Command';
use Pushmi::Mirror;
use Pushmi::Config;
use Path::Class;
use SVN::Mirror;
use SVK::Config;
use SVK::Mirror;
use SVK::XD;
use SVN::Delta;
use SVK::I18N;
use UNIVERSAL::require;
my $logger = Pushmi::Config->logger('pushmi.svkmirror');
{
no warnings 'redefine';
my $memd = Pushmi::Config->memcached;
*SVK::Mirror::lock = sub {
my ($self) = @_;
my $fs = $self->repos->fs;
my $token = join(':', $self->repos->path, $self->_lock_token );
my $content = $self->_lock_content;
my $where = join( ' ', ( caller(0) )[ 0 .. 2 ] );
my $lock_message = $self->_lock_message;
LOCKED:
{
my $pool = SVN::Pool->new_default;
my $trial = 0;
while (1) {
$pool->clear;
my $ret;
last LOCKED if $ret = $memd->add( $token, $content );
my $who = $memd->get( $token ) or next;
last if $who eq $content;
$logger->warn('['.$self->repos->path."] lock held by $who...")
unless $trial++ % 60;
$lock_message->($self, $who);
sleep 1;
}
}
$logger->debug('['.$self->repos->path."] locked by ".$token);
$self->_locked(1);
};
*SVK::Mirror::unlock = sub {
my ( $self, $force ) = @_;
my $token = join(':', $self->repos->path, $self->_lock_token );
my $who = $memd->get( $token );
if ($force || $self->_locked ) {
my $ret = $memd->delete( $token );
$logger->debug('['.$self->repos->path."] unlock result: $ret");
$self->_locked(0);
}
};
}
sub options { () }
sub run {
my $self = shift;
# compat
for ($self->subcommands) {
if ($self->{$_}) {
my $cmd = 'Pushmi::Command::'.ucfirst($_);
$cmd->require or die "can't require $cmd: $@";
return (bless $self, $cmd)->run(@_)
}
}
$self->run_init(@_);
}
sub root_svkpath {
my ($self, $repos) = @_;
my $depot = SVK::Depot->new( { repos => $repos, repospath => $repos->path, depotname => '' } );
SVK::Path->real_new(
{
depot => $depot,
path => '/'
}
)->refresh_revision;
}
sub setup_auth {
my $self = shift;
my $config = Pushmi::Config->config;
SVK::Config->auth_providers(
sub {
[ $config->{use_cached_auth} ? SVN::Client::get_simple_provider() : (),
SVN::Client::get_username_provider(),
SVN::Client::get_ssl_server_trust_file_provider(),
SVN::Client::get_ssl_server_trust_prompt_provider(
\&SVK::Config::_ssl_server_trust_prompt
),
SVN::Client::get_simple_prompt_provider( $self->can('pushmi_auth'), 0 ) ]
});
}
# XXX: we should be using real providers if we can thunk svn::auth providers
sub pushmi_auth {
my ($cred, $realm, $default_username, $may_save, $pool) = @_;
my $config = Pushmi::Config->config;
$logger->logdie("unable to get username from config file.")
unless defined $config->{username};
$cred->username($config->{username});
$cred->password($config->{password});
$cred->may_save(0);
return $SVN::_Core::SVN_NO_ERROR;
}
sub canonpath {
my $self = shift;
$_[0] = Path::Class::Dir->new($_[0])->absolute->stringify;
}
sub run_init {
my ($self, $repospath, $url) = @_;
$self->canonpath($repospath);
my ($repos, $created);
die "url required.\n" unless $url;
if (-e $repospath) {
$repos = SVN::Repos::open($repospath) or die "Can't open repository: $@";
}
else {
$created = 1;
$repos = SVN::Repos::create($repospath, undef, undef, undef, undef )
or die "Unable to create repository on $repospath";
}
my $t = $self->root_svkpath($repos);
my $mirror = SVK::Mirror->new( { depot => $t->depot, path => '/', url => $url, pool => SVN::Pool->new} );
require SVK::Mirror::Backend::SVNSync;
$self->setup_auth;
my $backend = bless { mirror => $mirror }, 'SVK::Mirror::Backend::SVNSync';
$mirror->_backend($backend->create( $mirror ));
Pushmi::Mirror->install_hook($repospath);
$mirror->depot->repos->fs->set_uuid($mirror->server_uuid);
print loc("Mirror initialized.\n");
return;
}
sub ensure_consistency {
my ($self, $t) = @_;
my $repos = $t->repos;
my $revision = $repos->fs->revision_prop(0, 'pushmi:inconsistent')
or return;
my $repospath = $repos->path;
$logger->info("[$repospath] ".ref($self).' blocked by inconsistency');
my ($mirror) = $t->is_mirrored;
my $master = $mirror->url;
die "Pushmi slave in inconsistency. Please use the master repository at $master\nand contact your administrator. Sorry for the inconveniences.\n";
}
1;