[Bps-public-commit] r14596 - in Pushmi/trunk: . lib/Pushmi lib/Pushmi/Command

clkao at bestpractical.com clkao at bestpractical.com
Tue Jul 29 12:14:47 EDT 2008


Author: clkao
Date: Tue Jul 29 12:14:47 2008
New Revision: 14596

Added:
   Pushmi/trunk/lib/Pushmi/Command/Runlock.pm
   Pushmi/trunk/lib/Pushmi/Command/Rununlock.pm
   Pushmi/trunk/t/lock.t
Modified:
   Pushmi/trunk/   (props changed)
   Pushmi/trunk/MANIFEST
   Pushmi/trunk/lib/Pushmi/Command.pm
   Pushmi/trunk/lib/Pushmi/Command/Runhook.pm
   Pushmi/trunk/lib/Pushmi/Mirror.pm
   Pushmi/trunk/lib/Pushmi/Test.pm

Log:
- Merge /bps/mirror/Pushmi/branches/lock to /bps/mirror/Pushmi/trunk

Modified: Pushmi/trunk/MANIFEST
==============================================================================
--- Pushmi/trunk/MANIFEST	(original)
+++ Pushmi/trunk/MANIFEST	Tue Jul 29 12:14:47 2008
@@ -21,9 +21,11 @@
 lib/Pushmi/Command/Help.pm
 lib/Pushmi/Command/Mirror.pm
 lib/Pushmi/Command/Runhook.pm
+lib/Pushmi/Command/Runlock.pm
 lib/Pushmi/Command/Sync.pm
 lib/Pushmi/Command/Tryauth.pm
 lib/Pushmi/Command/Unlock.pm
+lib/Pushmi/Command/Ununlock.pm
 lib/Pushmi/Command/Verify.pm
 lib/Pushmi/Config.pm
 lib/Pushmi/Editor/Locker.pm

Modified: Pushmi/trunk/lib/Pushmi/Command.pm
==============================================================================
--- Pushmi/trunk/lib/Pushmi/Command.pm	(original)
+++ Pushmi/trunk/lib/Pushmi/Command.pm	Tue Jul 29 12:14:47 2008
@@ -103,6 +103,10 @@
     return $SVN::_Core::SVN_NO_ERROR;
 }
 
+sub requires_svn_version {
+    my ($self, $version, $message) = @_;
+    die $message."\n" if $SVN::Core::VERSION lt $version;
+}
 
 1;
 

Modified: Pushmi/trunk/lib/Pushmi/Command/Runhook.pm
==============================================================================
--- Pushmi/trunk/lib/Pushmi/Command/Runhook.pm	(original)
+++ Pushmi/trunk/lib/Pushmi/Command/Runhook.pm	Tue Jul 29 12:14:47 2008
@@ -3,6 +3,7 @@
 use warnings;
 use base 'Pushmi::Command';
 use SVK::Editor::MapRev;
+use SVK::I18N;
 our $AUTHOR;
 
 my $logger = Pushmi::Config->logger('pushmi.runhook');
@@ -29,6 +30,26 @@
     my $t = $pushmi->root_svkpath;
     $pushmi->ensure_consistency;
 
+    my $locks;
+    if (!eof(\*STDIN)) {
+        if ((scalar <STDIN>) =~ m'^LOCKS-TOKENS:') {
+            while (<STDIN>) {
+                chomp;
+                last unless $_;
+                my ($path, $token) = split('\|', $_, 2);
+                $locks->{$path} = $token;
+            }
+
+            # turn lock path into relative
+            $locks = { map { my $token = $locks->{$_};
+                             substr($_, 0, 1, '');
+                             $_ => $token; } keys %$locks};
+        }
+    }
+
+    $self->requires_svn_version('1.6.0', loc("Commit with locks requires svn 1.6.0 on replica."))
+        if $locks;
+
     # 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");
@@ -38,6 +59,7 @@
     my ($editor, $inspector, %arg) = $t->get_editor(notee => 1,
 						    callback => sub {},
 						    caller => '',
+                                                    lock_tokens => $locks,
 						    message  => $txn->prop('svn:log'));
     my $mirror = $pushmi->master;
 

