Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
eheimbuch committed May 17, 2021
1 parent 232f15e commit 91a2caa
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 61 deletions.
Expand Up @@ -24,6 +24,10 @@

package sonia.scm.repository.spi;

import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.BasicAuthenticationManager;
Expand All @@ -33,7 +37,6 @@
import org.tmatesoft.svn.core.auth.SVNSSLAuthentication;
import org.tmatesoft.svn.core.wc.SVNWCUtil;
import org.tmatesoft.svn.core.wc.admin.SVNAdminClient;
import sonia.scm.repository.InternalRepositoryException;
import sonia.scm.repository.api.MirrorCommandResult;
import sonia.scm.repository.api.Pkcs12ClientCertificateCredential;
import sonia.scm.repository.api.UsernamePasswordCredential;
Expand All @@ -44,10 +47,12 @@
import java.util.Collection;
import java.util.function.Function;

import static sonia.scm.ContextEntry.ContextBuilder.entity;
import static java.util.Collections.emptyList;

public class SvnMirrorCommand extends AbstractSvnCommand implements MirrorCommand {

private static final Logger LOG = LoggerFactory.getLogger(SvnMirrorCommand.class);

private final TrustManager trustManager;
private final Function<File, SVNURL> urlFactory;

Expand All @@ -59,19 +64,31 @@ public class SvnMirrorCommand extends AbstractSvnCommand implements MirrorComman

@Override
public MirrorCommandResult mirror(MirrorCommandRequest mirrorCommandRequest) {

Stopwatch stopwatch = Stopwatch.createStarted();
long beforeUpdate;
long afterUpdate;
try {
beforeUpdate = context.open().getLatestRevision();
SVNURL url = urlFactory.apply(context.getDirectory());

SVNURL next = SVNURL.parseURIEncoded(mirrorCommandRequest.getSourceUrl());

SVNAdminClient admin = createAdminClient(url, mirrorCommandRequest);

admin.doCompleteSynchronize(next, url);
afterUpdate = context.open().getLatestRevision();
} catch (SVNException e) {
throw new InternalRepositoryException(entity(String.class, mirrorCommandRequest.getSourceUrl()), "could not mirror svn repository", e);
LOG.error("Could not mirror svn repository", e);
return new MirrorCommandResult(false, emptyList(), stopwatch.stop().elapsed());
}
return null;
return new MirrorCommandResult(
true,
ImmutableList.of("Updated from revision " + beforeUpdate + " to revision " + afterUpdate),
stopwatch.stop().elapsed()
);
}

@Override
public MirrorCommandResult update(MirrorCommandRequest request) {
return mirror(request);
}

private SVNAdminClient createAdminClient(SVNURL url, MirrorCommandRequest mirrorCommandRequest) {
Expand Down Expand Up @@ -101,9 +118,4 @@ private SVNSSLAuthentication createTlsAuth(SVNURL url, Pkcs12ClientCertificateCr
url,
true);
}

@Override
public MirrorCommandResult update(MirrorCommandRequest mirrorCommandRequest) {
return null;
}
}
Expand Up @@ -24,78 +24,36 @@

package sonia.scm.repository.spi;

//~--- non-JDK imports --------------------------------------------------------

import org.junit.After;

import java.io.IOException;

/**
*
* @author Sebastian Sdorra
*/
public class AbstractSvnCommandTestBase extends ZippedRepositoryTestBase
{
public class AbstractSvnCommandTestBase extends ZippedRepositoryTestBase {

/**
* Method description
*
*
* @throws IOException
*/
@After
public void close() throws IOException
{
if (context != null)
{
public void close() throws IOException {
if (context != null) {
context.close();
}
}

/**
* Method description
*
*
* @return
*/
public SvnContext createContext()
{
if (context == null)
{
public SvnContext createContext() {
if (context == null) {
context = new SvnContext(repository, repositoryDirectory);
}

return context;
}

//~--- get methods ----------------------------------------------------------

/**
* Method description
*
*
* @return
*/
@Override
protected String getType()
{
protected String getType() {
return "svn";
}

/**
* Method description
*
*
* @return
*/
@Override
protected String getZippedRepositoryResource()
{
protected String getZippedRepositoryResource() {
return "sonia/scm/repository/spi/scm-svn-spi-test.zip";
}

//~--- fields ---------------------------------------------------------------

/** Field description */
private SvnContext context;
}
@@ -0,0 +1,122 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package sonia.scm.repository.spi;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import sonia.scm.repository.RepositoryTestData;
import sonia.scm.repository.api.MirrorCommandResult;
import sonia.scm.repository.api.SimpleUsernamePasswordCredential;

import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.io.IOException;
import java.util.function.Consumer;

import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;

@RunWith(MockitoJUnitRunner.class)
public class SvnMirrorCommandTest extends AbstractSvnCommandTestBase {

@Mock
private X509TrustManager trustManager;

private SvnContext emptyContext;

@Before
public void bendContextToNewRepository() throws IOException, SVNException {
emptyContext = createEmptyContext();
}

@Test
public void shouldDoInitialMirror() {
MirrorCommandResult result = callMirror(emptyContext, repositoryDirectory, c -> {
});

assertThat(result.isSuccess()).isTrue();
}

@Test
public void shouldDoMirrorUpdate() throws SVNException, IOException {
File newRepoDir = tempFolder.newFolder();
SVNRepositoryFactory.createLocalRepository(newRepoDir, true, true);
MirrorCommandResult result = callMirrorUpdate(emptyContext, createContext().getDirectory());

assertThat(result.isSuccess()).isTrue();
assertThat(result.getLog()).contains("Updated from revision 0 to revision 1");
}

@Test
public void shouldUseCredentials() throws IOException, SVNException {
File newRepoDir = tempFolder.newFolder();
SVNRepositoryFactory.createLocalRepository(newRepoDir, true, true);
MirrorCommandResult result = callMirror(emptyContext, newRepoDir, createCredential("svnadmin", "secret"));

assertThat(result.isSuccess()).isTrue();
}

private MirrorCommandResult callMirrorUpdate(SvnContext context, File source) {
MirrorCommandRequest request = new MirrorCommandRequest();
SvnMirrorCommand command = createMirrorCommand(context, source, request);
return command.update(request);
}

private MirrorCommandResult callMirror(SvnContext context, File source, Consumer<MirrorCommandRequest> consumer) {
MirrorCommandRequest request = new MirrorCommandRequest();
SvnMirrorCommand command = createMirrorCommand(context, source, request);
consumer.accept(request);
return command.mirror(request);
}

private SvnMirrorCommand createMirrorCommand(SvnContext context, File source, MirrorCommandRequest request) {
return new SvnMirrorCommand(context, trustManager, c ->
{
try {
request.setSourceUrl(SVNURL.fromFile(c).toString());
return SVNURL.fromFile(source);
} catch (SVNException e) {
throw new IllegalStateException(e);
}
});
}

private Consumer<MirrorCommandRequest> createCredential(String username, String password) {
return request -> request.setCredentials(singletonList(new SimpleUsernamePasswordCredential(username, password.toCharArray())));
}

private SvnContext createEmptyContext() throws SVNException, IOException {
File dir = tempFolder.newFolder();
SVNRepositoryFactory.createLocalRepository(dir, true, true);
return new SvnContext(RepositoryTestData.createHappyVerticalPeopleTransporter(), dir);
}

}

0 comments on commit 91a2caa

Please sign in to comment.