Fire RepositoryImportHookEvent instead of PostReceiveRepositoryHookEvent (#1561)

We will fire an RepositoryImportHookEvent instead of PostReceiveRepositoryHookEvent for repository imports with metadata. The event is only fired if all parts of the repository could be successfully imported. The extra event is required to avoid heavy recalculations which can be triggered by the PostReceiveRepositoryHookEvent for example the scm-statistic-plugin uses the PostReceiveRepositoryHookEvent to calculate its statistics.

Co-authored-by: Eduard Heimbuch <eduard.heimbuch@cloudogu.com>
This commit is contained in:
Sebastian Sdorra
2021-02-26 09:49:34 +01:00
committed by GitHub
parent c8621061bf
commit 888f5d699b
24 changed files with 252 additions and 144 deletions

View File

@@ -26,7 +26,6 @@ package sonia.scm.repository.spi;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.Closeables;
import sonia.scm.event.ScmEventBus;
import sonia.scm.repository.Repository;
import sonia.scm.repository.SvnRepositoryHandler;
import sonia.scm.repository.SvnWorkingCopyFactory;
@@ -52,17 +51,14 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider {
private final SvnContext context;
private final SvnWorkingCopyFactory workingCopyFactory;
private final HookContextFactory hookContextFactory;
private final ScmEventBus eventBus;
SvnRepositoryServiceProvider(SvnRepositoryHandler handler,
Repository repository,
SvnWorkingCopyFactory workingCopyFactory,
HookContextFactory hookContextFactory,
ScmEventBus eventBus) {
HookContextFactory hookContextFactory) {
this.context = new SvnContext(repository, handler.getDirectory(repository.getId()));
this.workingCopyFactory = workingCopyFactory;
this.hookContextFactory = hookContextFactory;
this.eventBus = eventBus;
}
@Override
@@ -122,6 +118,6 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider {
@Override
public UnbundleCommand getUnbundleCommand() {
return new SvnUnbundleCommand(context, hookContextFactory, eventBus, new SvnLogCommand(context));
return new SvnUnbundleCommand(context, hookContextFactory, new SvnLogCommand(context));
}
}

View File

@@ -25,7 +25,6 @@
package sonia.scm.repository.spi;
import com.google.inject.Inject;
import sonia.scm.event.ScmEventBus;
import sonia.scm.plugin.Extension;
import sonia.scm.repository.Repository;
import sonia.scm.repository.SvnRepositoryHandler;
@@ -38,18 +37,14 @@ public class SvnRepositoryServiceResolver implements RepositoryServiceResolver {
private final SvnRepositoryHandler handler;
private final SvnWorkingCopyFactory workingCopyFactory;
private final HookContextFactory hookContextFactory;
private final ScmEventBus eventBus;
@Inject
public SvnRepositoryServiceResolver(SvnRepositoryHandler handler,
SvnWorkingCopyFactory workingCopyFactory,
HookContextFactory hookContextFactory,
ScmEventBus eventBus
) {
HookContextFactory hookContextFactory) {
this.handler = handler;
this.workingCopyFactory = workingCopyFactory;
this.hookContextFactory = hookContextFactory;
this.eventBus = eventBus;
}
@Override
@@ -57,7 +52,7 @@ public class SvnRepositoryServiceResolver implements RepositoryServiceResolver {
SvnRepositoryServiceProvider provider = null;
if (SvnRepositoryHandler.TYPE_NAME.equalsIgnoreCase(repository.getType())) {
provider = new SvnRepositoryServiceProvider(handler, repository, workingCopyFactory, hookContextFactory, eventBus);
provider = new SvnRepositoryServiceProvider(handler, repository, workingCopyFactory, hookContextFactory);
}
return provider;

View File

@@ -33,9 +33,7 @@ import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.wc.SVNClientManager;
import org.tmatesoft.svn.core.wc.admin.SVNAdminClient;
import sonia.scm.ContextEntry;
import sonia.scm.event.ScmEventBus;
import sonia.scm.repository.Changeset;
import sonia.scm.repository.PostReceiveRepositoryHookEvent;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryHookEvent;
import sonia.scm.repository.SvnUtil;
@@ -64,17 +62,14 @@ public class SvnUnbundleCommand extends AbstractSvnCommand implements UnbundleCo
private static final Logger LOG = LoggerFactory.getLogger(SvnUnbundleCommand.class);
private final HookContextFactory hookContextFactory;
private final ScmEventBus eventBus;
private final SvnLogCommand svnLogCommand;
public SvnUnbundleCommand(SvnContext context,
HookContextFactory hookContextFactory,
ScmEventBus eventBus,
SvnLogCommand svnLogCommand
) {
super(context);
this.hookContextFactory = hookContextFactory;
this.eventBus = eventBus;
this.svnLogCommand = svnLogCommand;
}
@@ -105,19 +100,18 @@ public class SvnUnbundleCommand extends AbstractSvnCommand implements UnbundleCo
SvnUtil.dispose(clientManager);
}
firePostReceiveRepositoryHookEvent();
fireHookEvent(request);
return response;
}
private void firePostReceiveRepositoryHookEvent() {
eventBus.post(createEvent());
private void fireHookEvent(UnbundleCommandRequest request) {
request.getPostEventSink().accept(createEvent());
}
private PostReceiveRepositoryHookEvent createEvent() {
private RepositoryHookEvent createEvent() {
Repository repository = this.context.getRepository();
HookContext context = hookContextFactory.createContext(new SvnImportHookContextProvider(repository, svnLogCommand), repository);
RepositoryHookEvent repositoryHookEvent = new RepositoryHookEvent(context, repository, POST_RECEIVE);
return new PostReceiveRepositoryHookEvent(repositoryHookEvent);
return new RepositoryHookEvent(context, repository, POST_RECEIVE);
}
private void restore(SVNAdminClient adminClient, ByteSource dump, File repository) throws SVNException, IOException {

View File

@@ -33,11 +33,10 @@ import org.mockito.Captor;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import sonia.scm.event.ScmEventBus;
import sonia.scm.repository.Changeset;
import sonia.scm.repository.Person;
import sonia.scm.repository.PostReceiveRepositoryHookEvent;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryHookEvent;
import sonia.scm.repository.RepositoryTestData;
import sonia.scm.repository.SvnUtil;
import sonia.scm.repository.api.HookChangesetBuilder;
@@ -48,30 +47,24 @@ import sonia.scm.repository.api.UnbundleResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class SvnUnbundleCommandTest extends AbstractSvnCommandTestBase {
private final Repository repository = RepositoryTestData.createHeartOfGold("svn");
private HookContextFactory hookContextFactory;
private ScmEventBus eventBus;
private SvnLogCommand logCommand;
private HookChangesetBuilder hookChangesetBuilder;
@Captor
private final ArgumentCaptor<PostReceiveRepositoryHookEvent> eventCaptor =
ArgumentCaptor.forClass(PostReceiveRepositoryHookEvent.class);
@Before
public void initMocks() {
hookContextFactory = mock(HookContextFactory.class);
eventBus = mock(ScmEventBus.class);
logCommand = mock(SvnLogCommand.class);
HookContext hookContext = mock(HookContext.class);
hookChangesetBuilder = mock(HookChangesetBuilder.class);
@@ -80,28 +73,28 @@ public class SvnUnbundleCommandTest extends AbstractSvnCommandTestBase {
}
@Test
public void shouldFirePostCommitEventAfterUnbundle() throws IOException, SVNException {
public void shouldFireRepositoryHookEventAfterUnbundle() throws IOException, SVNException {
Changeset first = new Changeset("1", 0L, new Person("trillian"), "first commit");
when(hookChangesetBuilder.getChangesetList()).thenReturn(ImmutableList.of(first));
File bundle = bundle();
SvnContext ctx = createEmptyContext();
//J-
UnbundleResponse res = new SvnUnbundleCommand(ctx, hookContextFactory, eventBus, logCommand)
.unbundle(new UnbundleCommandRequest(Files.asByteSource(bundle))
);
//J+
AtomicReference<RepositoryHookEvent> eventSink = new AtomicReference<>();
UnbundleCommandRequest request = new UnbundleCommandRequest(Files.asByteSource(bundle));
request.setPostEventSink(eventSink::set);
UnbundleResponse res = new SvnUnbundleCommand(ctx, hookContextFactory, logCommand)
.unbundle(request);
assertThat(res).isNotNull();
assertThat(res.getChangesetCount()).isEqualTo(5);
SVNRepository repo = ctx.open();
assertThat(repo.getLatestRevision()).isEqualTo(5);
verify(eventBus).post(eventCaptor.capture());
PostReceiveRepositoryHookEvent event = eventCaptor.getValue();
RepositoryHookEvent event = eventSink.get();
List<Changeset> changesets = event.getContext().getChangesetProvider().getChangesetList();
assertThat(changesets).hasSize(1);
assertThat(changesets).contains(first);
assertThat(changesets).hasSize(1).contains(first);
SvnUtil.closeSession(repo);
}