SVN-Mirror

 view release on metacpan or  search on metacpan

lib/SVN/Mirror/Ra.pm  view on Meta::CPAN

}

sub switch {
    my ($self, $url) = @_;
    my $ra = $self->_new_ra (url => $url);
    # XXX: get proper uuid like init_state
    die "uuid is different" unless $ra->get_uuid eq $self->{source_uuid};
    # warn "===> switching from $self->{source} to $url";
    # get a txn, change rsource and rsource_uuidto new url
}

sub get_latest_rev {
    my ($self, $ra) = @_;
    # don't care about real last-modified rev num unless in skip to mode.
    return $ra->get_latest_revnum
	unless $self->{skip_to};
    my ($rev, $headrev);
    my $offset = 2;

    # there were once get_log2, but it then was refactored by the svn_ra
    # overhaul.  We have to check the version.
    # also, it's harmful to make use of the limited get_log for svn 1.2
    # vs svnserve 1.1, it retrieves all logs and leave the connection
    # in an inconsistent state.
    if ($SVN::Core::VERSION ge '1.2.0' && $self->{rsource} !~ m/^svn/) {
        $ra->get_log ([''], $ra->get_latest_revnum, 0, 1, 0, 1,
    		   sub { $rev = $_[1] });
    }
    else {
        until (defined $rev) {
	    $headrev = $ra->get_latest_revnum
		unless defined $headrev;

	    $headrev -= $offset;
	    $ra->get_log ([''], -1, $headrev,
			  ($SVN::Core::VERSION ge '1.2.0') ? (0) : (),
			  0, 1,
			  sub { $rev = $_[1] unless defined $rev});
	    if ( $offset < $headrev ) {
		$offset*=2;
	    }
	    else {
		$offset = 2;
	    }
	}
    }

    die 'fatal: unable to find last-modified revision'
	unless defined $rev;
    return $rev;
}

sub run {
    my $self = shift;
    my $ra = $self->_new_ra;
    my $latestrev = $self->get_latest_rev ($ra);

    $self->lock ('sync');
    $self->load_fromrev;
    # there were code here to use find_local_rev, but it will get base that
    # is too old for use, if there are relocate happening.
    # but this might cause race condition, while we also have lock now, need
    # to take a closer look.
    $self->{headrev} = $self->{fs}->youngest_rev;
    if ($self->{skip_to} && $self->{skip_to} =~ m/^HEAD(?:-(\d+))?/) {
	$self->{skip_to} = $latestrev - ($1 || 0);
    }
    my $startrev = ($self->{skip_to} || 0);
    $startrev = $self->{fromrev}+1 if $self->{fromrev}+1 > $startrev;
    my $endrev = shift || -1;
    if ($endrev && $endrev =~ m/^HEAD(?:-(\d+))?/) {
        $endrev = $latestrev - ($1 || 0);
    }
    $endrev = $latestrev if $endrev == -1;

    print "Syncing $self->{source}".($self->_relayed ? " via $self->{rsource}\n" : "\n");

    $self->unlock ('sync'), return
	unless $endrev == -1 || $startrev <= $endrev;

    print "Retrieving log information from $startrev to $endrev\n";

    my $firsttime = 1;
    eval {
    $ra->get_log ([''], $startrev, $endrev,
		  ($SVN::Core::VERSION ge '1.2.0') ? (0) : (),
		  1, 1,
		  sub {
		      my ($paths, $rev, $author, $date, $msg, $pool) = @_;
		      # for the first time, skip_to might not hit
		      # active revision in the tree. adjust to make it so.
		      if ($firsttime) {
			  $self->{skip_to} = $rev if defined $self->{skip_to};
			  $firsttime = 0;
		      }
		      # move the anchor detection stuff to &mirror ?
		      if (defined $self->{skip_to} && $rev <= $self->{skip_to}) {
			  # XXX: get the logs for skipped changes
			  $self->{rev_incomplete} = 1;
			  $author = 'svm';
			  $msg = sprintf('SVM: skipping changes %d-%d for %s',
					 $self->{fromrev}, $rev, $self->{rsource});
		      }
		      else {
			  delete $self->{rev_incomplete};
		      }
		      $self->mirror($self->{fromrev}, $paths, $rev, $author,
				    $date, $msg, $pool);
		      $self->{fromrev} = $rev;
		  });
    };

    delete $self->{cached_ra};
    delete $self->{cached_ra_url};

    $self->unlock ('sync');

    return unless $@;
    if ($@ =~ /no item/) {
	print "Mirror source already removed.\n";
	undef $@;



( run in 0.989 second using v1.01-cache-2.11-cpan-5511b514fd6 )