Skip to content

Commit

Permalink
added repo locking. fixed #44
Browse files Browse the repository at this point in the history
  • Loading branch information
krimdomu authored and jfin committed Sep 10, 2016
1 parent 43649b0 commit 6e721af
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 39 deletions.
5 changes: 5 additions & 0 deletions .perltidyrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
--ignore-side-comment-lengths
--indent-columns=2
--minimum-space-to-comment=1
--no-outdent-long-quotes
--static-side-comments
9 changes: 8 additions & 1 deletion bin/repositorio
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use Config::General;
use Log::Dispatch;
use Data::Dumper;
use Getopt::Long;
use Rex::Repositorio::Log::Screen;

use lib '/usr/lib/rex/perl/share/perl5/vendor_perl';

Expand Down Expand Up @@ -58,7 +59,7 @@ my $log_file_level = $conf{LogFileLevel} || 'info';
my $screen_level = $conf{ScreenLevel} || 'info';
$screen_level = $cli{'loglevel'} if $cli{'loglevel'};

my $log_outputs = [[ 'Screen', 'min_level' => $screen_level, stderr => 0, newline => 1, ]];
my $log_outputs = [[ '+Rex::Repositorio::Log::Screen', 'min_level' => $screen_level, stderr => 0, newline => 1, ]];
push @{$log_outputs}, [ 'File', 'min_level' => $log_file_level, filename => $log_file, newline => 1, mode => '>>'] if $log_file;
my $logger = Log::Dispatch->new(outputs => $log_outputs);

Expand All @@ -68,8 +69,14 @@ $logger->debug("Configuration Dump:");
$logger->debug( Dumper( \%conf ) );

my $app = Rex::Repositorio->new( config => \%conf, logger => $logger );
$SIG{INT} = sub { $app->exit_app(); exit(0); };

$app->run(%cli);

END {
$app->exit_app if $app;
}

__END__

=pod
Expand Down
146 changes: 108 additions & 38 deletions lib/Rex/Repositorio.pm
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ if ( !$Rex::Repositorio::VERSION ) {
$Rex::Repositorio::VERSION = "9999.99.99";
}

has config => ( is => 'ro' );
has logger => ( is => 'ro' );
our @ON_EXIT;

has config => ( is => 'ro' );
has logger => ( is => 'ro' );