Added: Pushmi/trunk/lib/Pushmi/Command/Runlock.pm
==============================================================================
--- (empty file)
+++ Pushmi/trunk/lib/Pushmi/Command/Runlock.pm	Tue Jul 29 12:14:47 2008
@@ -0,0 +1,57 @@
+package Pushmi::Command::Runlock;
+use strict;
+use warnings;
+use base 'Pushmi::Command';
+use SVK::I18N;
+my $logger = Pushmi::Config->logger('pushmi.runlock');
+
+sub options {
+    ( 'path=s'    => 'path',
+      'user=s'    => 'user',
+      'comment=s' => 'comment',
+      'steal'     => 'steal' );
+}
+
+sub run {
+    my ($self, $repospath) = @_;
+    die "repospath required" unless $repospath;
+
+    $self->requires_svn_version('1.6.0', loc("locking requires svn 1.6.0 on replica."));
+
+    my $pushmi = Pushmi::Mirror->new( path => $repospath );
+    $pushmi->ensure_consistency;
+
+    my $t = $pushmi->root_svkpath;
+
+    my ($mirror) = $t->is_mirrored;
+    my $ra = $mirror->_backend->_new_ra;
+    my $lock_path = substr($self->{path}, 1);
+    $ra->lock({ $lock_path => -1 }, $self->{comment}, $self->{steal},
+          sub { my ($path, $locked, $lock, $err, $pool) = @_;
+                die $err->expanded_message."\n" if $err;
+                print $lock->token if $lock;
+            });
+    exit 0;
+}
+
+=head1 NAME
+
+Pushmi::Command::Runlock - svn lock preprocessing
+
+=head1 SYNOPSIS
+
+ runlock
+
+=head1 OPTIONS
+
+
+=head1 DESCRIPTION
+
+The command tries to lock the master and output the token on success
+to be used by the replica.
+
+This is not intended to be invoked manually.
+
+=cut
+
+1;

Added: Pushmi/trunk/lib/Pushmi/Command/Rununlock.pm
==============================================================================
--- (empty file)
+++ Pushmi/trunk/lib/Pushmi/Command/Rununlock.pm	Tue Jul 29 12:14:47 2008
@@ -0,0 +1,56 @@
+package Pushmi::Command::Rununlock;
+use strict;
+use warnings;
+use base 'Pushmi::Command';
+use SVK::I18N;
+my $logger = Pushmi::Config->logger('pushmi.runlock');
+
+sub options {
+    ( 'path=s'  => 'path',
+      'user=s'  => 'user',
+      'token=s' => 'token',
+      'break'   => 'break' );
+}
+
+sub run {
+    my ($self, $repospath) = @_;
+    die "repospath required" unless $repospath;
+
+    $self->requires_svn_version('1.6.0', loc("locking requires svn 1.6.0 on replica."));
+
+    my $pushmi = Pushmi::Mirror->new( path => $repospath );
+    $pushmi->ensure_consistency;
+
+    my $t = $pushmi->root_svkpath;
+
+    my ($mirror) = $t->is_mirrored;
+    my $ra = $mirror->_backend->_new_ra;
+    my $lock_path = substr($self->{path}, 1);
+    $ra->unlock({ $lock_path => $self->{token} }, $self->{break},
+          sub { my ($path, $locked, $lock, $err, $pool) = @_;
+                die $err->expanded_message."\n" if $err;
+            });
+    exit 0;
+}
+
+=head1 NAME
+
+Pushmi::Command::Rununlock - svn lock preprocessing
+
+=head1 SYNOPSIS
+
+ runlock
+
+=head1 OPTIONS
+
+
+=head1 DESCRIPTION
+
+The command tries to lock the master and output the token on success
+to be used by the replica.
+
+This is not intended to be invoked manually.
+
+=cut
+
+1;

Modified: Pushmi/trunk/lib/Pushmi/Mirror.pm
==============================================================================
--- Pushmi/trunk/lib/Pushmi/Mirror.pm	(original)
+++ Pushmi/trunk/lib/Pushmi/Mirror.pm	Tue Jul 29 12:14:47 2008
@@ -119,6 +119,28 @@
 
 END
 
+    _install_hook( $self->path, 'pre-lock', << "END");
+#!/bin/sh
+export SVKNOSVNCONFIG=1
+export PUSHMI_CONFIG=$ENV{PUSHMI_CONFIG}
+export LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}
+export DYLD_LIBRARY_PATH=$ENV{DYLD_LIBRARY_PATH}
+export PATH=$ENV{PATH}
+$perl $pushmi runlock "\$1" --path "\$2" --user "\$3" --comment "\$4" --steal "\$5"
+
+END
+
+    _install_hook( $self->path, 'pre-unlock', << "END");
+#!/bin/sh
+export SVKNOSVNCONFIG=1
+export PUSHMI_CONFIG=$ENV{PUSHMI_CONFIG}
+export LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}
+export DYLD_LIBRARY_PATH=$ENV{DYLD_LIBRARY_PATH}
+export PATH=$ENV{PATH}
+$perl $pushmi rununlock "\$1" --path "\$2" --user "\$3" --token "\$4" --break "\$5"
+
+END
+
 }
 
 sub _install_hook {

Modified: Pushmi/trunk/lib/Pushmi/Test.pm
==============================================================================
--- Pushmi/trunk/lib/Pushmi/Test.pm	(original)
+++ Pushmi/trunk/lib/Pushmi/Test.pm	Tue Jul 29 12:14:47 2008
@@ -48,15 +48,28 @@
     }
 }
 
