Mercurial > pub > Yours
view lib/Yours/SyncRepository.pm @ 3:ae61af01bfa5
sync
author | cin |
---|---|
date | Wed, 23 Oct 2013 01:13:19 +0400 |
parents | f2a86753b494 |
children | 8001dc056331 |
line wrap: on
line source
package Yours::SyncRepository; use strict; use File::Path qw(make_path); use File::Spec(); use IMPL::Const qw(:prop); use IMPL::declare { require => { UserAgent => 'LWP::UserAgent', Exception => 'IMPL::Exception', Validator => 'Yours::FileValidator' }, base => [ 'IMPL::Object' => undef, 'IMPL::Object::Autofill' => '@_' ], props => [ agent => PROP_RO, log => PROP_RO, skipSrc => PROP_RO, skipDebug => PROP_RO, _dirs => PROP_RW, _files => PROP_RW ] }; sub CTOR { my ($this, $opts) = @_; $opts ||= {}; $this->log($opts->{log}); $this->skipSrc($opts->{skipSrc}); $this->skipDebug($opts->{skipDebug}); $this->_dirs({}); $this->_files({}); my $agent = UserAgent->new(); $agent->env_proxy; $this->agent($agent); } sub _RegisterFile { my ($this,$file,$md) = @_; my ($vol,$dir) = File::Spec->splitpath($file); make_path($dir); $this->_dirs->{$dir} = 1; $this->_files->{$file} = $md; } sub _FetchFile { my ($this,$file,$md,$dieOnError) = @_; if ($md->{size}) { $this->Log(" fetch %s [%.2fM]", $md->{location}, $md->{size}/(1024*1024)); } else { $this->Log(" fetch %s", $md->{location}); } my $resp = $this->agent->get( $md->{location}, ':content_file' => $file ); unless($resp->is_success) { $this->Log(" %s %s", $resp->code, $resp->message); die Exception->new($resp->code,$resp->message) if $dieOnError; } } sub Update { my ($this,$repo) = @_; $this->Log("Updating %s [%s]", $repo->name, $repo->repoUrl); $this->Log(" loading metadata"); my $files = $repo->GetMetadataFiles; while( my ($file,$md) = each %$files ) { $this->_RegisterFile($file,$md); $this->_FetchFile($file,$md,'die') } $this->Log(" loading description"); $files = $repo->GetDescriptionFiles; while( my ($file,$md) = each %$files ) { $this->_RegisterFile($file,$md); $this->_FetchFile($file,$md,'die') unless -f $file; } my $retry = 3; $this->Log(" validating metadata"); while(my @errors = $repo->ValidateMetadata()) { die Exception->new("Unable to complete due errors") unless $retry; $retry--; foreach my $err (@errors) { $this->Log(" %s: %s", $err->{file},$err->{message}); $this->_FetchFile($err->{file},$err->{metadata}); } } $this->Log(" downloading content"); $repo->ProcessContent(sub { my ($file,$md) = @_; return if $this->skipSrc and $md->{arch} eq 'src'; return if $this->skipDebug and $md->{name} =~ /debuginfo|debugsource/; $this->_RegisterFile($file,$md); $this->_FetchFile($file,$md) unless -f $file; }); $this->Log(" clenup"); $this->_Cleanup; $this->Log(" validate"); $retry = 3; my $validateFiles = $this->_files; while(my @errors = Validator->new()->Validate($validateFiles)) { die Exception->new("Unable to complete due errors") unless $retry; $this->Log(" attempt to fix problems"); $retry--; $validateFiles = {}; foreach my $err (@errors) { $this->Log(" %s: %s", $err->{file},$err->{message}); $this->_FetchFile($err->{file},$err->{metadata}); $validateFiles->{$err->{file}} = $err->{metadata}; } } return; } sub _Cleanup { my ($this) = @_; my $dirs = $this->_dirs; my $files = $this->_files; foreach my $dir (keys %$dirs) { if (opendir(my $hdir, $dir)) { while(my $file = readdir $hdir) { next if $file eq '.' || $file eq '..'; my $fullPath = File::Spec->catfile($dir,$file); next unless -f $fullPath; unless( $files->{$fullPath} ){ $this->Log(" - %s",$file); unlink $fullPath; } } } } } sub Repair { my ($this) = @_; } sub Log { my ($this,$format,@args) = @_; if (my $h = $this->log) { printf $h ($format,@args); print $h "\n"; } } 1;