sub ua {
my ( $self, %option ) = @_;
Expand All @@ -55,15 +57,18 @@ sub ua {
sub run {
my ( $self, %option ) = @_;

# this config checking/munging stuff should probably be in the 'has config' definition?
# this config checking/munging stuff should probably be in the 'has config' definition?
$self->config->{RepositoryRoot} =~ s/\/$//;
$self->logger->log_and_croak(level => 'error', message => qq/"all" is a reserved word and cannot be used as a repo name\n/)
if grep { $_ eq 'all' } keys %{ $self->config->{Repository} };
$self->logger->log_and_croak(
level => 'error',
message => qq/"all" is a reserved word and cannot be used as a repo name\n/
) if grep { $_ eq 'all' } keys %{ $self->config->{Repository} };
$self->config->{TagStyle} ||= 'TopDir';
$self->logger->log_and_croak(
level => 'error', message => sprintf "Unknown TagStyle %s, must be TopDir or BottomDir\n", $self->config->{TagStyle}
)
unless $self->config->{TagStyle} =~ m/^(?:Top|Bottom)Dir$/;
level => 'error',
message => sprintf "Unknown TagStyle %s, must be TopDir or BottomDir\n",
$self->config->{TagStyle}
) unless $self->config->{TagStyle} =~ m/^(?:Top|Bottom)Dir$/;

$self->parse_cli_option(%option);
}
Expand All @@ -77,13 +82,18 @@ sub parse_cli_option {
}

if ( exists $option{repo} ) {
$self->logger->log_and_croak(level => 'error', message => sprintf("Unknown repo: %s\n", $option{repo}))
$self->logger->log_and_croak(
level => 'error',
message => sprintf( "Unknown repo: %s\n", $option{repo} )
)
unless $option{repo} eq 'all'
or $self->config->{Repository}->{ $option{repo} };
or $self->config->{Repository}->{ $option{repo} };

$self->lock( $option{repo} );
}

if ( exists $option{mirror} && exists $option{repo} ) {
$self->logger->info("Going to mirror $option{repo} This may take a while." );
$self->logger->info("Going to mirror $option{repo} This may take a while.");

my $update_files = 1;

Expand All @@ -105,10 +115,10 @@ sub parse_cli_option {

elsif ( exists $option{tag} && exists $option{repo} ) {
$self->tag(
tag => $option{tag},
tag => $option{tag},
clonetag => $option{clonetag} || 'head',
repo => $option{repo},
force => $option{force} || 0,
repo => $option{repo},
force => $option{force} || 0,
);
}

Expand Down Expand Up @@ -147,7 +157,10 @@ sub parse_cli_option {
}

elsif ( exists $option{"remove-file"} && exists $option{repo} ) {
$self->remove_file( file => $option{"remove-file"}, repo => $option{repo} );
$self->remove_file(
file => $option{"remove-file"},
repo => $option{repo}
);
}

else {
Expand All @@ -156,6 +169,43 @@ sub parse_cli_option {
}
}

sub lock {
my $self = shift;
my $repo = shift;

open( my $fh, ">", "/tmp/repositorio.$repo.lock" );
my $flock_ok = flock( $fh, 2 );
while ( !$flock_ok ) {
$self->logger->info("Waiting for repository lock $repo");
sleep 1;
$flock_ok = flock( $fh, 2 );
}

$self->on_exit(
sub {
close $fh;
}
);
}

sub on_exit {
my $self = shift;
my $code = shift;
push @ON_EXIT, $code;
}

sub exit_app {
my $self = shift;

$self->logger->debug("Running exit code.");

for my $e (@ON_EXIT) {
$e->();
}

$self->logger->debug("Exit code finished.");
}

sub server {
my $self = shift;
my %option = validate(
Expand Down Expand Up @@ -441,34 +491,47 @@ sub tag {

# Why is this an array?
my @dirs;
push @dirs, $self->get_repo_dir(repo => $option{repo}, tag => $option{clonetag});
my $tag_dir = $self->get_repo_dir(repo => $option{repo}, tag => $option{tag});
push @dirs,
$self->get_repo_dir( repo => $option{repo}, tag => $option{clonetag} );
my $tag_dir =
$self->get_repo_dir( repo => $option{repo}, tag => $option{tag} );

$self->logger->log_and_croak(level => 'error', message => "Unknown tag $option{clonetag} on repo $option{repo} ($dirs[0])\n")
unless ( -d $dirs[0] );
$self->logger->log_and_croak(
level => 'error',
message =>
"Unknown tag $option{clonetag} on repo $option{repo} ($dirs[0])\n"
) unless ( -d $dirs[0] );

if ( -e $tag_dir ) {
if( $option{force} ) {
if ( $option{force} ) {
$self->logger->debug("Removing $tag_dir");
rmtree $tag_dir; # should be remove_tree, but will use legacy to match mkdir
}
else {
$self->logger->log_and_croak(level => 'error', message => "Tag $option{tag} on repo $option{repo} already exists (${tag_dir}), use --force\n");
$self->logger->log_and_croak(
level => 'error',
message =>
"Tag $option{tag} on repo $option{repo} already exists (${tag_dir}), use --force\n"
);
}
}

make_path($tag_dir);

for my $dir (@dirs) {
opendir my $dh, $dir
or $self->logger->log_and_croak(level => 'error', message => "Failed to open $dir: $!\nNew tag is probably unusable\n");
opendir my $dh,
$dir
or $self->logger->log_and_croak(
level => 'error',
message => "Failed to open $dir: $!\nNew tag is probably unusable\n"
);
while ( my $entry = readdir $dh ) {
next if ( $entry eq '.' || $entry eq '..' );
my $rel_entry = File::Spec->catfile($dir, $entry);
my $rel_entry = File::Spec->catfile( $dir, $entry );
$rel_entry =~ s{^$dirs[0]/}{}; # TODO use File::Spec?

my $srcfile = File::Spec->catfile($dir,$entry);
my $dstfile = File::Spec->catfile($tag_dir,$rel_entry);
my $srcfile = File::Spec->catfile( $dir, $entry );
my $dstfile = File::Spec->catfile( $tag_dir, $rel_entry );
$self->logger->debug("Tag Src: $srcfile, Dst: $dstfile");

if ( -d $srcfile ) {
Expand All @@ -478,8 +541,7 @@ sub tag {
next;
}

$self->logger->debug(
"Linking (hard): $srcfile -> $dstfile");
$self->logger->debug("Linking (hard): $srcfile -> $dstfile");
link $srcfile, $dstfile;
}
closedir $dh;
Expand All @@ -500,48 +562,56 @@ sub get_errata_dir {
}
);

if ($self->config->{TagStyle} eq 'TopDir') {
if ( $self->config->{TagStyle} eq 'TopDir' ) {
return File::Spec->catdir(
File::Spec->rel2abs( $self->config->{RepositoryRoot} ),
$option{tag}, $option{repo}, 'errata' );
}
elsif ($self->config->{TagStyle} eq 'BottomDir') {
elsif ( $self->config->{TagStyle} eq 'BottomDir' ) {
return File::Spec->catdir(
File::Spec->rel2abs( $self->config->{RepositoryRoot} ),
$option{repo}, $option{tag}, 'errata' );
}
else {
# add other styles here
$self->logger->log_and_croak(level => 'error', message => 'Shouldnt have gotten here');
$self->logger->log_and_croak(
level => 'error',
message => 'Shouldnt have gotten here'
);
}

}

sub get_repo_dir {
my $self = shift;
my $self = shift;
my %option = validate(
@_,
{
repo => {
type => SCALAR
},
tag => {
type => SCALAR,
type => SCALAR,
default => 'head',
}
}
);

my $repo_config = $self->config->{Repository}->{ $option{repo} };

if ($self->config->{TagStyle} eq 'TopDir') {
return File::Spec->catdir($self->config->{RepositoryRoot}, $option{tag}, $repo_config->{local});
if ( $self->config->{TagStyle} eq 'TopDir' ) {
return File::Spec->catdir( $self->config->{RepositoryRoot},
$option{tag}, $repo_config->{local} );
}
elsif ($self->config->{TagStyle} eq 'BottomDir') {
return File::Spec->catdir($self->config->{RepositoryRoot}, $repo_config->{local}, $option{tag});
elsif ( $self->config->{TagStyle} eq 'BottomDir' ) {
return File::Spec->catdir( $self->config->{RepositoryRoot},
$repo_config->{local}, $option{tag} );
}
else {
$self->logger->log_and_croak(level => 'error', message => 'get_repo_dir: Unknown TagStyle: '.$self->config->{TagStyle});
$self->logger->log_and_croak(
level => 'error',
message => 'get_repo_dir: Unknown TagStyle: ' . $self->config->{TagStyle}
);
}

}
Expand Down
29 changes: 29 additions & 0 deletions lib/Rex/Repositorio/Log/Screen.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package Rex::Repositorio::Log::Screen;

use base qw(Log::Dispatch::Screen);
use DateTime;

sub new {
my $proto = shift;
return $proto->SUPER::new(@_);
}

sub log_message {
my $self = shift;
my %p = @_;

my $dt = DateTime->now;

my $message =
$self->{utf8} ? encode( 'UTF-8', $p{message} ) : $p{message};
if ( $self->{stderr} ) {
print STDERR $dt->iso8601() . $dt->strftime('%Z') . " ";
print STDERR $message;
}
else {
print STDOUT $dt->iso8601() . $dt->strftime('%Z') . " ";
print STDOUT $message;
}
}

1;

0 comments on commit 6e721af

Please sign in to comment.