+sub svn_cmd {
+    return $ENV{PUSHMI_SVN_COMMAND} if $ENV{PUSHMI_SVN_COMMAND};
+    return qw(arch -i386 /usr/local/bin/svn) if $^O eq 'darwin';
+    return 'svn';
+}
+
 sub is_svn_output {
     my ($arg, $exp_stdout, $exp_stderr) = @_;
     my $stdout_err = [];
     $exp_stderr ||= [];
-    my $ret = run3 ['svn', ($SVN::Core::VERSION ge '1.5.0'
+
+    my $ret = run3 [svn_cmd(), ($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
+
+    unless ($ret) {
+        diag("Exit value: $?");
+        @_ = (0, join(' ', 'svn', @$arg));
+    }
+
     if (@$stdout_err) {
 	@_ = (0, join(' ', 'svn', @$arg));
 	diag("Different in line: ".join(',', @$stdout_err));

Added: Pushmi/trunk/t/lock.t
==============================================================================
--- (empty file)
+++ Pushmi/trunk/t/lock.t	Tue Jul 29 12:14:47 2008
@@ -0,0 +1,72 @@
+#!/usr/bin/perl -w
+use strict;
+use Test::More;
+use SVK::Test;
+use Pushmi::Test;
+use Pushmi::Mirror;
+use FindBin;
+
+plan skip_all => 'requires 1.6.0 for lock'
+    if $SVN::Core::VERSION lt '1.6.0';
+
+plan tests => 21;
+
+my $user = $ENV{USER};
+
+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',
+	       'Checked out revision 1.']);
+chdir($copath);
+overwrite_file("fromsvn.txt", "orz\n");
+is_svn_output(['add', 'fromsvn.txt'],
+	      ['A         fromsvn.txt']);
+is_svn_output(['ci', -m => 'add fromsvn'],
+	      ['Adding         fromsvn.txt',
+	       'Transmitting file data .',
+	       'Committed revision 2.']);
+is($srepos->fs->youngest_rev, 2, 'committed via hook');
+
+is_svn_output(['lock', -m => 'lock from slave', 'fromsvn.txt'],
+              ["'fromsvn.txt' locked by user '$user'."]);
+my $lock = $repos->fs->get_lock('/fromsvn.txt');
+$lock = $lock->token if $lock;
+ok($lock, 'has lock on slave');
+my $lock2 = $srepos->fs->get_lock('/fromsvn.txt');
+is($lock && $lock2->comment, 'lock from slave');
+$lock2 = $lock2->token if $lock;
+ok($lock2, 'has lock on master');
+
+is($lock, $lock2, 'lock token are identical');
+
+is_svn_output(['unlock', 'fromsvn.txt'],
+              ["'fromsvn.txt' unlocked."]);
+
+ok(!$repos->fs->get_lock('/fromsvn.txt'), 'unlocked for slave');
+ok(!$srepos->fs->get_lock('/fromsvn.txt'), 'unlocked for msater');
+
+# lock from url 
+is_svn_output(['lock', -m => 'lock from slave', $muri.'/fromsvn.txt'],
+              ["'fromsvn.txt' locked by user '$user'."]);
+
+is_svn_output(['lock', -m => 'lock from slave', $uri.'/fromsvn.txt'],[],
+              [qr{svn: warning: Path '/fromsvn.txt' is already locked by user '$user' in filesystem}]);
+
+is_svn_output(['lock', -m => 'lock from slave', 'fromsvn.txt'], [],
+              [qr{svn: warning: Path '/fromsvn.txt' is already locked by user '$user' in filesystem}]);
+
+is_svn_output(['lock', -m => 'lock from slave', '--force', 'fromsvn.txt'],
+              ["'fromsvn.txt' locked by user '$user'."]);
+
+is($repos->fs->get_lock('/fromsvn.txt')->token, $srepos->fs->get_lock('/fromsvn.txt')->token, 'lock identical after stealing');
+
+is_svn_output(['lock', '--force', -m => 'lock from again', 'fromsvn.txt'],
+              ["'fromsvn.txt' locked by user '$user'."]);
+append_file('fromsvn.txt', "more content\n");
+is_svn_output(['ci', -m => 'yatta'],
+              ['Sending        fromsvn.txt',
+               'Transmitting file data .',
+               'Committed revision 3.' ], 'commit through slave holding lock, verified by master');



More information about the Bps-public-commit mailing list