[Bps-public-commit] r14307 - in Pushmi/branches/lock: . lib/Pushmi lib/Pushmi/Command
clkao at bestpractical.com
clkao at bestpractical.com
Fri Jul 18 22:29:18 EDT 2008
Author: clkao
Date: Fri Jul 18 22:29:18 2008
New Revision: 14307
Modified:
Pushmi/branches/lock/ (props changed)
Pushmi/branches/lock/lib/Pushmi/Command.pm
Pushmi/branches/lock/lib/Pushmi/Command/Mirror.pm
Pushmi/branches/lock/lib/Pushmi/Command/Runhook.pm
Pushmi/branches/lock/lib/Pushmi/Command/Sync.pm
Pushmi/branches/lock/lib/Pushmi/Command/Tryauth.pm
Pushmi/branches/lock/lib/Pushmi/Command/Unlock.pm
Pushmi/branches/lock/lib/Pushmi/Command/Verify.pm
Pushmi/branches/lock/lib/Pushmi/Config.pm
Pushmi/branches/lock/lib/Pushmi/Mirror.pm
Pushmi/branches/lock/lib/Pushmi/Test.pm
Pushmi/branches/lock/t/basic.t
Pushmi/branches/lock/t/concurrency.t
Pushmi/branches/lock/t/verify.t
Log:
- Merge /bps/mirror/Pushmi/trunk to /bps/mirror/Pushmi/branches/lock
Modified: Pushmi/branches/lock/lib/Pushmi/Command.pm
==============================================================================
--- Pushmi/branches/lock/lib/Pushmi/Command.pm (original)
+++ Pushmi/branches/lock/lib/Pushmi/Command.pm Fri Jul 18 22:29:18 2008
@@ -1,5 +1,108 @@
package Pushmi::Command;
+use strict;
+use warnings;
use base qw(App::CLI App::CLI::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');
+
+sub setup_auth {
+ my $self = shift;
+ my ($auth) = @_;
+ $auth ||= $self->can("pushmi_auth");
+ 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( $auth, 0 ) ]
+ });
+}
+
+sub run {
+ my $self = shift;
+
+ # compat
+ for ($self->subcommands) {
+ if (delete $self->{$_}) {
+ my $cmd = 'Pushmi::Command::'.ucfirst($_);
+ $cmd->require or die "can't require $cmd: $@";
+ return (bless $self, $cmd)->run(@_);
+ }
+ }
+
+ no warnings 'redefine';
+ my $memd = Pushmi::Config->memcached;
+
+ local *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);
+ };
+
+ local *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);
+ }
+ };
+
+ $self->setup_auth;
+ return $self->run_with_auth(@_);
+}
+
+
+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;
+}
+
+
1;
Modified: Pushmi/branches/lock/lib/Pushmi/Command/Mirror.pm
==============================================================================
--- Pushmi/branches/lock/lib/Pushmi/Command/Mirror.pm (original)
+++ Pushmi/branches/lock/lib/Pushmi/Command/Mirror.pm Fri Jul 18 22:29:18 2008
@@ -2,173 +2,32 @@
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 {
+sub run_with_auth {
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 $pushmi = Pushmi::Mirror->new( path => $repospath );
+ $pushmi->repos( create => 1 );
- my $mirror = SVK::Mirror->new( { depot => $t->depot, path => '/', url => $url, pool => SVN::Pool->new} );
+ my $mirror = SVK::Mirror->new( { depot => $pushmi->root_svkpath->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);
+ $pushmi->install_hook($repospath);
+ $pushmi->repos->fs->set_uuid($mirror->server_uuid);
- print loc("Mirror initialized.\n");
+ $logger->info(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";
-
-}
-
=head1 NAME
Pushmi::Command::Mirror - initialize pushmi mirrors
Modified: Pushmi/branches/lock/lib/Pushmi/Command/Runhook.pm
==============================================================================
--- Pushmi/branches/lock/lib/Pushmi/Command/Runhook.pm (original)
+++ Pushmi/branches/lock/lib/Pushmi/Command/Runhook.pm Fri Jul 18 22:29:18 2008
@@ -1,5 +1,7 @@
package Pushmi::Command::Runhook;
-use base 'Pushmi::Command::Mirror';
+use strict;
+use warnings;
+use base 'Pushmi::Command';
use SVK::Editor::MapRev;
our $AUTHOR;
@@ -9,15 +11,11 @@
('txnname=s' => 'txnname')
}
-sub run {
+sub run_with_auth {
my ($self, $repospath) = @_;
- die "repospath required" unless $repospath;
- $self->canonpath($repospath);
Carp::confess "txnname required" unless $self->{txnname};
- my $repos = SVN::Repos::open($repospath) or die "Can't open repository: $@";
-
- my $fs = $repos->fs;
- my $txn = $fs->open_txn($self->{txnname}) or die 'no such txn';
+ my $pushmi = Pushmi::Mirror->new( path => $repospath );
+ my $txn = $pushmi->repos->fs->open_txn($self->{txnname}) or die 'no such txn';
if ($txn->prop('svk:commit')) {
$txn->change_prop('svk:commit', undef);
exit 0;
@@ -28,13 +26,12 @@
# my $anchor = $self->_find_txn_anchor($txn_root);
# warn "doing $self->{txnname}: ".join(',', keys %{ $txn_root->paths_changed });
- my $t = $self->root_svkpath($repos);
- $self->ensure_consistency($t);
+ my $t = $pushmi->root_svkpath;
+ $pushmi->ensure_consistency;
# XXX: if we reentrant, the mirror will be in deadlock.
$AUTHOR = $txn->prop('svn:author');
$logger->info("[$repospath] committing from txn $self->{txnname} by $AUTHOR");
- $self->setup_auth;
# retrieve from memcached as soon as possible, as get_editor might
# delay because of the server latency of the first response
_get_password();
@@ -42,7 +39,7 @@
callback => sub {},
caller => '',
message => $txn->prop('svn:log'));
- my ($mirror) = $t->is_mirrored;
+ my $mirror = $pushmi->master;
require Pushmi::Editor::Locker;
$editor = Pushmi::Editor::Locker->new
@@ -100,7 +97,7 @@
# we need to switch back to the sync credential
delete $mirror->_backend->{_cached_ra};
- $self->setup_auth(Pushmi::Command::Mirror->can('pushmi_auth'));
+ $self->setup_auth(Pushmi::Command->can('pushmi_auth'));
my ($first, $last);
# if we failed on out-of-date, we might not have reached the
Modified: Pushmi/branches/lock/lib/Pushmi/Command/Sync.pm
==============================================================================
--- Pushmi/branches/lock/lib/Pushmi/Command/Sync.pm (original)
+++ Pushmi/branches/lock/lib/Pushmi/Command/Sync.pm Fri Jul 18 22:29:18 2008
@@ -1,7 +1,7 @@
package Pushmi::Command::Sync;
use strict;
use warnings;
-use base 'Pushmi::Command::Mirror';
+use base 'Pushmi::Command';
use SVK::I18N;
my $memd = Pushmi::Config->memcached;
@@ -11,28 +11,19 @@
('nowait' => 'nowait');
}
-sub run {
+sub run_with_auth {
my ($self, $repospath) = @_;
- $self->canonpath($repospath);
- my $repos = SVN::Repos::open($repospath) or die "Can't open repository: $@";
+ my $pushmi = Pushmi::Mirror->new( path => $repospath );
+ $pushmi->ensure_consistency;
- my $t = $self->root_svkpath($repos);
- $self->ensure_consistency($t);
-
- $self->setup_auth;
- my ($mirror) = $t->is_mirrored;
-
- if ($self->{nowait}) {
- my $token = join(':', $mirror->repos->path, $mirror->_lock_token);
- if (my $who = $memd->get( $token ) ) {
- print loc("Mirror on $repospath is locked by %1, skipping.\n", $who);
- return;
- }
+ if ($self->{nowait} and $pushmi->locked) {
+ print loc("Mirror on $repospath is locked by %1, skipping.\n", $pushmi->locked);
+ return;
}
my ($first, $last);
eval {
- $mirror->mirror_changesets(undef,
+ $pushmi->master->mirror_changesets(undef,
sub { $first ||= $_[0]; $last = $_[0] });
};
$logger->error("[$repospath] sync failed: $@") if $@;
Modified: Pushmi/branches/lock/lib/Pushmi/Command/Tryauth.pm
==============================================================================
--- Pushmi/branches/lock/lib/Pushmi/Command/Tryauth.pm (original)
+++ Pushmi/branches/lock/lib/Pushmi/Command/Tryauth.pm Fri Jul 18 22:29:18 2008
@@ -1,5 +1,7 @@
package Pushmi::Command::Tryauth;
-use base 'Pushmi::Command::Mirror';
+use strict;
+use warnings;
+use base 'Pushmi::Command';
our ($USER, $PASS) = @_;
@@ -11,16 +13,11 @@
return $SVN::_Core::SVN_NO_ERROR;
}
-sub run {
+sub run_with_auth {
my ($self, $repospath, $user, $pass) = @_;
($USER, $PASS) = ($user, $pass);
- die "repospath required" unless $repospath;
- $self->canonpath($repospath);
- my $repos = SVN::Repos::open($repospath) or die "Can't open repository: $@";
- my $t = $self->root_svkpath($repos);
- my ($mirror) = $t->is_mirrored;
- $self->setup_auth;
- my $editor = eval { $mirror->get_commit_editor('', '*should not be committed*', sub {}) };
+ my $pushmi = Pushmi::Mirror->new( path => $repospath );
+ my $editor = eval { $pushmi->master->get_commit_editor('', '*should not be committed*', sub {}) };
if ($editor) {
$editor->abort_edit;
exit 0;
Modified: Pushmi/branches/lock/lib/Pushmi/Command/Unlock.pm
==============================================================================
--- Pushmi/branches/lock/lib/Pushmi/Command/Unlock.pm (original)
+++ Pushmi/branches/lock/lib/Pushmi/Command/Unlock.pm Fri Jul 18 22:29:18 2008
@@ -1,9 +1,7 @@
package Pushmi::Command::Unlock;
-use base 'Pushmi::Command::Mirror';
use strict;
use warnings;
-
-use SVK::I18N;
+use base 'Pushmi::Command';
my $logger = Pushmi::Config->logger('pushmi.unlock');
@@ -11,29 +9,21 @@
( 'revision=i' => 'revision' )
}
-sub run {
+sub run_with_auth {
my ($self, $repospath) = @_;
- $self->canonpath($repospath);
- my $repos = SVN::Repos::open($repospath) or die "Can't open repository: $@";
-
- my $t = $self->root_svkpath($repos);
-
- $self->setup_auth;
- my ($mirror) = $t->is_mirrored;
+ my $pushmi = Pushmi::Mirror->new( path => $repospath );
- my $token = join(':', $mirror->repos->path, $mirror->_lock_token);
+ my $token = $pushmi->lock_token;
if ($self->{revision}) {
# non-runhook commits (like sync), nothing to unlock for.
- my $expected = $t->repos->fs->revision_prop($self->{revision}, 'svk:committed-by') or return;
+ my $expected = $pushmi->repos->fs->revision_prop($self->{revision}, 'svk:committed-by') or return;
if ($expected ne $token) {
$logger->logdie("[$repospath] revision $self->{revision} does not own lock $expected, expecting $token");
}
}
- my $memd = Pushmi::Config->memcached;
- if (my $content = $memd->get( $token ) ) {
+ if (my $content = $pushmi->locked ) {
$logger->info("[$repospath] lock $token ($content) removed");
- print loc("Removing lock %1 on %2.\n", $content, $repospath);
- $mirror->unlock('force');
+ $pushmi->unlock('force');
}
else {
$logger->info("[$repospath] lock $token not found");
Modified: Pushmi/branches/lock/lib/Pushmi/Command/Verify.pm
==============================================================================
--- Pushmi/branches/lock/lib/Pushmi/Command/Verify.pm (original)
+++ Pushmi/branches/lock/lib/Pushmi/Command/Verify.pm Fri Jul 18 22:29:18 2008
@@ -1,13 +1,11 @@
package Pushmi::Command::Verify;
-use base 'Pushmi::Command::Mirror';
use strict;
use warnings;
+use base 'Pushmi::Command';
use constant subcommands => qw(enable correct);
use IPC::Run3 'run3';
-use SVK::I18N;
-
my $logger = Pushmi::Config->logger('pushmi.verify');
sub options {
@@ -17,24 +15,17 @@
)
}
-sub get_path {
- my ($self, $repospath) = @_;
- $self->canonpath($repospath);
- my $repos = SVN::Repos::open($repospath) or die "Can't open repository: $@";
- return $self->root_svkpath($repos);
-}
-
-sub run {
+sub run_with_auth {
my ($self, $repospath) = @_;
- my $t = $self->get_path($repospath);
+ my $pushmi = Pushmi::Mirror->new( path => $repospath );
- $t->repos->fs->revision_prop(0, 'pushmi:auto-verify')
+ $pushmi->repos->fs->revision_prop(0, 'pushmi:auto-verify')
or return;
die "Revision required.\n" unless $self->{revision};
my $verify_mirror = Pushmi::Config->config->{verify_mirror} || 'verify-mirror';
- my $path = $t->path;
+ my $path = $pushmi->repos->path;
my $output;
eval {
@@ -50,7 +41,7 @@
$logger->logdie("[$repospath] can't run verify: $!") if $? == -1;
- $t->repos->fs->change_rev_prop(0, 'pushmi:inconsistent', $self->{revision});
+ $pushmi->repos->fs->change_rev_prop(0, 'pushmi:inconsistent', $self->{revision});
$logger->logdie("[$repospath] can't verify: $output");
}
@@ -60,9 +51,8 @@
sub run {
my ($self, $repospath) = @_;
- my $t = $self->get_path($repospath);
-
- $t->repos->fs->change_rev_prop(0, 'pushmi:auto-verify', '*');
+ my $pushmi = Pushmi::Mirror->new( path => $repospath );
+ $pushmi->repos->fs->change_rev_prop(0, 'pushmi:auto-verify', '*');
print "Auto-verify enabled for $repospath.\n";
}
@@ -72,12 +62,12 @@
sub run {
my ($self, $repospath) = @_;
- my $t = $self->get_path($repospath);
+ my $pushmi = Pushmi::Mirror->new( path => $repospath );
- my $rev = $t->repos->fs->revision_prop(0, 'pushmi:inconsistent')
+ my $rev = $pushmi->repos->fs->revision_prop(0, 'pushmi:inconsistent')
or return;
- $t->repos->fs->change_rev_prop(0, 'pushmi:inconsistent', undef);
+ $pushmi->repos->fs->change_rev_prop(0, 'pushmi:inconsistent', undef);
print "Inconsistency on revision $rev on $repospath cleared.\n";
}
Modified: Pushmi/branches/lock/lib/Pushmi/Config.pm
==============================================================================
--- Pushmi/branches/lock/lib/Pushmi/Config.pm (original)
+++ Pushmi/branches/lock/lib/Pushmi/Config.pm Fri Jul 18 22:29:18 2008
@@ -15,16 +15,18 @@
warn "pushmi config $file doesn't exist.\n";
return $config = {};
}
-
- return $config = LoadFile($file);
+ $config = LoadFile($file);
+ return $config;
}
sub logger {
shift;
- my $file = $ENV{PUSHMI_CONFIG} || '/etc/pushmi.conf';
- $file =~ s/pushmi/pushmi-log/;
- Log::Log4perl::init($file) if -e $file;
- Log::Log4perl::init('/etc/pushmi-log.conf') if -e '/etc/pushmi-log.conf';
+ unless (Log::Log4perl->initialized) {
+ my $file = $ENV{PUSHMI_CONFIG} || '/etc/pushmi.conf';
+ $file =~ s/pushmi/pushmi-log/;
+ Log::Log4perl::init($file) if -e $file;
+ Log::Log4perl::init('/etc/pushmi-log.conf') if -e '/etc/pushmi-log.conf';
+ }
return Log::Log4perl->get_logger(@_);
}
Modified: Pushmi/branches/lock/lib/Pushmi/Mirror.pm
==============================================================================
--- Pushmi/branches/lock/lib/Pushmi/Mirror.pm (original)
+++ Pushmi/branches/lock/lib/Pushmi/Mirror.pm Fri Jul 18 22:29:18 2008
@@ -1,24 +1,101 @@
package Pushmi::Mirror;
use strict;
+use warnings;
+
use SVN::Core;
use SVN::Repos;
use SVN::Fs;
-use SVK::Util qw(abs_path can_run);
+use Pushmi::Config;
-sub install_hook {
- shift;
- my $repospath = shift;
- my $repos = SVN::Repos::open($repospath) or die; # XXX proper error
+use SVK::Util qw(can_run);
+
+sub new {
+ my $class = shift;
+ my %args = (@_);
+ die "Must provide path to Pushmi::Mirror->new" unless $args{path};
+ $args{path} = Path::Class::Dir->new( $args{path} )->absolute->stringify;
+ return bless \%args, $class;
+}
+
+sub path {
+ my $self = shift;
+ return $self->{path};
+}
- $repos->fs->change_rev_prop(0, 'svk:notify-commit', '*');
+sub repos {
+ my $self = shift;
+ my %args = ( create => 0, @_ );
+ my $repos;
+ if ( -e $self->path ) {
+ $repos = SVN::Repos::open( $self->path )
+ or die "Can't open repository @{[$self->path]}";
+ } elsif ( $args{create} ) {
+ $repos = SVN::Repos::create( $self->path, undef, undef, undef, undef )
+ or die "Unable to create repository @{[$self->path]}";
+ } else {
+ die "Repository @{[$self->path]} doesn't exist; won't create\n";
+ }
+ return $repos;
+}
+
+sub root_svkpath {
+ my $self = shift;
+ my $depot = SVK::Depot->new(
+ { repos => $self->repos,
+ repospath => $self->repos->path,
+ depotname => ''
+ }
+ );
+ return SVK::Path->real_new(
+ { depot => $depot,
+ path => '/'
+ }
+ )->refresh_revision;
+}
+
+sub master {
+ my $self = shift;
+ my ($mirror) = $self->root_svkpath->is_mirrored;
+ return $mirror;
+}
- my $perl = join(' ', $^X, map { "'-I$_'" } @INC);
+sub ensure_consistency {
+ my $self = shift;
+ return unless $self->repos->fs->revision_prop( 0, 'pushmi:inconsistent' );
+
+ my $master = $self->master->url;
+ die
+ "Pushmi slave in inconsistency. Please use the master repository at $master\nand contact your administrator. Sorry for the inconveniences.\n";
+}
+
+sub lock_token {
+ my $self = shift;
+ return
+ join( ':', $self->master->repos->path, $self->master->_lock_token );
+}
+
+sub locked {
+ my $self = shift;
+ return Pushmi::Config->memcached->get( $self->lock_token );
+}
+
+sub unlock {
+ my $self = shift;
+ return $self->master->unlock(@_);
+}
+
+sub install_hook {
+ my $self = shift;
+ my $repos = $self->repos;
+ $repos->fs->change_rev_prop( 0, 'svk:notify-commit', '*' );
+
+ my $perl = join( ' ', $^X, map {"'-I$_'"} @INC );
my $pushmi = can_run('pushmi') or die "can't find pushmi";
no warnings 'uninitialized';
- _install_hook($repospath, 'pre-commit', << "END");
+ _install_hook( $self->path, 'pre-commit', << "END");
#!/bin/sh
export SVKNOSVNCONFIG=1
export PUSHMI_CONFIG=$ENV{PUSHMI_CONFIG}
@@ -29,7 +106,7 @@
END
- _install_hook($repospath, 'post-commit', << "END");
+ _install_hook( $self->path, 'post-commit', << "END");
#!/bin/sh
export SVKNOSVNCONFIG=1
export PUSHMI_CONFIG=$ENV{PUSHMI_CONFIG}
@@ -44,7 +121,7 @@
}
sub _install_hook {
- my ($repospath, $hook, $content) = @_;
+ my ( $repospath, $hook, $content ) = @_;
my $hpath = "$repospath/hooks/$hook";
open my $fh, '>', $hpath or die $!;
@@ -53,9 +130,10 @@
close $fh;
chmod 0755, $hpath;
- unless (-x $hpath) {
- # log info
- return 0;
+ unless ( -x $hpath ) {
+
+ # log info
+ return 0;
}
return 1;
}
Modified: Pushmi/branches/lock/lib/Pushmi/Test.pm
==============================================================================
--- Pushmi/branches/lock/lib/Pushmi/Test.pm (original)
+++ Pushmi/branches/lock/lib/Pushmi/Test.pm Fri Jul 18 22:29:18 2008
@@ -4,7 +4,7 @@
use Pushmi::Config;
use base 'Exporter';
-our @EXPORT = qw(get_dav_server run_pushmi is_svn_output start_memcached check_apache);
+our @EXPORT = qw(get_dav_server run_pushmi is_svn_output start_memcached check_apache svn_error_txn_outofdate svn_error_commit_hook build_basic_test_ok);
use FindBin;
BEGIN {
@@ -17,6 +17,7 @@
use SVK::Util qw(can_run abs_path);
use IPC::Run3 'run3';
use Test::More;
+use SVK::Test;
my $apache_port = 5008;
@@ -51,7 +52,9 @@
my ($arg, $exp_stdout, $exp_stderr) = @_;
my $stdout_err = [];
$exp_stderr ||= [];
- my $ret = run3 ['svn', '--non-interactive', @$arg], undef,
+ my $ret = run3 ['svn', ($SVN::Core::VERSION ge '1.5.0'
+ ? '--non-interactive' : ()),
+ @$arg], undef,
_mk_cmp_closure($exp_stdout, $stdout_err), # stdout
_mk_cmp_closure($exp_stderr, $stdout_err); # stderr
if (@$stdout_err) {
@@ -156,6 +159,57 @@
diag 'stopping memcached'; kill 'TERM', $memcached_pid if $memcached_pid };
}
+sub svn_error_txn_outofdate {
+ my ($file, $txn) = @_;
+
+ my $rel_file = substr($file, 1);
+ return ("Out of date: '$rel_file' in transaction '$txn'")
+ if $SVN::Core::VERSION lt '1.5.0';
+
+ return "File '$file' is out of date";
+}
+
+sub svn_error_commit_hook {
+ my $exit_code = shift;
+
+ return ("svn: 'pre-commit' hook failed with error output:", @_)
+ if $SVN::Core::VERSION lt '1.5.0';
+
+ return ("svn: Commit blocked by pre-commit hook (exit code $exit_code) with output:", @_);
+}
+
+sub build_basic_test_ok {
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ my ($xd, $svk) = SVK::Test::build_test('test');
+ my ($srepospath, $spath, $srepos) = $xd->find_repos ('/test/', 1);
+
+ $svk->mkdir('-m', 'init', '/test/A');
+
+ my ($copath, $corpath) = get_copath('basic-svn');
+ my ($scopath, $scorpath) = get_copath('basic-svk');
+
+ my $uri = uri($srepospath.($spath eq '/' ? '' : $spath));
+
+ my ($repospath, $path, $repos) = $xd->find_repos ('//', 1);
+ ok( Pushmi::Mirror->new(path => $repospath)->install_hook );
+
+ start_memcached();
+ my $muri = uri($repospath.($path eq '/' ? '' : $path));
+
+ $svk->mirror('//', $uri);
+
+ is_output($svk, 'sync', ['//'],
+ ["Syncing $uri",
+ 'Retrieving log information from 1 to 1',
+ 'Committed revision 1 from revision 1.']);
+
+ # XXX: this is so lame
+ return ($svk,
+ $uri, $srepos, $spath, $scopath, $scorpath,
+ $muri, $repos, $path, $copath, $corpath);
+}
+
+
END {
for (@CLEANUP) {
$_->();
Modified: Pushmi/branches/lock/t/basic.t
==============================================================================
--- Pushmi/branches/lock/t/basic.t (original)
+++ Pushmi/branches/lock/t/basic.t Fri Jul 18 22:29:18 2008
@@ -8,31 +8,9 @@
plan tests => 28;
-my ($xd, $svk) = build_test('test');
-
-our $output;
-
-my ($srepospath, $spath, $srepos) = $xd->find_repos ('/test/', 1);
-
-$svk->mkdir('-m', 'init', '/test/A');
-
-my ($copath, $corpath) = get_copath('basic-svn');
-my ($scopath, $scorpath) = get_copath('basic-svk');
-
-my $uri = uri($srepospath.($spath eq '/' ? '' : $spath));
-
-my ($repospath, $path, $repos) = $xd->find_repos ('//', 1);
-ok( Pushmi::Mirror->install_hook($repospath) );
-
-start_memcached();
-my $muri = uri($repospath.($path eq '/' ? '' : $path));
-
-$svk->mirror('//', $uri);
-
-is_output($svk, 'sync', ['//'],
- ["Syncing $uri",
- 'Retrieving log information from 1 to 1',
- 'Committed revision 1 from revision 1.']);
+my ($svk,
+ $uri, $srepos, undef, undef, $scorpath,
+ $muri, $repos, undef, $copath, undef ) = build_basic_test_ok();
is_output($svk, 'sync', ['//'],
["Syncing $uri"]);
@@ -77,28 +55,12 @@
is($repos->fs->youngest_rev, 4, "svn didn't commit through");
append_file("fromsvn.txt", "to conflict\n");
-sub svn_error_txn_outofdate {
- my ($file, $txn) = @_;
- # XXX: older svn:
- # "Out of date: '$file' in transaction '$txn'";
- return "File '$file' is out of date";
-}
-
-sub svn_error_commit_hook {
- my ($exit_code, $file, $txn) = @_;
-
- return ("svn: Commit blocked by pre-commit hook (exit code $exit_code) with output:",
- svn_error_txn_outofdate($file, $txn));
-
- qr{svn: 'pre-commit' hook failed.*:},
- q{Out of date: 'fromsvn.txt' in transaction '5-1'}
-}
-
is_svn_output(['ci', -m => 'trying to commit outdated change from svn'],
['Sending fromsvn.txt',
'Transmitting file data .'],
['svn: Commit failed (details follow):',
- svn_error_commit_hook(255, '/fromsvn.txt'),
+ svn_error_commit_hook(255,
+ svn_error_txn_outofdate('/fromsvn.txt', '5-1')),
'']);
is($srepos->fs->youngest_rev, 5, "svn didn't commit through");
Modified: Pushmi/branches/lock/t/concurrency.t
==============================================================================
--- Pushmi/branches/lock/t/concurrency.t (original)
+++ Pushmi/branches/lock/t/concurrency.t Fri Jul 18 22:29:18 2008
@@ -8,31 +8,9 @@
plan tests => 10;
-my ($xd, $svk) = build_test('test');
-
-our $output;
-
-my ($srepospath, $spath, $srepos) = $xd->find_repos ('/test/', 1);
-start_memcached();
-
-$svk->mkdir('-m', 'init', '/test/A');
-
-my ($copath, $corpath) = get_copath('basic-svn');
-my ($scopath, $scorpath) = get_copath('basic-svk');
-
-my $uri = uri($srepospath.($spath eq '/' ? '' : $spath));
-
-my ($repospath, $path, $repos) = $xd->find_repos ('//', 1);
-ok( Pushmi::Mirror->install_hook($repospath) );
-
-my $muri = uri($repospath.($path eq '/' ? '' : $path));
-
-$svk->mirror('//', $uri);
-
-is_output($svk, 'sync', ['//'],
- ["Syncing $uri",
- 'Retrieving log information from 1 to 1',
- 'Committed revision 1 from revision 1.']);
+my ($svk,
+ $uri, $srepos, undef, undef, $scorpath,
+ $muri, $repos, undef, $copath, undef ) = build_basic_test_ok();
is_svn_output(['co', $muri, $copath],
['A t/checkout/basic-svn/A',
Modified: Pushmi/branches/lock/t/verify.t
==============================================================================
--- Pushmi/branches/lock/t/verify.t (original)
+++ Pushmi/branches/lock/t/verify.t Fri Jul 18 22:29:18 2008
@@ -30,6 +30,7 @@
$lf = $f->filename; $lf =~ s/pushmi/pushmi-log/;
copy 't/pushmi-log.conf', $lf;
+ close $f;
}
my $pid = $$;
@@ -37,33 +38,9 @@
plan tests => 8;
-my ($xd, $svk) = build_test('test');
-
-our $output;
-
-my ($srepospath, $spath, $srepos) = $xd->find_repos ('/test/', 1);
-
-$svk->mkdir('-m', 'init', '/test/A');
-
-my ($copath, $corpath) = get_copath('basic-svn');
-my ($scopath, $scorpath) = get_copath('basic-svk');
-
-my $uri = uri($srepospath.($spath eq '/' ? '' : $spath));
-
-my ($repospath, $path, $repos) = $xd->find_repos ('//', 1);
-my $depot = $xd->find_depot('');
-$depot->repos->fs->change_rev_prop(0, 'pushmi:auto-verify', '*');
-ok( Pushmi::Mirror->install_hook($repospath) );
-
-start_memcached();
-my $muri = uri($repospath.($path eq '/' ? '' : $path));
-
-$svk->mirror('//', $uri);
-
-is_output($svk, 'sync', ['//'],
- ["Syncing $uri",
- 'Retrieving log information from 1 to 1',
- 'Committed revision 1 from revision 1.']);
+my ($svk,
+ $uri, $srepos, undef, undef, $scorpath,
+ $muri, $repos, undef, $copath, undef ) = build_basic_test_ok();
is_output($svk, 'sync', ['//'],
["Syncing $uri"]);
@@ -88,6 +65,8 @@
'Retrieving log information from 3 to 3',
'Committed revision 3 from revision 3.']);
+my $depot = $svk->{xd}->find_depot('');
+$depot->repos->fs->change_rev_prop(0, 'pushmi:auto-verify', '*');
$depot->repos->fs->change_rev_prop(0, 'pushmi:inconsistent', '2');
@@ -97,9 +76,9 @@
['Sending fromsvn.txt',
'Transmitting file data .'],
['svn: Commit failed (details follow):',
- qr{svn: 'pre-commit' hook failed.*:},
- "Pushmi slave in inconsistency. Please use the master repository at $uri",
- 'and contact your administrator. Sorry for the inconveniences.', '']);
+ svn_error_commit_hook(255,
+ "Pushmi slave in inconsistency. Please use the master repository at $uri",
+ 'and contact your administrator. Sorry for the inconveniences.'), '']);
-END { return unless $$ == $pid; wait; unlink $lf }
+END { return unless $$ == $pid; wait; unlink $lf; exit 0 }
More information about the Bps-public-commit
mailing list