Resolved branch revision in Source Extension Point (#1803)

This adds the "resolved revision" of the HEAD (of the current branch, if branches are supported) to the extension point repos.sources.extensions. This "resolved revision" holds the current HEAD revision of the repository (or the selected branch, if branches are supported). This means you can check, whether the release has changed since an extension has been rendered for the first time.

Co-authored-by: Konstantin Schaper <konstantin.schaper@cloudogu.com>
This commit is contained in:
René Pfeuffer
2021-10-20 13:29:47 +02:00
committed by GitHub
parent d41b293109
commit 27b9d2c78a
14 changed files with 217 additions and 32 deletions

View File

@@ -24,6 +24,7 @@
package sonia.scm.repository.spi;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.tmatesoft.svn.core.SVNCommitInfo;
import org.tmatesoft.svn.core.SVNDepth;
@@ -32,6 +33,8 @@ import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.wc.SVNClientManager;
import org.tmatesoft.svn.core.wc.SVNWCClient;
import org.tmatesoft.svn.core.wc.SVNWCUtil;
import sonia.scm.ConcurrentModificationException;
import sonia.scm.ContextEntry;
import sonia.scm.repository.InternalRepositoryException;
import sonia.scm.repository.Repository;
import sonia.scm.repository.SvnWorkingCopyFactory;
@@ -43,6 +46,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.regex.Pattern;
import static sonia.scm.ContextEntry.ContextBuilder.entity;
import static sonia.scm.repository.spi.IntegrateChangesFromWorkdirException.withPattern;
public class SvnModifyCommand implements ModifyCommand {
@@ -64,6 +68,10 @@ public class SvnModifyCommand implements ModifyCommand {
SVNClientManager clientManager = SVNClientManager.newInstance();
try (WorkingCopy<File, File> workingCopy = workingCopyFactory.createWorkingCopy(context, null)) {
File workingDirectory = workingCopy.getDirectory();
if (!StringUtils.isEmpty(request.getExpectedRevision())
&& !request.getExpectedRevision().equals(getCurrentRevision(clientManager, workingCopy))) {
throw new ConcurrentModificationException(entity(repository).build());
}
if (request.isDefaultPath()) {
workingDirectory = Paths.get(workingDirectory.toString() + "/trunk").toFile();
}
@@ -72,6 +80,14 @@ public class SvnModifyCommand implements ModifyCommand {
}
}
private String getCurrentRevision(SVNClientManager clientManager, WorkingCopy<File, File> workingCopy) {
try {
return Integer.toString(clientManager.getStatusClient().doStatus(workingCopy.getWorkingRepository(), false).getRevision().getID());
} catch (SVNException e) {
throw new InternalRepositoryException(entity(repository), "Could not read status of working repository", e);
}
}
private String commitChanges(SVNClientManager clientManager, File workingDirectory, String commitMessage) {
try {
clientManager.setAuthenticationManager(SVNWCUtil.createDefaultAuthenticationManager(getCurrentUserName(), new char[0]));

View File

@@ -33,6 +33,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import sonia.scm.AlreadyExistsException;
import sonia.scm.ConcurrentModificationException;
import sonia.scm.repository.Person;
import sonia.scm.repository.work.NoneCachingWorkingCopyPool;
import sonia.scm.repository.work.WorkdirProvider;
@@ -158,4 +159,36 @@ public class SvnModifyCommandTest extends AbstractSvnCommandTestBase {
assertThat(new File(workingCopy.getWorkingRepository(), "a.txt")).exists();
assertThat(new File(workingCopy.getWorkingRepository(), "a.txt")).hasContent("");
}
@Test
public void shouldThrowExceptionIfExpectedRevisionDoesNotMatch() throws IOException {
File testfile = temporaryFolder.newFile("Test123");
ModifyCommandRequest request = new ModifyCommandRequest();
request.addRequest(new ModifyCommandRequest.CreateFileRequest("Test123", testfile, false));
request.setCommitMessage("this should not pass");
request.setAuthor(new Person("Arthur Dent", "dent@hitchhiker.com"));
request.setExpectedRevision("42");
assertThrows(ConcurrentModificationException.class, () -> svnModifyCommand.execute(request));
WorkingCopy<File, File> workingCopy = workingCopyFactory.createWorkingCopy(context, null);
assertThat(new File(workingCopy.getWorkingRepository(), "Test123")).doesNotExist();
}
@Test
@SuppressWarnings("java:S2699") // we just want to ensure that no exception is thrown
public void shouldPassIfExpectedRevisionMatchesCurrentRevision() throws IOException {
File testfile = temporaryFolder.newFile("Test123");
ModifyCommandRequest request = new ModifyCommandRequest();
request.addRequest(new ModifyCommandRequest.CreateFileRequest("Test123", testfile, false));
request.setCommitMessage("this should not pass");
request.setAuthor(new Person("Arthur Dent", "dent@hitchhiker.com"));
request.setExpectedRevision("10");
svnModifyCommand.execute(request);
// nothing to check here; we just want to ensure that no exception is thrown
}
}